From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4695 invoked by alias); 8 Aug 2006 11:12:27 -0000 Received: (qmail 4655 invoked by uid 48); 8 Aug 2006 11:12:17 -0000 Date: Tue, 08 Aug 2006 11:12:00 -0000 Message-ID: <20060808111217.4654.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug rtl-optimization/27616] [4.1/4.2 Regression] Internal error with -O1 (CSE) In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "ebotcazou at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2006-08/txt/msg00598.txt.bz2 List-Id: ------- Comment #11 from ebotcazou at gcc dot gnu dot org 2006-08-08 11:12 ------- Ugh. This is an oscillation with period 6 (not 3 as indicated in comment #3) between fold_rtx and fold_rtx_mem: #0 fold_rtx (x=0x55759dd4, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:3621 #1 0x081a640a in fold_rtx_mem (x=0x55759de0, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:3453 #2 0x081a8203 in fold_rtx (x=0x55759de0, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:3678 #3 0x081ad4d0 in fold_rtx (x=0x55759d8c, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:4283 #4 0x081a640a in fold_rtx_mem (x=0x55759d98, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:3453 #5 0x081a8203 in fold_rtx (x=0x55759d98, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:3678 #6 0x081ad4d0 in fold_rtx (x=0x55759dd4, insn=0x0) at /home/eric/svn/gcc/gcc/cse.c:4283 The fundamental problem is that fold_rtx operates recursively on its operands after equivalencing them, unlike the tree folder. More specifically: /* If we have ( ) for an associative OP and REG is known to be of similar form, we may be able to replace the operation with a combined operation. This may eliminate the intermediate operation if every use is simplified in this way. Note that the similar optimization done by combine.c only works if the intermediate operation's result has only one reference. */ This is a recipe for infinite loops and the code already contains a couple of kludges against that: /* If we have compiled a statement like "if (x == (x & mask1))", and now are looking at "x & mask2", we will have a case where the first operand of Y is the same as our first operand. Unless we detect this case, an infinite loop will result. */ if (XEXP (y, 0) == folded_arg0) break; [...] /* If Y contains our first operand (the most common way this can happen is if Y is a MEM), we would do into an infinite loop if we tried to fold it. So don't in that case. */ if (! reg_mentioned_p (folded_arg0, y)) y = fold_rtx (y, insn); I have another one for the -O1 case but it falls apart at -O2 because PRE hoists an equivalencing insn out of the extended BB under consideration. The problematic pattern is set (reg1) (plus (reg) (mem (plus (reg2) (const_int)))) set (reg2) (plus (reg) (mem (plus (reg1) (const_int)))) so in particular it defeats all the first order kludges like the above two. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27616