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/22167] [3.4 regression] Strange optimization bug when using -Os


------- Additional Comments From rsandifo at gcc dot gnu dot org  2005-07-14 13:49 -------
I think this is a bug in gcse.c:hoist_code.  It appears to date back
to when the code was first added.

The function is supposed to be doing the following:

  for each block BB
    for each expr E
      HOISTABLE := 0
A:    if (E is very busy at the end of BB
          && E is transparent at the end of BB)
        for each block BB' that is dominated by BB
          if (BB' uses E
              && a computation of E at the end of BB would reach that use)
            HOISTABLE := HOISTABLE + 1
      HOIST_EXPRS[E] := HOISTABLE > 1
    if there exists an E such that HOIST_EXPRS[E] > 0
      for each expr E
B:      if HOIST_EXPRS[E]
	  for each block BB' that is dominated by BB
	    if (BB' uses E
	        && a computation of E at the end of BB would reach that use)
	      replace the use with the reaching reg

Unfortunately, the implementation of condition B is checking the wrong
bitmap (hoist_vbeout instead of hoist_exprs).  In other words, the code
is effectively doing:

B:      if E is very busy at the end of BB

Thus hoist_code() would do nothing for a function that has no candidate
expressions with two or more suitable uses.  However, if a function
_does_ have such an expression, hoist_code() would hoist all candidate
expressions, even if they have only one use.  And it would effectively
drop the all-important "E is transparent at the end of BB" condition
when doing this.

So what happens on MIPS (and presumably powerpc) is this: we have two
candidate expressions that are of interest:

  1. (mem s.p)
  2. (high "p is 0x%x and p2 ...")

Both expressions are very busy on the output from block 0, which ends
with the call to S::init().  And both expressions have more than one
suitable use.  However, expression 1 is not entered in HOIST_EXPRS
because it is not transparent at the end of block 0.  We'd have to
insert the load _before_ the call to S::init(), and that would change
its value.  Expression 2 _is_ transparent at the end of block 0 and
so HOIST_EXPRS[2] is correctly set to true.

So we have one expression that we want to hoist -- expression 2 -- and
we therefore enter the second loop.  This then ignores the fact that
expression 1 is not transparent at the end of block 0 and hoists it
anyway.

Although I haven't checked, I think the reason this doesn't show up
on i686 is because there's no equivalent of (high ...) that would
cause the second loop to be executed.

Richard


-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
         AssignedTo|unassigned at gcc dot gnu   |rsandifo at gcc dot gnu dot
                   |dot org                     |org
             Status|NEW                         |ASSIGNED
   Last reconfirmed|2005-06-29 14:40:54         |2005-07-14 13:49:01
               date|                            |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22167


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