This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug rtl-optimization/27616] [4.1/4.2 Regression] Internal error with -O1 (CSE)



------- 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 (<op> <reg> <const_int>) 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]