Thanks Richard,
I found the bug. try_eliminate_compare follows register
definitions between the flags use and the clobbering compare by
register number only, i.e. the register width isn't considered.
if (DF_REF_REGNO (def) == REGNO (in_a))
break;
This caused R1:HI to follow R0:SI causing the compare:HI (R0, so
be seen as as valid source of flags.
The following change fixes the problem while preserving the
proper behaviour.
x = single_set (insn);
if (x == NULL)
return false;
+ if( GET_MODE(x) != GET_MODE(in_a))
+ return false;
in_a = SET_SRC (x);
Cheers, Paul.
On 05/09/14 02:33, Richard Henderson wrote:
On 09/03/2014 03:14 PM, Paul Shortis wrote:
(insn 33 84 85 6 (parallel [
(set (reg:HI 1 r1)
(ashift:HI (reg:HI 1 r1)
(const_int 1 [0x1])))
(clobber (reg:CC_NOOV 7 flags))
]) ../gcc/testsuite/gcc.c-torture/execute/960311-3.c:18 33 {ashlhi3}
(insn 34 87 35 6 (set (reg:CC_NOOV 7 flags)
(compare:CC_NOOV (reg:SI 0 r0)
(const_int 0 [0])))
../gcc/testsuite/gcc.c-torture/execute/960311-3.c:20 39 {*comparesi3_nov}
(jump_insn 35 34 36 6 (set (pc)
(if_then_else (ge (reg:CC_NOOV 7 flags)
to
(insn 33 84 85 6 (parallel [
(set (reg:HI 1 r1)
(ashift:HI (reg:HI 1 r1)
(const_int 1 [0x1])))
(set (reg:CC_NOOV 7 flags)
(compare:CC_NOOV (ashift:HI (reg:HI 1 r1)
(const_int 1 [0x1]))
(const_int 0 [0])))
]) ../gcc/testsuite/gcc.c-torture/execute/960311-3.c:18 29 {ashlhi3_cc}
(jump_insn 35 87 36 6 (set (pc)
(if_then_else (ge (reg:CC_NOOV 7 flags)
(reg:HI r1) is a subreg of (reg:SI r0) however the cmpelim seems to be
substituting the compare of (reg:HI r1 and 0) for the compare of (reg:SI r0 and
0) ?
That would appear to be a bug, though I don't immediately see where.
The relevant test would appear to be
if (rtx_equal_p (SET_DEST (x), in_a))
which would not be true for (reg:SI) vs (reg:HI), whatever their regno's.
Anyway, put your breakpoint in try_eliminate_compare to debug this.
While I'm here, in i386.md some of the flag setting operations specify a mode
and some don't . Eg
(define_expand "cmp<mode>_1"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SWI48 0 "nonimmediate_operand")
That's a define_expand, not a define_insn.
(define_insn "*add<mode>_3"
[(set (reg FLAGS_REG)
(compare
The mode checks are done in the ix86_match_ccmode call inside the predicate.
r~