* config/rs6000/predicates.md (rs6000_cbranch_operator): Accept some
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 31 May 2013 19:12:05 +0000 (19:12 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 31 May 2013 19:12:05 +0000 (19:12 +0000)
unordered comparison operators when -fno-trapping-math is in effect
on the e500.
* config/rs6000/rs6000.c (rs6000_generate_compare): Remove dead code
and implement unordered comparison operators properly on the e500.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199557 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/e500-ord-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/e500-ord-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/e500-unord-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/e500-unord-2.c [new file with mode: 0644]

index 0894c50..2ec1dcc 100644 (file)
@@ -1,5 +1,13 @@
 2013-05-31  Eric Botcazou  <ebotcazou@adacore.com>
 
+       * config/rs6000/predicates.md (rs6000_cbranch_operator): Accept some
+       unordered comparison operators when -fno-trapping-math is in effect
+       on the e500.
+       * config/rs6000/rs6000.c (rs6000_generate_compare): Remove dead code
+       and implement unordered comparison operators properly on the e500.
+
+2013-05-31  Eric Botcazou  <ebotcazou@adacore.com>
+
        * simplify-rtx.c (simplify_byte_swapping_operation): Use proper macro
        for constant scalar integers.
        (simplify_relational_operation_1): Likewise.
index 078c938..7fdf7d1 100644 (file)
                                                   GET_MODE (XEXP (op, 0))),
                          1"))))
 
+;; Return 1 if OP is a valid comparison operator for "cbranch" instructions.
+;; If we're assuming that FP operations cannot generate user-visible traps,
+;; then on e500 we can use the ordered-signaling instructions to implement
+;; the unordered-quiet FP comparison predicates modulo a reversal.
 (define_predicate "rs6000_cbranch_operator"
   (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS")
-               (match_operand 0 "ordered_comparison_operator")
+               (if_then_else (match_test "flag_trapping_math")
+                             (match_operand 0 "ordered_comparison_operator")
+                             (ior (match_operand 0 "ordered_comparison_operator")
+                                  (match_code ("unlt,unle,ungt,unge"))))
                (match_operand 0 "comparison_operator")))
 
 ;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
index cb68760..9c4b7f0 100644 (file)
@@ -16087,16 +16087,41 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
     {
       rtx cmp, or_result, compare_result2;
       enum machine_mode op_mode = GET_MODE (op0);
+      bool reverse_p;
 
       if (op_mode == VOIDmode)
        op_mode = GET_MODE (op1);
 
+      /* First reverse the condition codes that aren't directly supported.  */
+      switch (code)
+       {
+         case NE:
+         case UNLT:
+         case UNLE:
+         case UNGT:
+         case UNGE:
+           code = reverse_condition_maybe_unordered (code);
+           reverse_p = true;
+           break;
+
+         case EQ:
+         case LT:
+         case LE:
+         case GT:
+         case GE:
+           reverse_p = false;
+           break;
+
+         default:
+           gcc_unreachable ();
+       }
+
       /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only.
         This explains the following mess.  */
 
       switch (code)
        {
-       case EQ: case UNEQ: case NE: case LTGT:
+       case EQ:
          switch (op_mode)
            {
            case SFmode:
@@ -16122,7 +16147,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
            }
          break;
 
-       case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
+       case GT:
+       case GE:
          switch (op_mode)
            {
            case SFmode:
@@ -16148,7 +16174,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
            }
          break;
 
-       case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
+       case LT: 
+       case LE:
          switch (op_mode)
            {
            case SFmode:
@@ -16173,24 +16200,16 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
              gcc_unreachable ();
            }
          break;
+
         default:
           gcc_unreachable ();
        }
 
       /* Synthesize LE and GE from LT/GT || EQ.  */
-      if (code == LE || code == GE || code == LEU || code == GEU)
+      if (code == LE || code == GE)
        {
          emit_insn (cmp);
 
-         switch (code)
-           {
-           case LE: code = LT; break;
-           case GE: code = GT; break;
-           case LEU: code = LT; break;
-           case GEU: code = GT; break;
-           default: gcc_unreachable ();
-           }
-
          compare_result2 = gen_reg_rtx (CCFPmode);
 
          /* Do the EQ.  */
@@ -16217,23 +16236,18 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
            default:
              gcc_unreachable ();
            }
+
          emit_insn (cmp);
 
          /* OR them together.  */
          or_result = gen_reg_rtx (CCFPmode);
          cmp = gen_e500_cr_ior_compare (or_result, compare_result,
-                                          compare_result2);
+                                        compare_result2);
          compare_result = or_result;
