Jeff Law <l...@redhat.com> writes: > On 01/24/14 01:24, Richard Sandiford wrote: >> Richard Sandiford <rdsandif...@googlemail.com> writes: >>> The other problem is related to the way that MIPS16 tests for equality. >>> Conditional branches test register $24, and the only instructions that >>> set $24 are MOVE and CMP(I), which is actually an XOR rather than a >>> subtraction. >> >> Er, don't know what I was thinking here, but please ignore this summary >> of the ISA. There are conditional branches to test MIPS16 registers >> and other ways of setting $24. (But other than that...) >> >> The patch itself still stands though. > Right. This is just the RTL version of what I did for trees about a > year ago. > > The comment is a bit misleading as far as pulling things out of the RTL. > You're showing it a combined form. SET is something like > (set (reg) (xor (reg) (reg))) if I'm reading everything correctly. > > Please try to improve the comment and you're good to go. No need to > wait for further review, but please post the final form for the archivers.
Thanks, here's what I applied. Richard gcc/ * rtlanal.c (canonicalize_condition): Split out duplicated mode check. Handle XOR. gcc/testsuite/ * gcc.dg/unroll_1.c: Add -fenable-rtl-loop2. Index: gcc/rtlanal.c =================================================================== --- gcc/rtlanal.c 2014-01-23 22:27:57.176646235 +0000 +++ gcc/rtlanal.c 2014-01-25 20:00:19.952181804 +0000 @@ -5051,23 +5051,24 @@ canonicalize_condition (rtx insn, rtx co ??? This mode check should perhaps look more like the mode check in simplify_comparison in combine. */ - - if ((GET_CODE (SET_SRC (set)) == COMPARE - || (((code == NE - || (code == LT - && val_signbit_known_set_p (inner_mode, - STORE_FLAG_VALUE)) + if (((GET_MODE_CLASS (mode) == MODE_CC) + != (GET_MODE_CLASS (inner_mode) == MODE_CC)) + && mode != VOIDmode + && inner_mode != VOIDmode) + break; + if (GET_CODE (SET_SRC (set)) == COMPARE + || (((code == NE + || (code == LT + && val_signbit_known_set_p (inner_mode, + STORE_FLAG_VALUE)) #ifdef FLOAT_STORE_FLAG_VALUE - || (code == LT - && SCALAR_FLOAT_MODE_P (inner_mode) - && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode), - REAL_VALUE_NEGATIVE (fsfv))) + || (code == LT + && SCALAR_FLOAT_MODE_P (inner_mode) + && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode), + REAL_VALUE_NEGATIVE (fsfv))) #endif - )) - && COMPARISON_P (SET_SRC (set)))) - && (((GET_MODE_CLASS (mode) == MODE_CC) - == (GET_MODE_CLASS (inner_mode) == MODE_CC)) - || mode == VOIDmode || inner_mode == VOIDmode)) + )) + && COMPARISON_P (SET_SRC (set)))) x = SET_SRC (set); else if (((code == EQ || (code == GE @@ -5080,15 +5081,25 @@ canonicalize_condition (rtx insn, rtx co REAL_VALUE_NEGATIVE (fsfv))) #endif )) - && COMPARISON_P (SET_SRC (set)) - && (((GET_MODE_CLASS (mode) == MODE_CC) - == (GET_MODE_CLASS (inner_mode) == MODE_CC)) - || mode == VOIDmode || inner_mode == VOIDmode)) - + && COMPARISON_P (SET_SRC (set))) { reverse_code = 1; x = SET_SRC (set); } + else if ((code == EQ || code == NE) + && GET_CODE (SET_SRC (set)) == XOR) + /* Handle sequences like: + + (set op0 (xor X Y)) + ...(eq|ne op0 (const_int 0))... + + in which case: + + (eq op0 (const_int 0)) reduces to (eq X Y) + (ne op0 (const_int 0)) reduces to (ne X Y) + + This is the form used by MIPS16, for example. */ + x = SET_SRC (set); else break; } Index: gcc/testsuite/gcc.dg/unroll_1.c =================================================================== --- gcc/testsuite/gcc.dg/unroll_1.c 2014-01-23 22:27:57.176646235 +0000 +++ gcc/testsuite/gcc.dg/unroll_1.c 2014-01-24 17:52:54.258209196 +0000 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-rtl-loop2_unroll=stderr -fno-peel-loops -fno-tree-vrp -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2_unroll" } */ +/* { dg-options "-O2 -fdump-rtl-loop2_unroll=stderr -fno-peel-loops -fno-tree-vrp -fdisable-tree-cunroll -fdisable-tree-cunrolli -fenable-rtl-loop2 -fenable-rtl-loop2_unroll" } */ unsigned a[100], b[100]; inline void bar()