summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorktkachov <ktkachov@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-15 10:43:43 +0000
committerktkachov <ktkachov@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-15 10:43:43 +0000
commitf6bbdcf62628538af217e1dfbc1d1c373af629fe (patch)
tree5d5c0f95ead98d820847ebc2339f133fefbd14ab /gcc
parent8aaed91dfc5f8fcd17fd6b61de3a6d68e59b5e1e (diff)
downloadgcc-f6bbdcf62628538af217e1dfbc1d1c373af629fe.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@197965 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/arm/arm.c3
-rw-r--r--gcc/config/arm/arm.md59
-rw-r--r--gcc/config/arm/constraints.md6
-rw-r--r--gcc/config/arm/neon.md25
-rw-r--r--gcc/config/arm/predicates.md28
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/arm/anddi3-opt.c11
-rw-r--r--gcc/testsuite/gcc.target/arm/anddi3-opt2.c9
9 files changed, 116 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d4dbb22ba25..f6d63f21db7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 27aa7986791..89affa7c8bd 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 4284535304a..913dc5f50c6 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -2162,13 +2162,58 @@
""
)
-(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"
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index 8974f4ee2ce..767ebfb6080 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -251,6 +251,12 @@
(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
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index d7c2cb36949..67f89b2fb03 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -724,29 +724,6 @@
[(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"))
@@ -5611,7 +5588,7 @@
(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;
})
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index f301df2fcdb..2e0de08a8d0 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -31,6 +31,17 @@
|| 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")
@@ -145,6 +156,12 @@
(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")
@@ -525,21 +542,10 @@
&& 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"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 98a2decdd05..efc3ded9099 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..cd0d0838632
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/anddi3-opt.c
@@ -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
index 00000000000..efe71f42ed5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/anddi3-opt2.c
@@ -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 \]*.+" } } */