-         code = EQ;
-       }
-      else
-       {
-         if (code == NE || code == LTGT)
-           code = NE;
-         else
-           code = EQ;
        }
 
+      code = reverse_p ? NE : EQ;
+
       emit_insn (cmp);
     }
   else
index b46c378..fb6c694 100644 (file)
@@ -1,3 +1,10 @@
+2013-05-31  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.target/powerpc/e500-ord-1.c: New test.
+       * gcc.target/powerpc/e500-ord-2.c: Likewise.
+       * gcc.target/powerpc/e500-unord-1.c: Likewise.
+       * gcc.target/powerpc/e500-unord-2.c: Likewise.
+
 2013-05-31  Marcus Shawcroft  <marcus.shawcroft@arm.com>
 
        * g++.dg/torture/pr54684.C: Add -fno-short-enums.
diff --git a/gcc/testsuite/gcc.target/powerpc/e500-ord-1.c b/gcc/testsuite/gcc.target/powerpc/e500-ord-1.c
new file mode 100644 (file)
index 0000000..c4f2769
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile { target powerpc*-*-eabi* } } */
+/* { dg-options "-O -ftrapping-math -fdump-rtl-final" } */
+
+int isgreater (float f1, float f2)
+{
+  int r = (f1 > f2);
+  return !r ?  -1 : 1;
+}
+
+int isgreaterequal (float f1, float f2)
+{
+  int r = (f1 >= f2);
+  return !r ?  -1 : 1;
+}
+
+int isless (float f1, float f2)
+{
+  int r = (f1 < f2);
+  return !r ?  -1 : 1;
+}
+
+int islessequal (float f1, float f2)
+{
+  int r = (f1 <= f2);
+  return !r ?  -1 : 1;
+}
+
+/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */
+/* { dg-final { cleanup-rtl-dump "final" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/e500-ord-2.c b/gcc/testsuite/gcc.target/powerpc/e500-ord-2.c
new file mode 100644 (file)
index 0000000..a6b5c29
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile { target powerpc*-*-eabi* } } */
+/* { dg-options "-O -fno-trapping-math -fdump-rtl-final" } */
+
+int isgreater (float f1, float f2)
+{
+  int r = (f1 > f2);
+  return !r ?  -1 : 1;
+}
+
+int isgreaterequal (float f1, float f2)
+{
+  int r = (f1 >= f2);
+  return !r ?  -1 : 1;
+}
+
+int isless (float f1, float f2)
+{
+  int r = (f1 < f2);
+  return !r ?  -1 : 1;
+}
+
+int islessequal (float f1, float f2)
+{
+  int r = (f1 <= f2);
+  return !r ?  -1 : 1;
+}
+
+/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */
+/* { dg-final { cleanup-rtl-dump "final" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/e500-unord-1.c b/gcc/testsuite/gcc.target/powerpc/e500-unord-1.c
new file mode 100644 (file)
index 0000000..0cd75d8
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile { target powerpc*-*-eabi* } } */
+/* { dg-options "-O -ftrapping-math -fdump-rtl-final" } */
+
+int isgreater (float f1, float f2)
+{
+  int r = __builtin_isgreater (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+int isgreaterequal (float f1, float f2)
+{
+  int r = __builtin_isgreaterequal (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+int isless (float f1, float f2)
+{
+  int r = __builtin_isless (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+int islessequal (float f1, float f2)
+{
+  int r = __builtin_islessequal (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+/* { dg-final { scan-rtl-dump-times "__unordsf2" 4 "final" } } */
+/* { dg-final { cleanup-rtl-dump "final" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/e500-unord-2.c b/gcc/testsuite/gcc.target/powerpc/e500-unord-2.c
new file mode 100644 (file)
index 0000000..51b1316
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile { target powerpc*-*-eabi* } } */
+/* { dg-options "-O -fno-trapping-math -fdump-rtl-final" } */
+
+int isgreater (float f1, float f2)
+{
+  int r = __builtin_isgreater (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+int isgreaterequal (float f1, float f2)
+{
+  int r = __builtin_isgreaterequal (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+int isless (float f1, float f2)
+{
+  int r = __builtin_isless (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+int islessequal (float f1, float f2)
+{
+  int r = __builtin_islessequal (f1, f2);
+  return !r ?  -1 : 1;
+}
+
+/* { dg-final { scan-rtl-dump-not "__unordsf2" "final" } } */
+/* { dg-final { cleanup-rtl-dump "final" } } */