]> gcc.gnu.org Git - gcc.git/commitdiff
Re: [AArch64] Fix possible wrong code generation when comparing DImode values.
authorJames Greenhalgh <james.greenhalgh@arm.com>
Tue, 22 Apr 2014 10:49:48 +0000 (10:49 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Tue, 22 Apr 2014 10:49:48 +0000 (10:49 +0000)
gcc/

* config/aarch64/aarch64-simd.md
(aarch64_cm<optab>di): Always split.
(*aarch64_cm<optab>di): New.
(aarch64_cmtstdi): Always split.
(*aarch64_cmtstdi): New.

From-SVN: r209617

gcc/ChangeLog
gcc/config/aarch64/aarch64-simd.md

index e882ff81db8d7ba0aae66a925c9cb358e0a2c363..b1850b9c4f90e0ca3e6efa356bc31472e3bcb69b 100644 (file)
@@ -1,3 +1,11 @@
+2014-04-22  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * config/aarch64/aarch64-simd.md
+       (aarch64_cm<optab>di): Always split.
+       (*aarch64_cm<optab>di): New.
+       (aarch64_cmtstdi): Always split.
+       (*aarch64_cmtstdi): New.
+
 2014-04-22  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/60823
index 7fa76be9ae8e7519daaea0a2bb99dea274ffa9d4..995b4a81acd0838347965e629147d322f7351fa7 100644 (file)
          )))
      (clobber (reg:CC CC_REGNUM))]
   "TARGET_SIMD"
-  "@
-  cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
-  cm<optab>\t%d0, %d1, #0
-  #"
-  "reload_completed
-   /* We need to prevent the split from
-      happening in the 'w' constraint cases.  */
-   && GP_REGNUM_P (REGNO (operands[0]))
-   && GP_REGNUM_P (REGNO (operands[1]))"
-  [(const_int 0)]
+  "#"
+  "reload_completed"
+  [(set (match_operand:DI 0 "register_operand")
+       (neg:DI
+         (COMPARISONS:DI
+           (match_operand:DI 1 "register_operand")
+           (match_operand:DI 2 "aarch64_simd_reg_or_zero")
+         )))]
   {
-    enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
-    rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
-    rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
-    emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
-    DONE;
+    /* If we are in the general purpose register file,
+       we split to a sequence of comparison and store.  */
+    if (GP_REGNUM_P (REGNO (operands[0]))
+       && GP_REGNUM_P (REGNO (operands[1])))
+      {
+       enum machine_mode mode = SELECT_CC_MODE (<CMP>, operands[1], operands[2]);
+       rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+       rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+       emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+       DONE;
+      }
+    /* Otherwise, we expand to a similar pattern which does not
+       clobber CC_REGNUM.  */
   }
   [(set_attr "type" "neon_compare, neon_compare_zero, multiple")]
 )
 
+(define_insn "*aarch64_cm<optab>di"
+  [(set (match_operand:DI 0 "register_operand" "=w,w")
+       (neg:DI
+         (COMPARISONS:DI
+           (match_operand:DI 1 "register_operand" "w,w")
+           (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz")
+         )))]
+  "TARGET_SIMD && reload_completed"
+  "@
+  cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
+  cm<optab>\t%d0, %d1, #0"
+  [(set_attr "type" "neon_compare, neon_compare_zero")]
+)
+
 ;; cm(hs|hi)
 
 (define_insn "aarch64_cm<optab><mode>"
          )))
     (clobber (reg:CC CC_REGNUM))]
   "TARGET_SIMD"
