This patch fixes gcc.dg/unroll_1.c for MIPS16.  There were two problems,
one in the testcase itself and one in the rtl code.

The testcase problem was that gcc.dg/unroll_1.c forces loop2_unroll to
be run via -fenable-rtl-loop2_unroll but it doesn't explicitly force the
associated init pass (loop2) to be run as well.  This only happens because
-fmove-loop-invariants is usually the default for -O2.  It isn't the default
on MIPS16 though, so neither loop2 nor loop2_unroll were being run.  The
patch adds an explicit -fenable-rtl-loop2 to get around this.

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.  So branches for equality typically look like:

       (set (reg:SI cond) (xor:SI (reg:SI X) (const_int Y)))
       (set (pc)
            (if_then_else (eq (reg:SI cond) (const_int 0))
                          (label_ref ...)
                          (pc)))

get_condition didn't recognise this form and so loop-iv.c couldn't
figure out the number of iterations.

I fixed that by handling (eq (xor ...) (const_int 0)) and
(ne (xor ...) (const_int 0)) in canonicalize_condition, in a similar
way to (compare ...).

The existing (compare ...) conditions both test:

             ((GET_MODE_CLASS (mode) == MODE_CC)
               != (GET_MODE_CLASS (inner_mode) == MODE_CC))
              && mode != VOIDmode
              && inner_mode != VOIDmode)

with the comment:

          /* ??? We may not combine comparisons done in a CCmode with
             comparisons not done in a CCmode.  This is to aid targets
             like Alpha that have an IEEE compliant EQ instruction, and
             a non-IEEE compliant BEQ instruction.  The use of CCmode is
             actually artificial, simply to prevent the combination, but
             should not affect other platforms.

             However, we must allow VOIDmode comparisons to match either
             CCmode or non-CCmode comparison, because some ports have
             modeless comparisons inside branch patterns.

             ??? This mode check should perhaps look more like the mode check
             in simplify_comparison in combine.  */

The IEEE thing obviously isn't a worry for XOR, but it still seemed more
consistent to handle all cases in the same way.  I therefore split the
condition out into a separate test.

Tested on mips64-linux-gnu.  OK to install?

Thanks,
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 19:12:05.089232340 +0000
+++ gcc/rtlanal.c       2014-01-23 19:12:15.168333561 +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,18 @@ 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)
+           /* (eq (xor X Y) (const_int 0)) -> (eq X Y)
+              (ne (xor X Y) (const_int 0)) -> (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 19:12:05.089232340 +0000
+++ gcc/testsuite/gcc.dg/unroll_1.c     2014-01-23 19:12:15.185333731 +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()

Reply via email to