[ARM] Rewrite vc<cond> NEON patterns to use RTL operations rather than UNSPECs
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Thu, 23 Apr 2015 16:19:26 +0000 (16:19 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Thu, 23 Apr 2015 16:19:26 +0000 (16:19 +0000)
* config/arm/iterators.md (GTGE, GTUGEU, COMPARISONS): New code
iterators.
(cmp_op, cmp_type): New code attributes.
(NEON_VCMP, NEON_VACMP): New int iterators.
(cmp_op_unsp): New int attribute.
* config/arm/neon.md (neon_vc<cmp_op><mode>): New define_expand.
(neon_vceq<mode>): Delete.
(neon_vc<cmp_op><mode>_insn): New pattern.
(neon_vc<cmp_op_unsp><mode>_insn_unspec): Likewise.
(neon_vcgeu<mode>): Delete.
(neon_vcle<mode>): Likewise.
(neon_vclt<mode>: Likewise.
(neon_vcage<mode>): Likewise.
(neon_vcagt<mode>): Likewise.
(neon_vca<cmp_op><mode>): New define_expand.
(neon_vca<cmp_op><mode>_insn): New pattern.
(neon_vca<cmp_op_unsp><mode>_insn_unspec): Likewise.

* gcc.target/arm/neon/pr51534.c: Update vcg* scan-assembly patterns
to look for vcl* where appropriate.

From-SVN: r222379

gcc/ChangeLog
gcc/config/arm/iterators.md
gcc/config/arm/neon.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/neon/pr51534.c

index 2d2b97a0bac00de3d1c0b1f30b3087f73dbecf8e..d36bae7c25171dc3e81611af5a9666841d52130e 100644 (file)
@@ -1,3 +1,23 @@
+2015-04-23  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/arm/iterators.md (GTGE, GTUGEU, COMPARISONS): New code
+       iterators.
+       (cmp_op, cmp_type): New code attributes.
+       (NEON_VCMP, NEON_VACMP): New int iterators.
+       (cmp_op_unsp): New int attribute.
+       * config/arm/neon.md (neon_vc<cmp_op><mode>): New define_expand.
+       (neon_vceq<mode>): Delete.
+       (neon_vc<cmp_op><mode>_insn): New pattern.
+       (neon_vc<cmp_op_unsp><mode>_insn_unspec): Likewise.
+       (neon_vcgeu<mode>): Delete.
+       (neon_vcle<mode>): Likewise.
+       (neon_vclt<mode>: Likewise.
+       (neon_vcage<mode>): Likewise.
+       (neon_vcagt<mode>): Likewise.
+       (neon_vca<cmp_op><mode>): New define_expand.
+       (neon_vca<cmp_op><mode>_insn): New pattern.
+       (neon_vca<cmp_op_unsp><mode>_insn_unspec): Likewise.
+
 2015-04-23  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-icf.c (sem_item::compare_attributes): New function.
index f7f8ab7f0d64489bef7dea94762437649327b8ef..66f3f4d7d9fe7843ea1ec279d539019c4a52b5df 100644 (file)
 ;; compare a second time.
 (define_code_iterator LTUGEU [ltu geu])
 
+;; The signed gt, ge comparisons
+(define_code_iterator GTGE [gt ge])
+
+;; The unsigned gt, ge comparisons
+(define_code_iterator GTUGEU [gtu geu])
+
+;; Comparisons for vc<cmp>
+(define_code_iterator COMPARISONS [eq gt ge le lt])
+
 ;; A list of ...
 (define_code_iterator ior_xor [ior xor])
 
 (define_code_attr arith_shift_insn
   [(plus "add") (minus "rsb") (ior "orr") (xor "eor") (and "and")])
 
+(define_code_attr cmp_op [(eq "eq") (gt "gt") (ge "ge") (lt "lt") (le "le")
+                          (gtu "gt") (geu "ge")])
+
+(define_code_attr cmp_type [(eq "i") (gt "s") (ge "s") (lt "s") (le "s")])
+
 ;;----------------------------------------------------------------------------
 ;; Int iterators
 ;;----------------------------------------------------------------------------
 (define_int_iterator VRINT [UNSPEC_VRINTZ UNSPEC_VRINTP UNSPEC_VRINTM
                             UNSPEC_VRINTR UNSPEC_VRINTX UNSPEC_VRINTA])
 
+(define_int_iterator NEON_VCMP [UNSPEC_VCEQ UNSPEC_VCGT UNSPEC_VCGE UNSPEC_VCLT UNSPEC_VCLE])
+
+(define_int_iterator NEON_VACMP [UNSPEC_VCAGE UNSPEC_VCAGT])
+
 (define_int_iterator VCVT [UNSPEC_VRINTP UNSPEC_VRINTM UNSPEC_VRINTA])
 
 (define_int_iterator NEON_VRINT [UNSPEC_NVRINTP UNSPEC_NVRINTZ UNSPEC_NVRINTM
 
 ])
 
+(define_int_attr cmp_op_unsp [(UNSPEC_VCEQ "eq") (UNSPEC_VCGT "gt")
+                              (UNSPEC_VCGE "ge") (UNSPEC_VCLE "le")
+                              (UNSPEC_VCLT "lt") (UNSPEC_VCAGE "ge")
+                              (UNSPEC_VCAGT "gt")])
+
 (define_int_attr r [
   (UNSPEC_VRHADD_S "r") (UNSPEC_VRHADD_U "r")
   (UNSPEC_VHADD_S "") (UNSPEC_VHADD_U "")
index 63c327ec68cacc85446c2c4aa3bf99eee9ebe074..445df2ad0bd631cbf00f5a966e46e1e829ab6918 100644 (file)
   [(set_attr "type" "neon_sub_halve_narrow_q")]
 )
 
-(define_insn "neon_vceq<mode>"
-  [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
-        (unspec:<V_cmp_result>
-         [(match_operand:VDQW 1 "s_register_operand" "w,w")
-          (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")]
-          UNSPEC_VCEQ))]
+;; These may expand to an UNSPEC pattern when a floating point mode is used
+;; without unsafe math optimizations.
+(define_expand "neon_vc<cmp_op><mode>"
+  [(match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
+     (neg:<V_cmp_result>
+       (COMPARISONS:VDQW (match_operand:VDQW 1 "s_register_operand" "w,w")
+                         (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")))]
   "TARGET_NEON"
-  "@
-  vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
-  vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, #0"
-  [(set (attr "type")
-      (if_then_else (match_test "<Is_float_mode>")
-                    (const_string "neon_fp_compare_s<q>")
-                    (if_then_else (match_operand 2 "zero_operand")
-                      (const_string "neon_compare_zero<q>")
-                      (const_string "neon_compare<q>"))))]
+  {
+    /* For FP comparisons use UNSPECS unless -funsafe-math-optimizations
+       are enabled.  */
+    if (GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT
+        && !flag_unsafe_math_optimizations)
+      {
+        /* We don't just emit a gen_neon_vc<cmp_op><mode>_insn_unspec because
+           we define gen_neon_vceq<mode>_insn_unspec only for float modes
+           whereas this expander iterates over the integer modes as well,
+           but we will never expand to UNSPECs for the integer comparisons.  */
+        switch (<MODE>mode)
+          {
+            case V2SFmode:
+              emit_insn (gen_neon_vc<cmp_op>v2sf_insn_unspec (operands[0],
+                                                              operands[1],
+                                                              operands[2]));
+              break;
+            case V4SFmode:
+              emit_insn (gen_neon_vc<cmp_op>v4sf_insn_unspec (operands[0],
+                                                              operands[1],
+                                                              operands[2]));
+              break;
+            default:
+              gcc_unreachable ();
+          }
+      }
+    else
+      emit_insn (gen_neon_vc<cmp_op><mode>_insn (operands[0],
+                                                 operands[1],
+                                                 operands[2]));
+    DONE;
+  }
 )
 
-(define_insn "neon_vcge<mode>"
+(define_insn "neon_vc<cmp_op><mode>_insn"
   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
-        (unspec:<V_cmp_result>
-         [(match_operand:VDQW 1 "s_register_operand" "w,w")
-          (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")]
-          UNSPEC_VCGE))]
-  "TARGET_NEON"
-  "@
-  vcge.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
-  vcge.<V_s_elem>\t%<V_reg>0, %<V_reg>1, #0"
+        (neg:<V_cmp_result>
+          (COMPARISONS:<V_cmp_result>
+            (match_operand:VDQW 1 "s_register_operand" "w,w")
+            (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz"))))]
+  "TARGET_NEON && !(GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT
+                    && !flag_unsafe_math_optimizations)"
+  {
+    char pattern[100];
+    sprintf (pattern, "vc<cmp_op>.%s%%#<V_sz_elem>\t%%<V_reg>0,"
+                      " %%<V_reg>1, %s",
+                       GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT
+                         ? "f" : "<cmp_type>",
+                       which_alternative == 0
+                         ? "%<V_reg>2" : "#0");
+    output_asm_insn (pattern, operands);
+    return "";
+  }
   [(set (attr "type")
-     (if_then_else (match_test "<Is_float_mode>")
-                   (const_string "neon_fp_compare_s<q>")
-                    (if_then_else (match_operand 2 "zero_operand")
+        (if_then_else (match_operand 2 "zero_operand")
                       (const_string "neon_compare_zero<q>")
-                      (const_string "neon_compare<q>"))))]
-)
-
-(define_insn "neon_vcgeu<mode>"
-  [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
-        (unspec:<V_cmp_result>
-         [(match_operand:VDQIW 1 "s_register_operand" "w")
-          (match_operand:VDQIW 2 "s_register_operand" "w")]
-          UNSPEC_VCGEU))]
-  "TARGET_NEON"
-  "vcge.u%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
-  [(set_attr "type" "neon_compare<q>")]
+                      (const_string "neon_compare<q>")))]
 )
 
-(define_insn "neon_vcgt<mode>"
+(define_insn "neon_vc<cmp_op_unsp><mode>_insn_unspec"
   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
         (unspec:<V_cmp_result>
-         [(match_operand:VDQW 1 "s_register_operand" "w,w")
-          (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")]
-          UNSPEC_VCGT))]
+         [(match_operand:VCVTF 1 "s_register_operand" "w,w")
+          (match_operand:VCVTF 2 "reg_or_zero_operand" "w,Dz")]
+          NEON_VCMP))]
   "TARGET_NEON"
-  "@
-  vcgt.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2
-  vcgt.<V_s_elem>\t%<V_reg>0, %<V_reg>1, #0"
-  [(set (attr "type")
-     (if_then_else (match_test "<Is_float_mode>")
-                   (const_string "neon_fp_compare_s<q>")
-                    (if_then_else (match_operand 2 "zero_operand")
-                      (const_string "neon_compare_zero<q>")
-                      (const_string "neon_compare<q>"))))]
+  {
+    char pattern[100];
+    sprintf (pattern, "vc<cmp_op_unsp>.f%%#<V_sz_elem>\t%%<V_reg>0,"
+                       " %%<V_reg>1, %s",
+                       which_alternative == 0
+                         ? "%<V_reg>2" : "#0");
+    output_asm_insn (pattern, operands);
+    return "";
+}
+  [(set_attr "type" "neon_fp_compare_s<q>")]
 )
 
-(define_insn "neon_vcgtu<mode>"
+(define_insn "neon_vc<cmp_op>u<mode>"
   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
-        (unspec:<V_cmp_result>
-         [(match_operand:VDQIW 1 "s_register_operand" "w")
-          (match_operand:VDQIW 2 "s_register_operand" "w")]
-          UNSPEC_VCGTU))]
+        (neg:<V_cmp_result>
+          (GTUGEU:<V_cmp_result>
+           (match_operand:VDQIW 1 "s_register_operand" "w")
+           (match_operand:VDQIW 2 "s_register_operand" "w"))))]
   "TARGET_NEON"
-  "vcgt.u%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+  "vc<cmp_op>.u%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
   [(set_attr "type" "neon_compare<q>")]
 )
 
-;; VCLE and VCLT only support comparisons with immediate zero (register
-;; variants are VCGE and VCGT with operands reversed).
-
-(define_insn "neon_vcle<mode>"
-  [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
-        (unspec:<V_cmp_result>
-         [(match_operand:VDQW 1 "s_register_operand" "w")
-          (match_operand:VDQW 2 "zero_operand" "Dz")]
-          UNSPEC_VCLE))]
+(define_expand "neon_vca<cmp_op><mode>"
+  [(set (match_operand:<V_cmp_result> 0 "s_register_operand")
+        (neg:<V_cmp_result>
+          (GTGE:<V_cmp_result>
+            (abs:VCVTF (match_operand:VCVTF 1 "s_register_operand"))
+            (abs:VCVTF (match_operand:VCVTF 2 "s_register_operand")))))]
   "TARGET_NEON"
-  "vcle.<V_s_elem>\t%<V_reg>0, %<V_reg>1, #0"
-  [(set (attr "type")
-      (if_then_else (match_test "<Is_float_mode>")
-                    (const_string "neon_fp_compare_s<q>")
-                    (if_then_else (match_operand 2 "zero_operand")
-                      (const_string "neon_compare_zero<q>")
-                      (const_string "neon_compare<q>"))))]
-)
-
-(define_insn "neon_vclt<mode>"
-  [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
-        (unspec:<V_cmp_result>
-         [(match_operand:VDQW 1 "s_register_operand" "w")
-          (match_operand:VDQW 2 "zero_operand" "Dz")]
-          UNSPEC_VCLT))]
-  "TARGET_NEON"
-  "vclt.<V_s_elem>\t%<V_reg>0, %<V_reg>1, #0"
-  [(set (attr "type")
-      (if_then_else (match_test "<Is_float_mode>")
-                    (const_string "neon_fp_compare_s<q>")
-                    (if_then_else (match_operand 2 "zero_operand")
-                      (const_string "neon_compare_zero<q>")
-                      (const_string "neon_compare<q>"))))]
+  {
+    if (flag_unsafe_math_optimizations)
+      emit_insn (gen_neon_vca<cmp_op><mode>_insn (operands[0], operands[1],
+                                                  operands[2]));
+    else
+      emit_insn (gen_neon_vca<cmp_op><mode>_insn_unspec (operands[0],
+                                                         operands[1],
+                                                         operands[2]));
+    DONE;
+  }
 )
 
-(define_insn "neon_vcage<mode>"
+(define_insn "neon_vca<cmp_op><mode>_insn"
   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
-        (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
-                               (match_operand:VCVTF 2 "s_register_operand" "w")]
-                               UNSPEC_VCAGE))]
-  "TARGET_NEON"
-  "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+        (neg:<V_cmp_result>
+          (GTGE:<V_cmp_result>
+            (abs:VCVTF (match_operand:VCVTF 1 "s_register_operand" "w"))
+            (abs:VCVTF (match_operand:VCVTF 2 "s_register_operand" "w")))))]
+  "TARGET_NEON && flag_unsafe_math_optimizations"
+  "vac<cmp_op>.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
   [(set_attr "type" "neon_fp_compare_s<q>")]
 )
 
