https://gcc.gnu.org/g:2ec5082dd24cef5149ba645ee88a9acd8b4c290a

commit r16-727-g2ec5082dd24cef5149ba645ee88a9acd8b4c290a
Author: Jennifer Schmitz <jschm...@nvidia.com>
Date:   Thu May 15 07:16:15 2025 -0700

    regcprop: Return from copy_value for unordered modes
    
    The ICE in PR120276 resulted from a comparison of VNx4QI and V8QI using
    partial_subreg_p in the function copy_value during the RTL pass
    regcprop, failing the assertion in
    
    inline bool
    partial_subreg_p (machine_mode outermode, machine_mode innermode)
    {
      /* Modes involved in a subreg must be ordered.  In particular, we must
         always know at compile time whether the subreg is paradoxical.  */
      poly_int64 outer_prec = GET_MODE_PRECISION (outermode);
      poly_int64 inner_prec = GET_MODE_PRECISION (innermode);
      gcc_checking_assert (ordered_p (outer_prec, inner_prec));
      return maybe_lt (outer_prec, inner_prec);
    }
    
    Returning from the function if the modes are not ordered before reaching
    the call to partial_subreg_p resolves the ICE and passes bootstrap and
    testing without regression.
    OK for mainline?
    
    Signed-off-by: Jennifer Schmitz <jschm...@nvidia.com>
    
    gcc/
            PR middle-end/120276
            * regcprop.cc (copy_value): Return in case of unordered modes.
    
    gcc/testsuite/
            PR middle-end/120276
            * gcc.dg/torture/pr120276.c: New test.

Diff:
---
 gcc/regcprop.cc                         |  4 ++++
 gcc/testsuite/gcc.dg/torture/pr120276.c | 20 ++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/gcc/regcprop.cc b/gcc/regcprop.cc
index 4fa1305526cc..98ab3f77e835 100644
--- a/gcc/regcprop.cc
+++ b/gcc/regcprop.cc
@@ -332,6 +332,10 @@ copy_value (rtx dest, rtx src, struct value_data *vd)
   if (vd->e[sr].mode == VOIDmode)
     set_value_regno (sr, vd->e[dr].mode, vd);
 
+  else if (!ordered_p (GET_MODE_PRECISION (vd->e[sr].mode),
+                      GET_MODE_PRECISION (GET_MODE (src))))
+    return;
+
   /* If we are narrowing the input to a smaller number of hard regs,
      and it is in big endian, we are really extracting a high part.
      Since we generally associate a low part of a value with the value itself,
diff --git a/gcc/testsuite/gcc.dg/torture/pr120276.c 
b/gcc/testsuite/gcc.dg/torture/pr120276.c
new file mode 100644
index 000000000000..9717a7103e5e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr120276.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a+sve" { target aarch64*-*-* } } */
+
+int a;
+char b[1];
+int c[18];
+void d(char *);
+void e() {
+  int f;
+  char *g;
+  a = 0;
+  for (; a < 18; a++) {
+    int h = f = 0;
+    for (; f < 4; f++) {
+      g[a * 4 + f] = c[a] >> h;
+      h += 8;
+    }
+  }
+  d(b);
+}
\ No newline at end of file

Reply via email to