Re: Compare Elimination problems
Correction, ...compare:CC_N... (R1:HI, 0) On 05/09/14 09:31, Paul Shortis wrote: 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_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_3" [(set (reg FLAGS_REG) (compare The mode checks are done in the ix86_match_ccmode call inside the predicate. r~
Re: Compare Elimination problems
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_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_3" [(set (reg FLAGS_REG) (compare The mode checks are done in the ix86_match_ccmode call inside the predicate. r~
Re: Compare Elimination problems
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_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_3" > [(set (reg FLAGS_REG) > (compare The mode checks are done in the ix86_match_ccmode call inside the predicate. r~
Re: Compare Elimination problems
Hello! > While I'm here, in i386.md some of the flag setting operations specify a mode > and some don't . Eg > > (define_expand "cmp_1" > [(set (reg:CC FLAGS_REG) > (compare:CC (match_operand:SWI48 0 "nonimmediate_operand") > > > (define_insn "*add_3" > [(set (reg FLAGS_REG) > (compare The mode of the mode-less FLAGS_REG is checked with ix86_match_ccmode in the insn constraint. Several modes are compatible with required mode, also depending on input operands. Uros.