-(define_insn "neon_vcagt<mode>"
+(define_insn "neon_vca<cmp_op_unsp><mode>_insn_unspec"
   [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w")
         (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w")
                                (match_operand:VCVTF 2 "s_register_operand" "w")]
-                               UNSPEC_VCAGT))]
+                               NEON_VACMP))]
   "TARGET_NEON"
-  "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+  "vac<cmp_op_unsp>.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
   [(set_attr "type" "neon_fp_compare_s<q>")]
 )
 
index ff96f59b5f105f8b667855713bd3de73758183c4..2a0850fb2e4ae7b8de321ae11024e232802ee7e5 100644 (file)
@@ -1,3 +1,8 @@
+2015-04-23  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * gcc.target/arm/neon/pr51534.c: Update vcg* scan-assembly patterns
+       to look for vcl* where appropriate.
+
 2015-04-23  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * gcc.dg/vect/costmodel/ppc/costmodel-bb-slp-9a.c: Replace
index 71cbb055f1667df57e9092433b535b3a567e0fa2..074bbd42040497d18d561767a431d65d63a2d0c7 100644 (file)
@@ -58,18 +58,18 @@ GEN_COND_TESTS(vceq)
 /* { dg-final { scan-assembler-times "vcge\.u16\[      \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" 2 } } */
 /* { dg-final { scan-assembler "vcge\.s32\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
 /* { dg-final { scan-assembler-times "vcge\.u32\[      \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" 2 } } */
-/* { dg-final { scan-assembler "vcgt\.s8\[     \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcgt\.s16\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcgt\.s32\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcgt\.s8\[     \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcgt\.s16\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcgt\.s32\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcge\.s8\[     \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcge\.s16\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcge\.s32\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, \[dD\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcge\.s8\[     \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcge\.s16\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" } } */
-/* { dg-final { scan-assembler "vcge\.s32\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+" } } */
+/* { dg-final { scan-assembler "vclt\.s8\[     \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vclt\.s16\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vclt\.s32\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vclt\.s8\[     \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vclt\.s16\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vclt\.s32\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vcle\.s8\[     \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vcle\.s16\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vcle\.s32\[    \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vcle\.s8\[     \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vcle\.s16\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
+/* { dg-final { scan-assembler "vcle\.s32\[    \]+\[qQ\]\[0-9\]+, \[qQ\]\[0-9\]+, #0" } } */
 /* { dg-final { scan-assembler-times "vceq\.i8\[       \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" 2 } } */
 /* { dg-final { scan-assembler-times "vceq\.i16\[      \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" 2 } } */
 /* { dg-final { scan-assembler-times "vceq\.i32\[      \]+\[dD\]\[0-9\]+, \[dD\]\[0-9\]+, #0" 2 } } */