This patch fixes PR16458 by using the type expression attached to a reg
rtx to detect its signedness and generating unsigned compares when
appropriate.  However, we continue to use signed compares for the
special case of when we compare an unsigned reg against the constant 0.
This is because signed and unsigned compares give the same results
for equality and "(unsigned)x > 0)" is equivalent to "x != 0".
Using a signed compare in this special case allows us to continue to
generate record form instructions (ie, instructions that implicitly
set cr0).

I'll note that for the moment, I have XFAILed pr16458-4.c, since this
test case isn't working yet, but it is due to a problem in expand not
attaching any type expression information on *index's reg rtx like it
does for *a and *b in pr16458-2.c.  We're tracking that down for 4.8.

This has passed bootstrap and regtesting with no regressions.
Ok for mainline?

Peter

gcc/
        PR target/16458
        * config/rs6000/rs6000.c (rs6000_unsigned_reg_p): New function.
        (rs6000_generate_compare): Use it.

gcc/testsuite/
        PR target/16458
        * gcc.target/powerpc/pr16458-1.c: New test.
        * gcc.target/powerpc/pr16458-2.c: Likewise.
        * gcc.target/powerpc/pr16458-3.c: Likewise.
        * gcc.target/powerpc/pr16458-4.c: Likewise.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 183628)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -15588,6 +15588,22 @@ rs6000_reverse_condition (enum machine_m
     return reverse_condition (code);
 }
 
+static bool
+rs6000_unsigned_reg_p (rtx op)
+{
+  enum rtx_code code = GET_CODE (op);
+
+  if (code == REG
+      && REG_EXPR (op)
+      && TYPE_UNSIGNED (TREE_TYPE (REG_EXPR (op))))
+    return true;
+
+  if (code == SUBREG && SUBREG_PROMOTED_UNSIGNED_P (op))
+    return true;
+
+  return false;
+}
+
 /* Generate a compare for CODE.  Return a brand-new rtx that
    represents the result of the compare.  */
 
@@ -15606,14 +15622,11 @@ rs6000_generate_compare (rtx cmp, enum m
           || code == GEU || code == LEU)
     comp_mode = CCUNSmode;
   else if ((code == EQ || code == NE)
-          && GET_CODE (op0) == SUBREG
-          && GET_CODE (op1) == SUBREG
-          && SUBREG_PROMOTED_UNSIGNED_P (op0)
-          && SUBREG_PROMOTED_UNSIGNED_P (op1))
+          && rs6000_unsigned_reg_p (op0)
+          && (rs6000_unsigned_reg_p (op1)
+              || (CONST_INT_P (op1) && INTVAL (op1) != 0)))
     /* These are unsigned values, perhaps there will be a later
-       ordering compare that can be shared with this one.
-       Unfortunately we cannot detect the signedness of the operands
-       for non-subregs.  */
+       ordering compare that can be shared with this one.  */
     comp_mode = CCUNSmode;
   else
     comp_mode = CCmode;
Index: gcc/testsuite/gcc.target/powerpc/pr16458-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-1.c        (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-1.c        (revision 0)
@@ -0,0 +1,18 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-not "cmpw" } } */
+/* { dg-final { scan-assembler-times "cmplw" 1 } } */
+
+unsigned int a, b;
+
+int
+foo (void)
+{
+  if (a == b) return 1;
+  if (a > b)  return 2;
+  if (a < b)  return 3;
+  if (a != b) return 4;
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr16458-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-2.c        (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-2.c        (revision 0)
@@ -0,0 +1,18 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-not "cmpw" } } */
+/* { dg-final { scan-assembler-times "cmplw" 1 } } */
+
+unsigned int *a, *b;
+
+int
+foo (void)
+{
+  if (*a == *b) return 1;
+  if (*a > *b)  return 2;
+  if (*a < *b)  return 3;
+  if (*a != *b) return 4;
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr16458-3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-3.c        (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-3.c        (revision 0)
@@ -0,0 +1,41 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-jump-tables" } */
+
+/* { dg-final { scan-assembler-not "cmpwi" } } */
+/* { dg-final { scan-assembler-times "cmplwi" 5 } } */
+
+extern int case0 (void);
+extern int case1 (void);
+extern int case2 (void);
+extern int case3 (void);
+extern int case4 (void);
+
+enum CASE_VALUES
+{
+  CASE0 = 0,
+  CASE1,
+  CASE2,
+  CASE3,
+  CASE4
+};
+
+int
+foo (enum CASE_VALUES index)
+{
+  switch (index)
+    {
+    case CASE0:
+      return case0 ();
+    case CASE1:
+      return case1 ();
+    case CASE2:
+      return case2 ();
+    case CASE3:
+      return case3 ();
+    case CASE4:
+      return case4 ();
+    }
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/pr16458-4.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr16458-4.c        (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr16458-4.c        (revision 0)
@@ -0,0 +1,44 @@
+/* Test cse'ing of unsigned compares.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-jump-tables" } */
+
+/* The following tests fail due to an issue in expand not
+   attaching an type expression information on *index's reg rtx.  */
+
+/* { dg-final { scan-assembler-not "cmpwi" { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "cmplwi" 5 { xfail *-*-* } } } */
+
+extern int case0 (void);
+extern int case1 (void);
+extern int case2 (void);
+extern int case3 (void);
+extern int case4 (void);
+
+enum CASE_VALUES
+{
+  CASE0 = 0,
+  CASE1,
+  CASE2,
+  CASE3,
+  CASE4
+};
+
+int
+foo (enum CASE_VALUES *index)
+{
+  switch (*index)
+    {
+    case CASE0:
+      return case0 ();
+    case CASE1:
+      return case1 ();
+    case CASE2:
+      return case2 ();
+    case CASE3:
+      return case3 ();
+    case CASE4:
+      return case4 ();
+    }
+
+  return 0;
+}


Reply via email to