arm.c (const_ok_for_dimode_op): Handle AND case.
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 15 Apr 2013 10:43:43 +0000 (10:43 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 15 Apr 2013 10:43:43 +0000 (10:43 +0000)
2013-04-15  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

* config/arm/arm.c (const_ok_for_dimode_op): Handle AND case.
* config/arm/arm.md (*anddi3_insn): Change to insn_and_split.
* config/arm/constraints.md (De): New constraint.
* config/arm/neon.md (anddi3_neon): Delete.
(neon_vand<mode>): Expand to standard anddi3 pattern.
* config/arm/predicates.md (imm_for_neon_inv_logic_operand):
Move earlier in the file.
(neon_inv_logic_op2): Likewise.
(arm_anddi_operand_neon): New predicate.

testsuite:
* gcc.target/arm/anddi3-opt.c: New test.
* gcc.target/arm/anddi3-opt2.c: Likewise.

From-SVN: r197965

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/constraints.md
gcc/config/arm/neon.md
gcc/config/arm/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/anddi3-opt.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/anddi3-opt2.c [new file with mode: 0644]

index d4dbb22..f6d63f2 100644 (file)
@@ -1,3 +1,15 @@
+2013-04-15  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/arm/arm.c (const_ok_for_dimode_op): Handle AND case.
+       * config/arm/arm.md (*anddi3_insn): Change to insn_and_split.
+       * config/arm/constraints.md (De): New constraint.
+       * config/arm/neon.md (anddi3_neon): Delete.
+       (neon_vand<mode>): Expand to standard anddi3 pattern.
+       * config/arm/predicates.md (imm_for_neon_inv_logic_operand):
+       Move earlier in the file.
+       (neon_inv_logic_op2): Likewise.
+       (arm_anddi_operand_neon): New predicate.
+
 2013-04-15  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * configure.ac (gcc_cv_ld_as_needed): Set
index 27aa798..89affa7 100644 (file)
@@ -2646,6 +2646,9 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code)
 
   switch (code)
     {
+    case AND:
+      return (const_ok_for_op (hi_val, code) || hi_val == 0xFFFFFFFF)
+              && (const_ok_for_op (lo_val, code) || lo_val == 0xFFFFFFFF);
     case PLUS:
       return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
 
index 4284535..913dc5f 100644 (file)
   ""
 )
 
-(define_insn "*anddi3_insn"
-  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
-       (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
-               (match_operand:DI 2 "s_register_operand"   "r,r")))]
-  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
-  "#"
-  [(set_attr "length" "8")]
+(define_insn_and_split "*anddi3_insn"
+  [(set (match_operand:DI         0 "s_register_operand"     "=&r,&r,&r,&r,w,w ,?&r,?&r,?w,?w")
+       (and:DI (match_operand:DI 1 "s_register_operand"     "%0 ,r ,0,r ,w,0 ,0  ,r  ,w ,0")
+               (match_operand:DI 2 "arm_anddi_operand_neon" "r  ,r ,De,De,w,DL,r  ,r  ,w ,DL")))]
+  "TARGET_32BIT && !TARGET_IWMMXT"
+{
+  switch (which_alternative)
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 3: /* fall through */
+      return "#";
+    case 4: /* fall through */
+    case 8: return "vand\t%P0, %P1, %P2";
+    case 5: /* fall through */
+    case 9: return neon_output_logic_immediate ("vand", &operands[2],
+                    DImode, 1, VALID_NEON_QREG_MODE (DImode));
+    case 6: return "#";
+    case 7: return "#";
+    default: gcc_unreachable ();
+    }
+}
+  "TARGET_32BIT && !TARGET_IWMMXT"
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 5) (match_dup 6))]
+  "
+  {
+    operands[3] = gen_lowpart (SImode, operands[0]);
+    operands[5] = gen_highpart (SImode, operands[0]);
+
+    operands[4] = simplify_gen_binary (AND, SImode,
+                                           gen_lowpart (SImode, operands[1]),
+                                           gen_lowpart (SImode, operands[2]));
+    operands[6] = simplify_gen_binary (AND, SImode,
+                                           gen_highpart (SImode, operands[1]),
+                                           gen_highpart_mode (SImode, DImode, operands[2]));
+
+  }"
+  [(set_attr "neon_type" "*,*,*,*,neon_int_1,neon_int_1,*,*,neon_int_1,neon_int_1")
+   (set_attr "arch" "*,*,*,*,neon_for_64bits,neon_for_64bits,*,*,
+                     avoid_neon_for_64bits,avoid_neon_for_64bits")
+   (set_attr "length" "8,8,8,8,*,*,8,8,*,*")
+   (set (attr "insn_enabled") (if_then_else
+                                (lt (symbol_ref "which_alternative")
+                                    (const_int 4))
+                                (if_then_else (match_test "!TARGET_NEON")
+                                              (const_string "yes")
+                                              (const_string "no"))
+                                (if_then_else (match_test "TARGET_NEON")
+                                              (const_string "yes")
+                                              (const_string "no"))))]
 )
 
 (define_insn_and_split "*anddi_zesidi_di"
index 8974f4e..767ebfb 100644 (file)
  (and (match_code "const_int")
       (match_test "TARGET_32BIT && const_ok_for_dimode_op (ival, PLUS)")))
 
