https://gcc.gnu.org/g:756890d66cf4971fc11187ccdf5893681aa661a1
commit r15-4568-g756890d66cf4971fc11187ccdf5893681aa661a1 Author: Wilco Dijkstra <wilco.dijks...@arm.com> Date: Tue Oct 8 15:55:25 2024 +0000 AArch64: Improve SIMD immediate generation (2/3) Allow use of SVE immediates when generating AdvSIMD code and SVE is available. First check for a valid AdvSIMD immediate, and if SVE is available, try using an SVE move or bitmask immediate. gcc/ChangeLog: * config/aarch64/aarch64-simd.md (ior<mode>3<vczle><vczbe>): Use aarch64_reg_or_orr_imm predicate. Combine SVE/AdvSIMD immediates and use aarch64_output_simd_orr_imm. * config/aarch64/aarch64.cc (struct simd_immediate_info): Add SVE_MOV. (aarch64_sve_valid_immediate): Use SVE_MOV for SVE move immediates. (aarch64_simd_valid_imm): Enable SVE SIMD immediates when possible. (aarch64_output_simd_imm): Support emitting SVE SIMD immediates. * config/aarch64/predicates.md (aarch64_orr_imm_sve_advsimd): Remove. gcc/testsuite/ChangeLog: * gcc.target/aarch64/sve/acle/asm/insr_s64.c: Allow SVE MOV imm. * gcc.target/aarch64/sve/acle/asm/insr_u64.c: Likewise. * gcc.target/aarch64/sve/fneg-abs_1.c: Update to check for ORRI. * gcc.target/aarch64/sve/fneg-abs_2.c: Likewise. * gcc.target/aarch64/sve/simd_imm_mov.c: New test. Diff: --- gcc/config/aarch64/aarch64-simd.md | 10 +++--- gcc/config/aarch64/aarch64.cc | 41 +++++++++++++++++----- gcc/config/aarch64/predicates.md | 5 --- .../gcc.target/aarch64/sve/acle/asm/insr_s64.c | 4 +-- .../gcc.target/aarch64/sve/acle/asm/insr_u64.c | 4 +-- gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_1.c | 6 ++-- gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_2.c | 4 +-- .../gcc.target/aarch64/sve/simd_imm_mov.c | 39 ++++++++++++++++++++ 8 files changed, 85 insertions(+), 28 deletions(-) diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index b031b52c8fb1..bf4863441de1 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -1135,13 +1135,11 @@ (define_insn "ior<mode>3<vczle><vczbe>" [(set (match_operand:VDQ_I 0 "register_operand") (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand") - (match_operand:VDQ_I 2 "aarch64_orr_imm_sve_advsimd")))] + (match_operand:VDQ_I 2 "aarch64_reg_or_orr_imm")))] "TARGET_SIMD" - {@ [ cons: =0 , 1 , 2; attrs: arch ] - [ w , w , w ; simd ] orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype> - [ w , 0 , vsl; sve ] orr\t%Z0.<Vetype>, %Z0.<Vetype>, #%2 - [ w , 0 , Do ; simd ] \ - << aarch64_output_simd_orr_imm (operands[2], <bitsize>); + {@ [ cons: =0 , 1 , 2 ] + [ w , w , w ] orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype> + [ w , 0 , Do ] << aarch64_output_simd_orr_imm (operands[2], <bitsize>); } [(set_attr "type" "neon_logic<q>")] ) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 4db224ff0421..614f99e799ca 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -140,7 +140,7 @@ enum simd_immediate_check { /* Information about a legitimate vector immediate operand. */ struct simd_immediate_info { - enum insn_type { MOV, MVN, INDEX, PTRUE }; + enum insn_type { MOV, MVN, INDEX, PTRUE, SVE_MOV }; enum modifier_type { LSL, MSL }; simd_immediate_info () {} @@ -22982,14 +22982,16 @@ aarch64_sve_valid_immediate (unsigned HOST_WIDE_INT ival, scalar_int_mode mode, { /* DUP with no shift. */ if (info) - *info = simd_immediate_info (mode, val); + *info = simd_immediate_info (mode, val, + simd_immediate_info::SVE_MOV); return true; } if ((val & 0xff) == 0 && IN_RANGE (val, -0x8000, 0x7f00)) { /* DUP with LSL #8. */ if (info) - *info = simd_immediate_info (mode, val); + *info = simd_immediate_info (mode, val, + simd_immediate_info::SVE_MOV); return true; } } @@ -22997,7 +22999,7 @@ aarch64_sve_valid_immediate (unsigned HOST_WIDE_INT ival, scalar_int_mode mode, { /* DUPM. */ if (info) - *info = simd_immediate_info (mode, val); + *info = simd_immediate_info (mode, val, simd_immediate_info::SVE_MOV); return true; } return false; @@ -23322,8 +23324,13 @@ aarch64_simd_valid_imm (rtx op, simd_immediate_info *info, if (vec_flags & VEC_SVE_DATA) return aarch64_sve_valid_immediate (ival, imode, info, which); - else - return aarch64_advsimd_valid_immediate (val64, imode, info, which); + + if (aarch64_advsimd_valid_immediate (val64, imode, info, which)) + return true; + + if (TARGET_SVE) + return aarch64_sve_valid_immediate (ival, imode, info, which); + return false; } /* Return true if OP is a valid SIMD move immediate for SVE or AdvSIMD. */ @@ -25427,6 +25434,14 @@ aarch64_output_simd_imm (rtx const_vector, unsigned width, return templ; } + if (info.insn == simd_immediate_info::SVE_MOV) + { + gcc_assert (TARGET_SVE); + snprintf (templ, sizeof (templ), "mov\t%%Z0.%c, #" HOST_WIDE_INT_PRINT_DEC, + element_char, INTVAL (info.u.mov.value)); + return templ; + } + mnemonic = info.insn == simd_immediate_info::MVN ? "mvni" : "movi"; shift_op = (info.u.mov.modifier == simd_immediate_info::MSL ? "msl" : "lsl"); @@ -25446,8 +25461,18 @@ aarch64_output_simd_imm (rtx const_vector, unsigned width, else { /* AARCH64_CHECK_ORR or AARCH64_CHECK_AND. */ - mnemonic = info.insn == simd_immediate_info::MVN ? "bic" : "orr"; - if (info.u.mov.shift) + mnemonic = "orr"; + if (which == AARCH64_CHECK_AND) + mnemonic = info.insn == simd_immediate_info::MVN ? "bic" : "and"; + + if (info.insn == simd_immediate_info::SVE_MOV) + { + gcc_assert (TARGET_SVE); + snprintf (templ, sizeof (templ), "%s\t%%Z0.%c, %%Z0.%c, " + HOST_WIDE_INT_PRINT_DEC, mnemonic, element_char, + element_char, INTVAL (info.u.mov.value)); + } + else if (info.u.mov.shift) snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count, element_char, UINTVAL (info.u.mov.value), "lsl", diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 0a171387b1a7..2c18af94b8ec 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -943,11 +943,6 @@ (ior (match_operand 0 "register_operand") (match_operand 0 "aarch64_sve_logical_immediate"))) -(define_predicate "aarch64_orr_imm_sve_advsimd" - (ior (match_operand 0 "aarch64_reg_or_orr_imm") - (and (match_test "TARGET_SVE") - (match_operand 0 "aarch64_sve_logical_operand")))) - (define_predicate "aarch64_sve_gather_offset_b" (ior (match_operand 0 "register_operand") (match_operand 0 "aarch64_sve_gather_immediate_b"))) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_s64.c index 32cdc8263d19..6f36f32415ac 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_s64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_s64.c @@ -43,8 +43,8 @@ TEST_UNIFORM_Z (insr_0_s64_untied, svint64_t, /* ** insr_1_s64: ** ( -** mov (x[0-9]+), #?1 -** insr z0\.d, \1 +** mov z([0-9]+)\.d, #?1 +** insr z0\.d, d\1 ** | ** movi v([0-9]+)\.2d, 0x1 ** insr z0\.d, d\2 diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_u64.c index ab23f677d4fc..f92059a97f57 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_u64.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/insr_u64.c @@ -43,8 +43,8 @@ TEST_UNIFORM_Z (insr_0_u64_untied, svuint64_t, /* ** insr_1_u64: ** ( -** mov (x[0-9]+), #?1 -** insr z0\.d, \1 +** mov z([0-9]+)\.d, #?1 +** insr z0\.d, d\1 ** | ** movi v([0-9]+)\.2d, 0x1 ** insr z0\.d, d\2 diff --git a/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_1.c b/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_1.c index a8b27199ff83..03560008fda1 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_1.c @@ -6,7 +6,7 @@ /* ** t1: -** orr z[0-9]+.s, z[0-9]+.s, #-2147483648 +** orr v0.2s, #?128, lsl #?24 ** ret */ float32x2_t t1 (float32x2_t a) @@ -16,7 +16,7 @@ float32x2_t t1 (float32x2_t a) /* ** t2: -** orr z[0-9]+.s, z[0-9]+.s, #-2147483648 +** orr v0.4s, #?128, lsl #?24 ** ret */ float32x4_t t2 (float32x4_t a) @@ -26,7 +26,7 @@ float32x4_t t2 (float32x4_t a) /* ** t3: -** orr z[0-9]+.d, z[0-9]+.d, #-9223372036854775808 +** orr z[0-9]+.d, z[0-9]+.d, #?-9223372036854775808 ** ret */ float64x2_t t3 (float64x2_t a) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_2.c b/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_2.c index 19a7695e605b..fe08fe31fe87 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/fneg-abs_2.c @@ -7,7 +7,7 @@ /* ** f1: -** orr z0.s, z0.s, #-2147483648 +** orr v0.2s, #?128, lsl #?24 ** ret */ float32_t f1 (float32_t a) @@ -17,7 +17,7 @@ float32_t f1 (float32_t a) /* ** f2: -** orr z0.d, z0.d, #-9223372036854775808 +** orr z0.d, z0.d, #?-9223372036854775808 ** ret */ float64_t f2 (float64_t a) diff --git a/gcc/testsuite/gcc.target/aarch64/sve/simd_imm_mov.c b/gcc/testsuite/gcc.target/aarch64/sve/simd_imm_mov.c new file mode 100644 index 000000000000..57aa9807e6ab --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/simd_imm_mov.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include <arm_neon.h> + +typedef short v8hi __attribute__((vector_size(16))); +typedef int v4si __attribute__((vector_size(16))); +typedef long v2di __attribute__((vector_size(16))); + +/* +** t1: +** mov z0.s, #?4092 +** ret +*/ +v4si t1 () +{ + return (v4si) { 0xffc, 0xffc, 0xffc, 0xffc }; +} + +/* +** t2: +** mov z0.h, #?510 +** ret +*/ +v8hi t2 () +{ + return (v8hi) { 510, 510, 510, 510, 510, 510, 510, 510 }; +} + +/* +** t3: +** mov z0.d, #?1 +** ret +*/ +v2di t3 () +{ + return (v2di) { 1, 1 }; +}