-  "@
-  cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>
-  #"
-  "reload_completed
-   /* We need to prevent the split from
-      happening in the 'w' constraint cases.  */
-   && GP_REGNUM_P (REGNO (operands[0]))
-   && GP_REGNUM_P (REGNO (operands[1]))"
-  [(const_int 0)]
+  "#"
+  "reload_completed"
+  [(set (match_operand:DI 0 "register_operand")
+       (neg:DI
+         (UCOMPARISONS:DI
+           (match_operand:DI 1 "register_operand")
+           (match_operand:DI 2 "aarch64_simd_reg_or_zero")
+         )))]
   {
-    enum machine_mode mode = CCmode;
-    rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
-    rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
-    emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
-    DONE;
+    /* If we are in the general purpose register file,
+       we split to a sequence of comparison and store.  */
+    if (GP_REGNUM_P (REGNO (operands[0]))
+       && GP_REGNUM_P (REGNO (operands[1])))
+      {
+       enum machine_mode mode = CCmode;
+       rtx cc_reg = aarch64_gen_compare_reg (<CMP>, operands[1], operands[2]);
+       rtx comparison = gen_rtx_<CMP> (mode, operands[1], operands[2]);
+       emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+       DONE;
+      }
+    /* Otherwise, we expand to a similar pattern which does not
+       clobber CC_REGNUM.  */
   }
-  [(set_attr "type" "neon_compare, neon_compare_zero")]
+  [(set_attr "type" "neon_compare,multiple")]
+)
+
+(define_insn "*aarch64_cm<optab>di"
+  [(set (match_operand:DI 0 "register_operand" "=w")
+       (neg:DI
+         (UCOMPARISONS:DI
+           (match_operand:DI 1 "register_operand" "w")
+           (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w")
+         )))]
+  "TARGET_SIMD && reload_completed"
+  "cm<n_optab>\t%d0, %d<cmp_1>, %d<cmp_2>"
+  [(set_attr "type" "neon_compare")]
 )
 
 ;; cmtst
            (const_int 0))))
     (clobber (reg:CC CC_REGNUM))]
   "TARGET_SIMD"
-  "@
-  cmtst\t%d0, %d1, %d2
-  #"
-  "reload_completed
-   /* We need to prevent the split from
-      happening in the 'w' constraint cases.  */
-   && GP_REGNUM_P (REGNO (operands[0]))
-   && GP_REGNUM_P (REGNO (operands[1]))"
-  [(const_int 0)]
+  "#"
+  "reload_completed"
+  [(set (match_operand:DI 0 "register_operand")
+       (neg:DI
+         (ne:DI
+           (and:DI
+             (match_operand:DI 1 "register_operand")
+             (match_operand:DI 2 "register_operand"))
+           (const_int 0))))]
   {
-    rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
-    enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
-    rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
-    rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
-    emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
-    DONE;
+    /* If we are in the general purpose register file,
+       we split to a sequence of comparison and store.  */
+    if (GP_REGNUM_P (REGNO (operands[0]))
+       && GP_REGNUM_P (REGNO (operands[1])))
+      {
+       rtx and_tree = gen_rtx_AND (DImode, operands[1], operands[2]);
+       enum machine_mode mode = SELECT_CC_MODE (NE, and_tree, const0_rtx);
+       rtx cc_reg = aarch64_gen_compare_reg (NE, and_tree, const0_rtx);
+       rtx comparison = gen_rtx_NE (mode, and_tree, const0_rtx);
+       emit_insn (gen_cstoredi_neg (operands[0], comparison, cc_reg));
+       DONE;
+      }
+    /* Otherwise, we expand to a similar pattern which does not
+       clobber CC_REGNUM.  */
   }
+  [(set_attr "type" "neon_tst,multiple")]
+)
+
+(define_insn "*aarch64_cmtstdi"
+  [(set (match_operand:DI 0 "register_operand" "=w")
+       (neg:DI
+         (ne:DI
+           (and:DI
+             (match_operand:DI 1 "register_operand" "w")
+             (match_operand:DI 2 "register_operand" "w"))
+           (const_int 0))))]
+  "TARGET_SIMD"
+  "cmtst\t%d0, %d1, %d2"
   [(set_attr "type" "neon_tst")]
 )
 
This page took 0.069663 seconds and 5 git commands to generate.