From 1c50eadaae42490efff780b9b68123a952d34f57 Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Mon, 15 Apr 2013 10:43:43 +0000 Subject: [PATCH] arm.c (const_ok_for_dimode_op): Handle AND case. 2013-04-15 Kyrylo Tkachov * 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): 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 | 12 ++++++ gcc/config/arm/arm.c | 3 ++ gcc/config/arm/arm.md | 59 ++++++++++++++++++++++++++---- gcc/config/arm/constraints.md | 6 +++ gcc/config/arm/neon.md | 25 +------------ gcc/config/arm/predicates.md | 28 ++++++++------ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.target/arm/anddi3-opt.c | 11 ++++++ gcc/testsuite/gcc.target/arm/anddi3-opt2.c | 9 +++++ 9 files changed, 116 insertions(+), 42 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/anddi3-opt.c create mode 100644 gcc/testsuite/gcc.target/arm/anddi3-opt2.c 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 + + * 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): 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 * 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 "orn3_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_and3 (operands[0], operands[1], operands[2])); + emit_insn (gen_and3 (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 + + * gcc.target/arm/anddi3-opt.c: New test. + * gcc.target/arm/anddi3-opt2.c: Likewise. + 2013-04-15 Eric Botcazou * 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 \]*.+" } } */ -- 2.11.4.GIT