https://gcc.gnu.org/g:667a1b5285c2d5d075a324a29323804f93d43add

commit r17-1584-g667a1b5285c2d5d075a324a29323804f93d43add
Author: Kyrylo Tkachov <[email protected]>
Date:   Tue Jun 16 00:58:28 2026 -0700

    aarch64: Fix wrong code for high-64-zero Advanced SIMD constants [PR125794]
    
    r17-1491-gf152cf1734f808 (PR113926) taught aarch64_simd_valid_imm to
    materialize a 128-bit Advanced SIMD MOV constant whose high 64 bits are
    zero with a 64-bit MOVI/FMOV, which zeroes the upper half of the
    register.  It records this with simd_immediate_info::width == 64
    (output_width).
    
    However, when the low 64 bits are not themselves a valid Advanced SIMD
    (MOVI/MVNI/FMOV) immediate, the function fell through to the SVE
    immediate forms (aarch64_sve_valid_immediate).  Those use a replicating
    "mov zN.<T>, #imm", which sets the whole vector, including the high 64
    bits that were required to be zero, to the repeated low-64-bit value.
    For e.g. the V4SI constant { 0, 1, 0, 0 } this emitted
    
            mov     z31.d, #4294967296      // 0x100000000, i.e. { 0, 1, 0, 1 }
    
    instead of the intended { 0, 1, 0, 0 }, producing wrong code.
    
    Fix it by not falling through to the SVE forms when output_width is set:
    such a constant must be formed by a 64-bit Advanced SIMD MOVI/FMOV
    (handled by the Advanced SIMD and floating-point paths just above) or
    not at all, in which case the caller materializes it some other way
    (e.g. a literal-pool load), which is the pre-r17-1491 behavior for these
    constants.
    
    The PR113926 optimization is unaffected: it only applies when the
    Advanced SIMD or floating-point path accepts the low 64 bits, and those
    still return true before the new check.
    
    Bootstrapped and regression-tested on aarch64-linux-gnu.
    Pushing to trunk.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>
    
    gcc/ChangeLog:
    
            PR target/125794
            * config/aarch64/aarch64.cc (aarch64_simd_valid_imm): Do not fall
            through to the replicating SVE immediate forms for a 128-bit
            Advanced SIMD constant whose high 64 bits are zero (output_width
            != 0).
    
    gcc/testsuite/ChangeLog:
    
            PR target/125794
            * gcc.target/aarch64/sve/pr125794.c: New test.

Diff:
---
 gcc/config/aarch64/aarch64.cc                   |  6 ++++++
 gcc/testsuite/gcc.target/aarch64/sve/pr125794.c | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 08746b657746..42e56512c616 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -24733,6 +24733,12 @@ aarch64_simd_valid_imm (rtx op, simd_immediate_info 
*info,
       return true;
     }
 
+  /* A constant with zero high 64 bits (output_width == 64) must be formed
+     by a 64-bit Advanced SIMD MOVI/FMOV; it must not fall through to the
+     SVE forms below, which replicate it across the whole vector.  */
+  if (output_width != 0)
+    return false;
+
   if (TARGET_SVE)
     return aarch64_sve_valid_immediate (ival, imode, info, which);
   return false;
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr125794.c 
b/gcc/testsuite/gcc.target/aarch64/sve/pr125794.c
new file mode 100644
index 000000000000..a4e198b94666
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr125794.c
@@ -0,0 +1,22 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-additional-options "-O2" } */
+
+/* PR target/125794: a 128-bit Advanced SIMD integer constant whose high 64
+   bits are zero (here { 0, 1, 0, 0 }) must be materialised with a 64-bit MOVI
+   that zeroes the upper half of the register.  It was wrongly emitted as a
+   replicating SVE "mov zN.d, #imm", which set the high 64 bits to a non-zero
+   value and produced wrong code.  */
+
+typedef unsigned V __attribute__((__vector_size__ (32)));
+
+V x;
+
+int
+main ()
+{
+  x[5] = 1;
+  for (unsigned i = 0; i < 8; i++)
+    if (x[i] != (i == 5))
+      __builtin_abort ();
+  return 0;
+}

Reply via email to