http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51374
--- Comment #6 from Georg-Johann Lay <gjl at gcc dot gnu.org> 2011-12-18
19:01:56 UTC ---
In combine.c:try_combine, just after the "Trying..." dump output, there is:
i0 = 0
i1 = 0
i2 =
(set (reg/v:QI 43 [ status ])
(mem/v:QI (const_int 43 [0x2b])))
i3 =
(set (pc)
(if_then_else (eq (zero_extract:QI (reg/v:QI 43 [ status ])
(const_int 1)
(const_int 4))
(const_int 0))
(label_ref:HI 16)
(pc)))
where the potential insertion is i2 into i3.
These insns are fed into can_combine_p with
src = (mem/v:QI (const_int 43))
dest = (reg/v:QI 43)
and then there is this part of an if-clause:
/* Make sure that the value that is to be substituted for the register
does not use any registers whose values alter in between. However,
If the insns are adjacent, a use can't cross a set even though we
think it might (this can happen for a sequence of insns each setting
the same destination; last_set of that register might point to
a NOTE). If INSN has a REG_EQUIV note, the register is always
equivalent to the memory so the substitution is valid even if there
are intervening stores. Also, don't move a volatile asm or
UNSPEC_VOLATILE across any other insns. */
|| (! all_adjacent
&& (((!MEM_P (src)
|| ! find_reg_note (insn, REG_EQUIV, src))
&& use_crosses_set_p (src, DF_INSN_LUID (insn)))
|| (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))
|| GET_CODE (src) == UNSPEC_VOLATILE))
In addition to these tests, the following must be disallowed:
If src contains volatile memory, then disallow moving it across:
* volatile memory
* unspec_volatile
* asm volatile
As far as I can see, use_crosses_set_p (src,...) returns 0 (false) which is
incorrect.
So either use_crosses_set_p is incorrect or it relies on incorrect data from
data flow analysis or from wherever.