From: Sudakshina Das Date: Wed, 4 Oct 2017 16:59:40 +0000 (+0000) Subject: [PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ab6501d713bb9de29609bd99b40da3f479e504b6;p=gcc.git [PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern This patch adds the support for BIC (vector, immediate) and ORR (vector, immediate) SIMD patterns to the AArch64 backend. Committed on behalf of Sudi Das. Reviewed-by: Richard Earnshaw Reviewed-by: James Greenhalgh gcc/ * config/aarch64/aarch64-protos.h (enum simd_immediate_check): New check type for aarch64_simd_valid_immediate. (aarch64_output_simd_mov_immediate): Update prototype. (aarch64_simd_valid_immediate): Update prototype. * config/aarch64/aarch64-simd.md (orr3): modified pattern to add support for ORR-immediate. (and3): modified pattern to add support for BIC-immediate. * config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function now checks for valid immediate for BIC and ORR based on new enum argument. (aarch64_output_simd_mov_immediate): Function now used to output BIC/ORR imm as well based on new enum argument. * config/aarch64/constraints.md (Do): New vector immediate constraint. (Db) : Likewise. * config/aarch64/predicates.md (aarch64_reg_or_orr_imm): New predicate. (aarch64_reg_or_bic_imm): Likewise. gcc/testsuite/ * gcc.target/aarch64/bic_imm_1.c: New test. * gcc.target/aarch64/orr_imm_1.c: Likewise. From-SVN: r253422 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d8a9bc1e75b..2046e349a80 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2017-10-04 Sudakshina Das + + * config/aarch64/aarch64-protos.h (enum simd_immediate_check): New + check type for aarch64_simd_valid_immediate. + (aarch64_output_simd_mov_immediate): Update prototype. + (aarch64_simd_valid_immediate): Update prototype. + * config/aarch64/aarch64-simd.md (orr3): modified pattern to add + support for ORR-immediate. + (and3): modified pattern to add support for BIC-immediate. + * config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function + now checks for valid immediate for BIC and ORR based on new enum + argument. + (aarch64_output_simd_mov_immediate): Function now used to output + BIC/ORR imm as well based on new enum argument. + * config/aarch64/constraints.md (Do): New vector immediate constraint. + (Db) : Likewise. + * config/aarch64/predicates.md (aarch64_reg_or_orr_imm): New predicate. + (aarch64_reg_or_bic_imm): Likewise. + 2017-10-04 Andreas Krebbel * config/s390/vx-builtins.md ("vec_mergeh") diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index e67c2ed5e80..5d7c5dfc690 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -308,6 +308,16 @@ enum aarch64_parse_opt_result AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */ }; +/* Enum to distinguish which type of check is to be done in + aarch64_simd_valid_immediate. This is used as a bitmask where + AARCH64_CHECK_MOV has both bits set. Thus AARCH64_CHECK_MOV will + perform all checks. Adding new types would require changes accordingly. */ +enum simd_immediate_check { + AARCH64_CHECK_ORR = 1 << 0, + AARCH64_CHECK_BIC = 1 << 1, + AARCH64_CHECK_MOV = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC +}; + extern struct tune_params aarch64_tune_params; HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned); @@ -345,7 +355,8 @@ bool aarch64_mov_operand_p (rtx, machine_mode); rtx aarch64_reverse_mask (machine_mode); bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT); char *aarch64_output_scalar_simd_mov_immediate (rtx, scalar_int_mode); -char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned); +char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned, + enum simd_immediate_check w = AARCH64_CHECK_MOV); bool aarch64_pad_reg_upward (machine_mode, const_tree, bool); bool aarch64_regno_ok_for_base_p (int, bool); bool aarch64_regno_ok_for_index_p (int, bool); @@ -356,7 +367,8 @@ bool aarch64_simd_imm_zero_p (rtx, machine_mode); bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode); bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool); bool aarch64_simd_valid_immediate (rtx, machine_mode, bool, - struct simd_immediate_info *); + struct simd_immediate_info *, + enum simd_immediate_check w = AARCH64_CHECK_MOV); bool aarch64_split_dimode_const_store (rtx, rtx); bool aarch64_symbolic_address_p (rtx); bool aarch64_uimm12_shift (HOST_WIDE_INT); diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 70e9339e275..12da8be73e8 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -558,21 +558,45 @@ [(set_attr "type" "neon_fp_abd_")] ) +;; For AND (vector, register) and BIC (vector, immediate) (define_insn "and3" - [(set (match_operand:VDQ_I 0 "register_operand" "=w") - (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w") - (match_operand:VDQ_I 2 "register_operand" "w")))] + [(set (match_operand:VDQ_I 0 "register_operand" "=w,w") + (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0") + (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm" "w,Db")))] "TARGET_SIMD" - "and\t%0., %1., %2." + { + switch (which_alternative) + { + case 0: + return "and\t%0., %1., %2."; + case 1: + return aarch64_output_simd_mov_immediate (operands[2], + mode, GET_MODE_BITSIZE (mode), AARCH64_CHECK_BIC); + default: + gcc_unreachable (); + } + } [(set_attr "type" "neon_logic")] ) +;; For ORR (vector, register) and ORR (vector, immediate) (define_insn "ior3" - [(set (match_operand:VDQ_I 0 "register_operand" "=w") - (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w") - (match_operand:VDQ_I 2 "register_operand" "w")))] + [(set (match_operand:VDQ_I 0 "register_operand" "=w,w") + (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0") + (match_operand:VDQ_I 2 "aarch64_reg_or_orr_imm" "w,Do")))] "TARGET_SIMD" - "orr\t%0., %1., %2." + { + switch (which_alternative) + { + case 0: + return "orr\t%0., %1., %2."; + case 1: + return aarch64_output_simd_mov_immediate (operands[2], + mode, GET_MODE_BITSIZE (mode), AARCH64_CHECK_ORR); + default: + gcc_unreachable (); + } + } [(set_attr "type" "neon_logic")] ) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index e89c8156976..ee98a1f8228 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -11483,7 +11483,8 @@ aarch64_vect_float_const_representable_p (rtx x) /* Return true for valid and false for invalid. */ bool aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse, - struct simd_immediate_info *info) + struct simd_immediate_info *info, + enum simd_immediate_check which) { #define CHECK(STRIDE, ELSIZE, CLASS, TEST, SHIFT, NEG) \ matches = 1; \ @@ -11551,54 +11552,65 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse, do { - CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0 - && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0); + if (which & AARCH64_CHECK_ORR) + { + CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0 + && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0); - CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1] - && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0); + CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1] + && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0); - CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0 - && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0); + CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0 + && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0); - CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0 - && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0); + CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0 + && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0); - CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0); + CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0); - CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0); + CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0); + } - CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff - && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1); + if (which & AARCH64_CHECK_BIC) + { + CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff + && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1); - CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1] - && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1); + CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1] + && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1); - CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff - && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1); + CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff + && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1); - CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff - && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1); + CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff + && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1); - CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1); + CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1); - CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1); + CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1); + } - CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1] - && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0); + /* Shifting ones / 8-bit / 64-bit variants only checked + for 'ALL' (MOVI/MVNI). */ + if (which == AARCH64_CHECK_MOV) + { + CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1] + && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0); - CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1] - && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1); + CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1] + && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1); - CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff - && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0); + CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff + && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0); - CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0 - && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1); + CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0 + && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1); - CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0); + CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0); - CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff) - && bytes[i] == bytes[(i + 8) % idx], 0, 0); + CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff) + && bytes[i] == bytes[(i + 8) % idx], 0, 0); + } } while (0); @@ -13000,10 +13012,14 @@ aarch64_float_const_representable_p (rtx x) return (exponent >= 0 && exponent <= 7); } +/* Returns the string with the instruction for AdvSIMD MOVI, MVNI, ORR or BIC + immediate with a CONST_VECTOR of MODE and WIDTH. WHICH selects whether to + output MOVI/MVNI, ORR or BIC immediate. */ char* aarch64_output_simd_mov_immediate (rtx const_vector, machine_mode mode, - unsigned width) + unsigned width, + enum simd_immediate_check which) { bool is_valid; static char templ[40]; @@ -13015,9 +13031,11 @@ aarch64_output_simd_mov_immediate (rtx const_vector, struct simd_immediate_info info = { NULL_RTX, 0, 0, false, false }; /* This will return true to show const_vector is legal for use as either - a AdvSIMD MOVI instruction (or, implicitly, MVNI) immediate. It will - also update INFO to show how the immediate should be generated. */ - is_valid = aarch64_simd_valid_immediate (const_vector, mode, false, &info); + a AdvSIMD MOVI instruction (or, implicitly, MVNI), ORR or BIC immediate. + It will also update INFO to show how the immediate should be generated. + WHICH selects whether to check for MOVI/MVNI, ORR or BIC. */ + is_valid = aarch64_simd_valid_immediate (const_vector, mode, false, + &info, which); gcc_assert (is_valid); element_char = sizetochar (info.element_width); @@ -13048,20 +13066,37 @@ aarch64_output_simd_mov_immediate (rtx const_vector, } } - mnemonic = info.mvn ? "mvni" : "movi"; - shift_op = info.msl ? "msl" : "lsl"; - gcc_assert (CONST_INT_P (info.value)); - if (lane_count == 1) - snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX, - mnemonic, UINTVAL (info.value)); - else if (info.shift) - snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX - ", %s %d", mnemonic, lane_count, element_char, - UINTVAL (info.value), shift_op, info.shift); + + if (which == AARCH64_CHECK_MOV) + { + mnemonic = info.mvn ? "mvni" : "movi"; + shift_op = info.msl ? "msl" : "lsl"; + if (lane_count == 1) + snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX, + mnemonic, UINTVAL (info.value)); + else if (info.shift) + snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " + HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count, + element_char, UINTVAL (info.value), shift_op, info.shift); + else + snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " + HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count, + element_char, UINTVAL (info.value)); + } else - snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX, - mnemonic, lane_count, element_char, UINTVAL (info.value)); + { + /* For AARCH64_CHECK_BIC and AARCH64_CHECK_ORR. */ + mnemonic = info.mvn ? "bic" : "orr"; + if (info.shift) + snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" + HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count, + element_char, UINTVAL (info.value), "lsl", info.shift); + else + snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" + HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count, + element_char, UINTVAL (info.value)); + } return templ; } diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 3649fb48a33..77c510cea0d 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -190,6 +190,20 @@ (and (match_code "const_double") (match_test "aarch64_can_const_movi_rtx_p (op, GET_MODE (op))"))) +(define_constraint "Do" + "@internal + A constraint that matches vector of immediates for orr." + (and (match_code "const_vector") + (match_test "aarch64_simd_valid_immediate (op, mode, false, + NULL, AARCH64_CHECK_ORR)"))) + +(define_constraint "Db" + "@internal + A constraint that matches vector of immediates for bic." + (and (match_code "const_vector") + (match_test "aarch64_simd_valid_immediate (op, mode, false, + NULL, AARCH64_CHECK_BIC)"))) + (define_constraint "Dn" "@internal A constraint that matches vector of immediates." diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 11243c4ce00..887a13ee4f1 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -69,6 +69,16 @@ (ior (match_test "op == constm1_rtx") (match_test "op == const1_rtx")))))) +(define_predicate "aarch64_reg_or_orr_imm" + (ior (match_operand 0 "register_operand") + (match_test "aarch64_simd_valid_immediate (op, mode, false, + NULL, AARCH64_CHECK_ORR)"))) + +(define_predicate "aarch64_reg_or_bic_imm" + (ior (match_operand 0 "register_operand") + (match_test "aarch64_simd_valid_immediate (op, mode, false, + NULL, AARCH64_CHECK_BIC)"))) + (define_predicate "aarch64_fp_compare_operand" (ior (match_operand 0 "register_operand") (and (match_code "const_double") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 26ca5563af4..da8358ced9e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-10-04 Sudakshina Das + + * gcc.target/aarch64/bic_imm_1.c: New. + * gcc.target/aarch64/orr_imm_1.c: Likewise. + 2017-10-04 Nathan Sidwell * g++.dg/abi/mangle41.C: Adjust diagnostics.