aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJennifer Schmitz <jschmitz@nvidia.com>2025-05-15 07:16:15 -0700
committerJennifer Schmitz <jschmitz@nvidia.com>2025-05-19 08:18:56 +0200
commit2ec5082dd24cef5149ba645ee88a9acd8b4c290a (patch)
tree74b945b5f2d36dbbb1b9f8feb6eb228831bf7202 /gcc
parentc9eb473fb9946f642506d24f4131d7c83855fd78 (diff)
downloadgcc-2ec5082dd24cef5149ba645ee88a9acd8b4c290a.zip
gcc-2ec5082dd24cef5149ba645ee88a9acd8b4c290a.tar.gz
gcc-2ec5082dd24cef5149ba645ee88a9acd8b4c290a.tar.bz2
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 <jschmitz@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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/regcprop.cc4
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr120276.c20
2 files changed, 24 insertions, 0 deletions
diff --git a/gcc/regcprop.cc b/gcc/regcprop.cc
index 4fa1305..98ab3f7 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 0000000..9717a71
--- /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