> -----Original Message-----
> From: Dylan Rees <[email protected]>
> Sent: 08 June 2026 17:34
> To: [email protected]
> Cc: Dylan Rees <[email protected]>; [email protected];
> [email protected]; [email protected]; Tamar Christina
> <[email protected]>
> Subject: [PATCH v2 1/2] aarch64: Improve simd highpart builtin folding
>
> The current helper function folding calls to lowpart builtins into
> highpart builtins calls does not handle cases where we have a 64b
> wide uniform vector, which can be extended to 128b, used for
> high part operations requiring 128b vector inputs. This change
> adds an additional check on the statement arguments and widens
> uniform vectors before adding to the 'call_args' of the new call
> to the equivalent highpart builtin. Relevant function comments were
> also updated.
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64-builtins.cc (aarch64_fold_lo_call_to_hi):
> New branch to check for uniform vectors, extend and then add
> them to the new highpart builtin call.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/aarch64/simd/fold_to_highpart_7.c: New test.
> ---
> gcc/config/aarch64/aarch64-builtins.cc | 17 +++++++++++++-
> .../aarch64/simd/fold_to_highpart_7.c | 22 +++++++++++++++++++
> 2 files changed, 38 insertions(+), 1 deletion(-)
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/simd/fold_to_highpart_7.c
>
> diff --git a/gcc/config/aarch64/aarch64-builtins.cc
> b/gcc/config/aarch64/aarch64-builtins.cc
> index b9cc2bf404f..b547ddf29ee 100644
> --- a/gcc/config/aarch64/aarch64-builtins.cc
> +++ b/gcc/config/aarch64/aarch64-builtins.cc
> @@ -5306,9 +5306,11 @@ aarch64_fold_lo_call_to_hi (unsigned int fcode,
> gcall *stmt,
>
> /* Prefer to use the highpart builtin when at least one vector
> argument is a reference to the high half of a 128b vector, and
> - all others are VECTOR_CSTs that we can extend to 128b. */
> + all others are VECTOR_CSTs or uniform vectors that we can extend
> + to 128b. */
> auto_vec<unsigned int, 2> vec_constants;
> auto_vec<unsigned int, 2> vec_highparts;
> + auto_vec<unsigned int, 2> vec_uniforms;
> /* The arguments and signature of the new call. */
> auto_vec<tree, 4> call_args;
> auto_vec<tree, 4> call_types;
> @@ -5337,6 +5339,8 @@ aarch64_fold_lo_call_to_hi (unsigned int fcode,
> gcall *stmt,
> }
> else if (TREE_CODE (arg) == VECTOR_CST)
> vec_constants.safe_push (argno);
> + else if (ssa_uniform_vector_p (arg))
> + vec_uniforms.safe_push (argno);
> else
> return nullptr;
> }
> @@ -5367,6 +5371,17 @@ aarch64_fold_lo_call_to_hi (unsigned int fcode,
> gcall *stmt,
> call_args[i] = vce_ssa;
> }
>
> + location_t loc = gimple_location (stmt);
> + for (auto i : vec_uniforms)
> + {
> + tree elt = ssa_uniform_vector_p (call_args[i]);
> + gimple_seq seq = NULL;
> + tree vec_dup = gimple_build_vector_from_val (&seq, loc, call_types[i],
> + elt);
> + gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
> + call_args[i] = vec_dup;
> + }
There's a gimple_build_vector_from_val overload that takes a gsi directly,
use that instead since you're only emitting one statement at a time anyway.
OK with that change.
Thanks,
Tamar
> +
> gcall *new_call = gimple_build_call_vec (builtin_hi, call_args);
> gimple_call_set_lhs (new_call, gimple_call_lhs (stmt));
> return new_call;
> diff --git a/gcc/testsuite/gcc.target/aarch64/simd/fold_to_highpart_7.c
> b/gcc/testsuite/gcc.target/aarch64/simd/fold_to_highpart_7.c
> new file mode 100644
> index 00000000000..d945566b043
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/simd/fold_to_highpart_7.c
> @@ -0,0 +1,22 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O3" } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include <arm_neon.h>
> +
> +/* We should fold to the highpart builtin when the multiplying the highpart
> of
> a
> + 128b vector with a uniform vector which can be widened.
> +
> + Use vdup_n_u8 to create an 8x8 splat vector. */
> +
> +/*
> +** foo:
> +** ...
> +** umull2 v([0-9]+).8h, v([0-9]+).16b, v([0-9]+).16b
> +** ...
> +*/
> +uint16x8_t foo(uint8_t *a, uint8_t *b) {
> + const uint8x8_t uniform_vec = vdup_n_u8(*a);
> + const uint8x16_t hipart_vec = vld1q_u8(b);
> + return vmull_u8(vget_high_u8(hipart_vec), uniform_vec);
> +}
> --
> 2.43.0