Commit 1c50eada by Kyrylo Tkachov Committed by Kyrylo Tkachov

arm.c (const_ok_for_dimode_op): Handle AND case.

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
parent e927b6ad
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> 2013-04-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (gcc_cv_ld_as_needed): Set * configure.ac (gcc_cv_ld_as_needed): Set
......
...@@ -2646,6 +2646,9 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code) ...@@ -2646,6 +2646,9 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code code)
switch (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: case PLUS:
return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode); return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
......
...@@ -2162,13 +2162,58 @@ ...@@ -2162,13 +2162,58 @@
"" ""
) )
(define_insn "*anddi3_insn" (define_insn_and_split "*anddi3_insn"
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r") [(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") (and:DI (match_operand:DI 1 "s_register_operand" "%0 ,r ,0,r ,w,0 ,0 ,r ,w ,0")
(match_operand:DI 2 "s_register_operand" "r,r")))] (match_operand:DI 2 "arm_anddi_operand_neon" "r ,r ,De,De,w,DL,r ,r ,w ,DL")))]
"TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON" "TARGET_32BIT && !TARGET_IWMMXT"
"#" {
[(set_attr "length" "8")] 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" (define_insn_and_split "*anddi_zesidi_di"
......
...@@ -251,6 +251,12 @@ ...@@ -251,6 +251,12 @@
(and (match_code "const_int") (and (match_code "const_int")
(match_test "TARGET_32BIT && const_ok_for_dimode_op (ival, PLUS)"))) (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" (define_constraint "Di"
"@internal "@internal
In ARM/Thumb-2 state a const_int or const_double where both the high In ARM/Thumb-2 state a const_int or const_double where both the high
......
...@@ -724,29 +724,6 @@ ...@@ -724,29 +724,6 @@
[(set_attr "neon_type" "neon_int_1")] [(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" (define_insn "orn<mode>3_neon"
[(set (match_operand:VDQ 0 "s_register_operand" "=w") [(set (match_operand:VDQ 0 "s_register_operand" "=w")
(ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w")) (ior:VDQ (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))
...@@ -5611,7 +5588,7 @@ ...@@ -5611,7 +5588,7 @@
(match_operand:SI 3 "immediate_operand" "")] (match_operand:SI 3 "immediate_operand" "")]
"TARGET_NEON" "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; DONE;
}) })
......
...@@ -31,6 +31,17 @@ ...@@ -31,6 +31,17 @@
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); || 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. ;; Any hard register.
(define_predicate "arm_hard_register_operand" (define_predicate "arm_hard_register_operand"
(match_code "reg") (match_code "reg")
...@@ -145,6 +156,12 @@ ...@@ -145,6 +156,12 @@
(ior (match_operand 0 "arm_rhs_operand") (ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "arm_neg_immediate_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" (define_predicate "arm_adddi_operand"
(ior (match_operand 0 "s_register_operand") (ior (match_operand 0 "s_register_operand")
(and (match_code "const_int") (and (match_code "const_int")
...@@ -525,21 +542,10 @@ ...@@ -525,21 +542,10 @@
&& neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL)); && 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" (define_predicate "neon_logic_op2"
(ior (match_operand 0 "imm_for_neon_logic_operand") (ior (match_operand 0 "imm_for_neon_logic_operand")
(match_operand 0 "s_register_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. ;; Predicates for named expanders that overlap multiple ISAs.
(define_predicate "cmpdi_operand" (define_predicate "cmpdi_operand"
......
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> 2013-04-15 Eric Botcazou <ebotcazou@adacore.com>
* gcc.dg/pr56890-1.c: New test. * gcc.dg/pr56890-1.c: New test.
......
/* { 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 \]*.+" } } */
/* { 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 \]*.+" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment