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        | 16 +++++++++++++-
 .../aarch64/simd/fold_to_highpart_7.c         | 22 +++++++++++++++++++
 2 files changed, 37 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..c0fd902351d 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,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
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

Reply via email to