]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
aarch64: Improve simd highpart builtin folding
authorDylan Rees <dylan.rees@arm.com>
Mon, 13 Jul 2026 09:57:17 +0000 (09:57 +0000)
committerPengfei Li <Pengfei.Li2@arm.com>
Mon, 13 Jul 2026 12:25:08 +0000 (12:25 +0000)
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
gcc/testsuite/gcc.target/aarch64/simd/fold_to_highpart_7.c [new file with mode: 0644]

index 4622b42afa68d945d0eed23aa61b2c6adad22d9c..60a57839ff5e4aa1df1a18781735d5d477a52287 100644 (file)
@@ -4904,9 +4904,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;
@@ -4935,6 +4937,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;
        }
@@ -4965,6 +4969,16 @@ 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]);
+      tree vec_dup = gimple_build_vector_from_val (gsi, true,
+                                                  GSI_SAME_STMT, loc,
+                                                  call_types[i], elt);
+      call_args[i] = vec_dup;
+    }
+
   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 (file)
index 0000000..d945566
--- /dev/null
@@ -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);
+}