------- 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