+(define_constraint "De"
+ "@internal
+  In ARM/Thumb-2 state a const_int that can be used by insn anddi."
+ (and (match_code "const_int")
+      (match_test "TARGET_32BIT && const_ok_for_dimode_op (ival, AND)")))
+
 (define_constraint "Di"
  "@internal
   In ARM/Thumb-2 state a const_int or const_double where both the high
index d7c2cb3..67f89b2 100644 (file)
   [(set_attr "neon_type" "neon_int_1")]
 )
 
-(define_insn "anddi3_neon"
-  [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r,?w,?w")
-        (and:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r,w,0")
-               (match_operand:DI 2 "neon_inv_logic_op2" "w,DL,r,r,w,DL")))]
-  "TARGET_NEON"
-{
-  switch (which_alternative)
-    {
-    case 0: /* fall through */
-    case 4: return "vand\t%P0, %P1, %P2";
-    case 1: /* fall through */
-    case 5: return neon_output_logic_immediate ("vand", &operands[2],
-                    DImode, 1, VALID_NEON_QREG_MODE (DImode));
-    case 2: return "#";
-    case 3: return "#";
-    default: gcc_unreachable ();
-    }
-}
-  [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*,neon_int_1,neon_int_1")
-   (set_attr "length" "*,*,8,8,*,*")
-   (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
-)
-
 (define_insn "orn<mode>3_neon"
   [(set (match_operand:VDQ 0 "s_register_operand" "=w")
        (ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
    (match_operand:SI 3 "immediate_operand" "")]
   "TARGET_NEON"
 {
-  emit_insn (gen_and<mode>3<V_suf64> (operands[0], operands[1], operands[2]));
+  emit_insn (gen_and<mode>3 (operands[0], operands[1], operands[2]));
   DONE;
 })
 
index f301df2..2e0de08 100644 (file)
              || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
 })
 
+(define_predicate "imm_for_neon_inv_logic_operand"
+  (match_code "const_vector")
+{
+  return (TARGET_NEON
+          && neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL));
+})
+
+(define_predicate "neon_inv_logic_op2"
+  (ior (match_operand 0 "imm_for_neon_inv_logic_operand")
+       (match_operand 0 "s_register_operand")))
+
 ;; Any hard register.
 (define_predicate "arm_hard_register_operand"
   (match_code "reg")
   (ior (match_operand 0 "arm_rhs_operand")
        (match_operand 0 "arm_neg_immediate_operand")))
 
+(define_predicate "arm_anddi_operand_neon"
+  (ior (match_operand 0 "s_register_operand")
+       (and (match_code "const_int")
+           (match_test "const_ok_for_dimode_op (INTVAL (op), AND)"))
+       (match_operand 0 "neon_inv_logic_op2")))
+
 (define_predicate "arm_adddi_operand"
   (ior (match_operand 0 "s_register_operand")
        (and (match_code "const_int")
           && neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL));
 })
 
-(define_predicate "imm_for_neon_inv_logic_operand"
-  (match_code "const_vector")
-{
-  return (TARGET_NEON
-          && neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL));
-})
-
 (define_predicate "neon_logic_op2"
   (ior (match_operand 0 "imm_for_neon_logic_operand")
        (match_operand 0 "s_register_operand")))
 
-(define_predicate "neon_inv_logic_op2"
-  (ior (match_operand 0 "imm_for_neon_inv_logic_operand")
-       (match_operand 0 "s_register_operand")))
-
 ;; Predicates for named expanders that overlap multiple ISAs.
 
 (define_predicate "cmpdi_operand"
index 98a2dec..efc3ded 100644 (file)
@@ -1,3 +1,8 @@
+2013-04-15  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * gcc.target/arm/anddi3-opt.c: New test.
+       * gcc.target/arm/anddi3-opt2.c: Likewise.
+
 2013-04-15  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.dg/pr56890-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/arm/anddi3-opt.c b/gcc/testsuite/gcc.target/arm/anddi3-opt.c
new file mode 100644 (file)
index 0000000..cd0d083
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+unsigned long long
+muld (unsigned long long X, unsigned long long Y)
+{
+  unsigned long long mask = 0xffffffffull;
+  return (X & mask) * (Y & mask);
+}
+
+/* { dg-final { scan-assembler-not "and\[\\t \]+.+,\[\\t \]*.+,\[\\t \]*.+" } } */
diff --git a/gcc/testsuite/gcc.target/arm/anddi3-opt2.c b/gcc/testsuite/gcc.target/arm/anddi3-opt2.c
new file mode 100644 (file)
index 0000000..efe71f4
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+long long muld(long long X, long long Y)
+{
+  return X & ~1;
+}
+
+/* { dg-final { scan-assembler-not "and\[\\t \]+.+,\[\\t \]*.+,\[\\t \]*.+" } } */