[AArch64] Fix unordered comparisons to floating-point vcond.
authorJames Greenhalgh <james.greenhalgh@arm.com>
Fri, 18 Jan 2013 16:34:10 +0000 (16:34 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Fri, 18 Jan 2013 16:34:10 +0000 (16:34 +0000)
gcc/
* config/aarch64/aarch64-simd.md
(aarch64_vcond_internal<mode>): Handle unordered cases.
* config/aarch64/iterators.md (v_cmp_result): New.

gcc/testsuite/
* gcc.target/aarch64/vect-fcm-gt-f.c: Change expected output.
* gcc.target/aarch64/vect-fcm-gt-d.c: Likewise.
* gcc.target/aarch64/vect-fcm-ge-f.c: Likewise.
* gcc.target/aarch64/vect-fcm-ge-d.c: Likewise.
* gcc.target/aarch64/vect-fcm-eq-f.c: Likewise.

From-SVN: r195297

gcc/ChangeLog
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/vect-fcm-eq-d.c
gcc/testsuite/gcc.target/aarch64/vect-fcm-eq-f.c
gcc/testsuite/gcc.target/aarch64/vect-fcm-ge-d.c
gcc/testsuite/gcc.target/aarch64/vect-fcm-ge-f.c
gcc/testsuite/gcc.target/aarch64/vect-fcm-gt-d.c
gcc/testsuite/gcc.target/aarch64/vect-fcm-gt-f.c

index 8d1b689862b9abb633f0d07e44efd2acc9be504e..8174a4b346b2acfebb19544ef185bd74b4e68a4a 100644 (file)
@@ -1,3 +1,9 @@
+2013-01-18  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * config/aarch64/aarch64-simd.md
+       (aarch64_vcond_internal<mode>): Handle unordered cases.
+       * config/aarch64/iterators.md (v_cmp_result): New.
+
 2013-01-18  Yi-Hsiu Hsu  <ahsu@marvell.com>
            Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
 
index 50297a907eae1f1a89a03351f5846356da59ec53..19cc87d230c9c22348fc113351934fc8b8fbcb44 100644 (file)
   "TARGET_SIMD"
 {
   int inverse = 0;
+  int swap_bsl_operands = 0;
   rtx mask = gen_reg_rtx (<V_cmp_result>mode);
+  rtx tmp = gen_reg_rtx (<V_cmp_result>mode);
 
-  if (!REG_P (operands[5])
-      && (operands[5] != CONST0_RTX (<MODE>mode)))
-    operands[5] = force_reg (<MODE>mode, operands[5]);
+  rtx (*base_comparison) (rtx, rtx, rtx);
+  rtx (*complimentary_comparison) (rtx, rtx, rtx);
+
+  switch (GET_CODE (operands[3]))
+    {
+    case GE:
+    case LE:
+    case EQ:
+      if (!REG_P (operands[5])
+         && (operands[5] != CONST0_RTX (<MODE>mode)))
+       operands[5] = force_reg (<MODE>mode, operands[5]);
+      break;
+    default:
+      if (!REG_P (operands[5]))
+       operands[5] = force_reg (<MODE>mode, operands[5]);
+    }
 
   switch (GET_CODE (operands[3]))
     {
     case LT:
+    case UNLT:
       inverse = 1;
       /* Fall through.  */
     case GE:
-      emit_insn (gen_aarch64_cmge<mode> (mask, operands[4], operands[5]));
+    case UNGE:
+    case ORDERED:
+    case UNORDERED:
+      base_comparison = gen_aarch64_cmge<mode>;
+      complimentary_comparison = gen_aarch64_cmgt<mode>;
       break;
     case LE:
+    case UNLE:
       inverse = 1;
       /* Fall through.  */
     case GT:
-      emit_insn (gen_aarch64_cmgt<mode> (mask, operands[4], operands[5]));
+    case UNGT:
+      base_comparison = gen_aarch64_cmgt<mode>;
+      complimentary_comparison = gen_aarch64_cmge<mode>;
       break;
+    case EQ:
     case NE:
-      inverse = 1;
-      /* Fall through.  */
+    case UNEQ:
+      base_comparison = gen_aarch64_cmeq<mode>;
+      complimentary_comparison = gen_aarch64_cmeq<mode>;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  switch (GET_CODE (operands[3]))
+    {
+    case LT:
+    case LE:
+    case GT:
+    case GE:
     case EQ:
-      emit_insn (gen_aarch64_cmeq<mode> (mask, operands[4], operands[5]));
+      /* The easy case.  Here we emit one of FCMGE, FCMGT or FCMEQ.
+        As a LT b <=> b GE a && a LE b <=> b GT a.  Our transformations are:
+        a GE b -> a GE b
+        a GT b -> a GT b
+        a LE b -> b GE a
+        a LT b -> b GT a
+        a EQ b -> a EQ b  */
+
+      if (!inverse)
+       emit_insn (base_comparison (mask, operands[4], operands[5]));
+      else
+       emit_insn (complimentary_comparison (mask, operands[5], operands[4]));
+      break;
+    case UNLT:
+    case UNLE:
+    case UNGT:
+    case UNGE:
+    case NE:
+      /* FCM returns false for lanes which are unordered, so if we use
+        the inverse of the comparison we actually want to emit, then
+        swap the operands to BSL, we will end up with the correct result.
+        Note that a NE NaN and NaN NE b are true for all a, b.
+
+        Our transformations are:
+        a GE b -> !(b GT a)
+        a GT b -> !(b GE a)
+        a LE b -> !(a GT b)
+        a LT b -> !(a GE b)
+        a NE b -> !(a EQ b)  */
+
+      if (inverse)
+       emit_insn (base_comparison (mask, operands[4], operands[5]));
+      else
+       emit_insn (complimentary_comparison (mask, operands[5], operands[4]));
+
+      swap_bsl_operands = 1;
+      break;
+    case UNEQ:
+      /* We check (a > b ||  b > a).  combining these comparisons give us
+        true iff !(a != b && a ORDERED b), swapping the operands to BSL
+        will then give us (a == b ||  a UNORDERED b) as intended.  */
+
+      emit_insn (gen_aarch64_cmgt<mode> (mask, operands[4], operands[5]));
+      emit_insn (gen_aarch64_cmgt<mode> (tmp, operands[5], operands[4]));
+      emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
+      swap_bsl_operands = 1;
+      break;
+    case UNORDERED:
+       /* Operands are ORDERED iff (a > b || b >= a).
+        Swapping the operands to BSL will give the UNORDERED case.  */
+     swap_bsl_operands = 1;
+     /* Fall through.  */
+    case ORDERED:
+      emit_insn (gen_aarch64_cmgt<mode> (tmp, operands[4], operands[5]));
+      emit_insn (gen_aarch64_cmge<mode> (mask, operands[5], operands[4]));
+      emit_insn (gen_ior<v_cmp_result>3 (mask, mask, tmp));
       break;
     default:
       gcc_unreachable ();
     }
 
-  if (inverse)
+  if (swap_bsl_operands)
     emit_insn (gen_aarch64_simd_bsl<mode> (operands[0], mask, operands[2],
                                    operands[1]));
   else
index 3a5749440efcc398c6b0c4e9e484f646fc72faae..b66418e30023bea611d76b8d679a34ba077ed054 100644 (file)
                                (V2SF "V2SI") (V4SF  "V4SI")
                                (V2DF "V2DI")])
 
+;; Lower case mode of results of comparison operations.
+(define_mode_attr v_cmp_result [(V8QI "v8qi") (V16QI "v16qi")
+                               (V4HI "v4hi") (V8HI  "v8hi")
+                               (V2SI "v2si") (V4SI  "v4si")
+                               (DI   "di")   (V2DI  "v2di")
+                               (V2SF "v2si") (V4SF  "v4si")
+                               (V2DF "v2di")])
+
 ;; Vm for lane instructions is restricted to FP_LO_REGS.
 (define_mode_attr vwx [(V4HI "x") (V8HI "x") (HI "x")
                       (V2SI "w") (V4SI "w") (SI "w")])
index e7045ce028c8ab24f3caca08e4cc4509ca6833d4..543f480c0f32b9e0791c47583ed8bccc75dbac5c 100644 (file)
@@ -1,3 +1,11 @@
+2013-01-18  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * gcc.target/aarch64/vect-fcm-gt-f.c: Change expected output.
+       * gcc.target/aarch64/vect-fcm-gt-d.c: Likewise.
+       * gcc.target/aarch64/vect-fcm-ge-f.c: Likewise.
+       * gcc.target/aarch64/vect-fcm-ge-d.c: Likewise.
+       * gcc.target/aarch64/vect-fcm-eq-f.c: Likewise.
+
 2013-01-17  Jeff Law  <law@redhat.com>
 
        * gcc.dg/pr52573.c: Move to...
index a177d28fedb9f1744f373c6119b18adf0ee9ac11..b6fb5ae8798849970a723e52edf2c55b5aaf1480 100644 (file)
@@ -8,7 +8,7 @@
 #include "vect-fcm.x"
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" } } */
-/* { dg-final { scan-assembler-times "fcmeq\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" 2 } } */
-/* { dg-final { scan-assembler-times "fcmeq\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 0" 1 } } */
+/* { dg-final { scan-assembler "fcmeq\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" } } */
+/* { dg-final { scan-assembler "fcmeq\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 0" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 /* { dg-final { cleanup-saved-temps } } */
index 01f388075d3e2be14c2286f28e7ad315cdca59dc..283d34fb80a234495bea5bbb987b358a5757e9ff 100644 (file)
@@ -8,7 +8,7 @@
 #include "vect-fcm.x"
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" } } */
-/* { dg-final { scan-assembler-times "fcmeq\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s" 2 } } */
-/* { dg-final { scan-assembler-times "fcmeq\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, 0" 1 } } */
+/* { dg-final { scan-assembler "fcmeq\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s" } } */
+/* { dg-final { scan-assembler "fcmeq\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, 0" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 /* { dg-final { cleanup-saved-temps } } */
index 6027593a8d45bccbb48fcc2823f1d642f244bb3d..868e1f8e60d6cdda497766da3ff116b487bc3638 100644 (file)
@@ -8,7 +8,7 @@
 #include "vect-fcm.x"
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" } } */
-/* { dg-final { scan-assembler-times "fcmge\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" 2 } } */
-/* { dg-final { scan-assembler-times "fcmge\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 0" 1 } } */
+/* { dg-final { scan-assembler "fcmge\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" } } */
+/* { dg-final { scan-assembler "fcmge\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 0" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 /* { dg-final { cleanup-saved-temps } } */
index 0337d70359c583069da42411aff141c839ca88d6..e3258f3641ebfd7679ccb9826648d6424dfba40a 100644 (file)
@@ -8,7 +8,7 @@
 #include "vect-fcm.x"
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" } } */
-/* { dg-final { scan-assembler-times "fcmge\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s" 2 } } */
-/* { dg-final { scan-assembler-times "fcmge\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, 0" 1 } } */
+/* { dg-final { scan-assembler "fcmge\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s" } } */
+/* { dg-final { scan-assembler "fcmge\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, 0" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 /* { dg-final { cleanup-saved-temps } } */
index b812a39196d24ce2047f8ab5c005368f455bfb62..ed8b452159146c8ce54980afd2b0a09992aff0d5 100644 (file)
@@ -8,7 +8,7 @@
 #include "vect-fcm.x"
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" } } */
-/* { dg-final { scan-assembler-times "fcmgt\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" 2 } } */
-/* { dg-final { scan-assembler-times "fcmgt\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 0" 1 } } */
+/* { dg-final { scan-assembler "fcmgt\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.2d" } } */
+/* { dg-final { scan-assembler "fcmgt\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, 0" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 /* { dg-final { cleanup-saved-temps } } */
index 5e012a4f4c9c6a81b352c310abb4d5c133e946f5..e90a87581d3c7f94a070bef6bf2d1d16e83d1881 100644 (file)
@@ -8,7 +8,7 @@
 #include "vect-fcm.x"
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" } } */
-/* { dg-final { scan-assembler-times "fcmgt\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s" 2 } } */
-/* { dg-final { scan-assembler-times "fcmgt\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, 0" 1 } } */
+/* { dg-final { scan-assembler "fcmgt\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s" } } */
+/* { dg-final { scan-assembler "fcmgt\\tv\[0-9\]+\.\[24\]s, v\[0-9\]+\.\[24\]s, 0" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 /* { dg-final { cleanup-saved-temps } } */