https://gcc.gnu.org/g:b13ba91282e7f04a7eb350e0a1a1bdc6ba8a837d
commit r17-4227-gb13ba91282e7f04a7eb350e0a1a1bdc6ba8a837d Author: Wilco Dijkstra <[email protected]> Date: Thu Jun 11 14:14:54 2026 +0000 AArch64: Add tune for zeroing SVE move Add a new tune to select whether to prefer zeroing SVE move immediate or use the merging variant after zeroing the destination. Since the expander is bypassed in multiple places, split after reload to zero the destination. Enable it on cores where the latter was measured to be slightly faster. With -mcpu=neoverse-v2 we now emit this for the testcase: movi d0, #0 mov z0.s, p0/m, #1 instead of: mov z0.s, p0/z, #1 This matches the floating point case (where there is no zeroing variant): movi d0, #0 fmov z0.s, p0/m, #1.0 gcc: * config/aarch64/aarch64.h (TARGET_SVE_PREFER_ZEROING_MOVIMM): New define. * config/aarch64/aarch64-sve.md (*vcond_mask_<mode><vpred>): Add a split condition for zero predicate. * config/aarch64/aarch64-tuning-flags.def: Add AVOID_MOVIMM_Z tune. * config/aarch64/tuning_models/neoversev1.h (tune_flags): Update. * config/aarch64/tuning_models/neoversev2.h (tune_flags): Update. gcc/testsuite: * gcc.target/aarch64/sve/zeroing_mov_z.c: New test. Diff: --- gcc/config/aarch64/aarch64-sve.md | 9 +++++++- gcc/config/aarch64/aarch64-tuning-flags.def | 3 +++ gcc/config/aarch64/aarch64.h | 4 ++++ gcc/config/aarch64/tuning_models/neoversev1.h | 3 ++- gcc/config/aarch64/tuning_models/neoversev2.h | 1 + .../gcc.target/aarch64/sve/zeroing_mov_z.c | 27 ++++++++++++++++++++++ 6 files changed, 45 insertions(+), 2 deletions(-) diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index 1667145d3c71..8b15e25e8b50 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -8622,7 +8622,7 @@ ;; This creates a false dependency on z0 which can result in stalls. ;; The zeroing will be done via a movi d0, 0 which is cheaper. ;; -(define_insn "*vcond_mask_<mode><vpred>" +(define_insn_and_rewrite "*vcond_mask_<mode><vpred>" [(set (match_operand:SVE_ALL 0 "register_operand") (unspec:SVE_ALL [(match_operand:<VPRED> 3 "aarch64_predicate_operand") @@ -8640,6 +8640,13 @@ [ ?&w , vss , w , Upa ; yes ] movprfx\t%0, %2\;mov\t%0.<Vetype>, %3/m, #%I1 [ ?&w , Ufc , w , Upa ; yes ] movprfx\t%0, %2\;fmov\t%0.<Vetype>, %3/m, #%1 } + "&& reload_completed + && aarch64_simd_or_scalar_imm_zero (operands[2], <MODE>mode) + && !TARGET_SVE_PREFER_ZEROING_MOVIMM" + { + emit_move_insn (operands[0], operands[2]); + operands[2] = copy_rtx (operands[0]); + } ) ;; Optimize selects between a duplicated scalar variable and another vector. diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def index 32bc1c4f3eec..64a773be34c0 100644 --- a/gcc/config/aarch64/aarch64-tuning-flags.def +++ b/gcc/config/aarch64/aarch64-tuning-flags.def @@ -81,4 +81,7 @@ AARCH64_EXTRA_TUNING_OPTION ("dispatch_sched", DISPATCH_SCHED) 32 bits are unused. */ AARCH64_EXTRA_TUNING_OPTION ("narrow_gp_writes", NARROW_GP_WRITES) +/* Enable when the target prefers SVE merging movimm over zeroing. */ +AARCH64_EXTRA_TUNING_OPTION ("avoid_zeroing_movimm", AVOID_MOVIMM_Z) + #undef AARCH64_EXTRA_TUNING_OPTION diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 6dec56df5cc1..39f51d4e92d7 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -522,6 +522,10 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED && (aarch64_tune_params.extra_tuning_flags \ & AARCH64_EXTRA_TUNE_AVOID_PRED_RMW)) +/* Set if we prefer SVE merging predicated mov immediate over zeroing. */ +#define TARGET_SVE_PREFER_ZEROING_MOVIMM \ + !(aarch64_tune_params.extra_tuning_flags & AARCH64_EXTRA_TUNE_AVOID_MOVIMM_Z) + /* fp8 instructions are enabled through +fp8. */ #define TARGET_FP8 AARCH64_HAVE_ISA (FP8) diff --git a/gcc/config/aarch64/tuning_models/neoversev1.h b/gcc/config/aarch64/tuning_models/neoversev1.h index 253f11e87a68..004676a8dbac 100644 --- a/gcc/config/aarch64/tuning_models/neoversev1.h +++ b/gcc/config/aarch64/tuning_models/neoversev1.h @@ -229,7 +229,8 @@ static const struct tune_params neoversev1_tunings = (AARCH64_EXTRA_TUNE_BASE | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT - | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW), /* tune_flags. */ + | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW + | AARCH64_EXTRA_TUNE_AVOID_MOVIMM_Z), /* tune_flags. */ &generic_armv9a_prefetch_tune, AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ AARCH64_LDP_STP_POLICY_ALWAYS, /* stp_policy_model. */ diff --git a/gcc/config/aarch64/tuning_models/neoversev2.h b/gcc/config/aarch64/tuning_models/neoversev2.h index 6df0cc444b80..734089772517 100644 --- a/gcc/config/aarch64/tuning_models/neoversev2.h +++ b/gcc/config/aarch64/tuning_models/neoversev2.h @@ -359,6 +359,7 @@ static const struct tune_params neoversev2_tunings = | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW + | AARCH64_EXTRA_TUNE_AVOID_MOVIMM_Z | AARCH64_EXTRA_TUNE_AVOID_LDAPUR | AARCH64_EXTRA_TUNE_DISPATCH_SCHED), /* tune_flags. */ &generic_armv9a_prefetch_tune, diff --git a/gcc/testsuite/gcc.target/aarch64/sve/zeroing_mov_z.c b/gcc/testsuite/gcc.target/aarch64/sve/zeroing_mov_z.c new file mode 100644 index 000000000000..c257e8e7b720 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/zeroing_mov_z.c @@ -0,0 +1,27 @@ +/* { dg-options "-O2 -mcpu=neoverse-v2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include <arm_sve.h> + +/* +** foo: +** movi d0, #0 +** mov z0.s, p0/m, #1 +** ret +*/ +svint32_t foo (svbool_t pg) +{ + return svsel (pg, svdup_s32 (1), svdup_s32 (0)); +} + +/* +** foo2: +** movi d0, #0 +** fmov z0.s, p0/m, #1.0 +** ret +*/ +svfloat32_t foo2 (svbool_t pg) +{ + return svsel (pg, svdup_f32 (1.0f), svdup_f32 (0.0f)); +} +
