> -----Original Message-----
> From: Wilco Dijkstra <[email protected]>
> Sent: 11 September 2026 17:53
> To: Tamar Christina <[email protected]>; Kyrylo Tkachov
> <[email protected]>; Alice Carlotti <[email protected]>; Alex Coplan
> <[email protected]>; Andrew Pinski
> <[email protected]>
> Cc: GCC Patches <[email protected]>
> Subject: Re: [PATCH v2] AArch64: Add tune for zeroing SVE move
> 
> Hi Tamar,
> 
> > So instead of
> >
> > mov     z0.s, p0/z, #5
> >
> > we generate with the flag
> >
> > movi    d0, #0
> > fmov    z0.s, p0/m, #1.0
> 
> Correct - and that is exactly what we already do for FP immediates since there
> is
> no zeroing variant.
> 
> > ? Weird but sure I believe you. But should aarch64_sel_dup<mode> also get
> the
> > same treatment then? You previously changed this to drop the movprfx
> version
> > so I'd expect the same behaviour?
> 
> It already does, I removed all the zeroing movprfx variants, so they already 
> use
> movi.
> This case is the last zeroing variant.
> 
> > Could you also please add a testcase for the tune.
> 
> Done.
> 
> Cheers,
> Wilco
> 
> 
> v2: Add testcase, improve description
> 
> 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
> 
> Passes regress, OK for commit?

OK.

Thanks,
Tamar

> 
> 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 --git a/gcc/config/aarch64/aarch64-sve.md
> b/gcc/config/aarch64/aarch64-sve.md
> index
> 1667145d3c71c14b7d19e32d14f521c8f3c91ad7..8b15e25e8b50dd671174
> b8c971589e904f95607f 100644
> --- a/gcc/config/aarch64/aarch64-sve.md
> +++ b/gcc/config/aarch64/aarch64-sve.md
> @@ -8622,7 +8622,7 @@ (define_expand "@vcond_mask_<mode><vpred>"
>  ;; 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 @@ (define_insn "*vcond_mask_<mode><vpred>"
>       [ ?&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
> 32bc1c4f3eecf04f35740bb573ea39c8449cf901..64a773be34c0c28e18a1c2
> b3b0a84ce369633010 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
> fdedb04391127c5a1b821ed5d4b399c1c28d9f31..c7fa687514e48aad2897d
> dc85880a4685c3b7602 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -519,6 +519,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
> 253f11e87a68548a51201ee8e1318aaae606cab2..004676a8dbacf438beb5c
> 5598a39f80988bb6a48 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
> 6df0cc444b804cf098e8f16d10d7afff6340dd9e..734089772517e69af448d
> d44acf5b20982b8cc3a 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
> 0000000000000000000000000000000000000000..c257e8e7b72014d672
> c92d94f27aeaa8ededd6f8
> --- /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));
> +}
> +

Reply via email to