]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR rtl-optimization/123380] Avoid creating bogus SUBREG in combine
authorJeff Law <jeffrey.law@oss.qualcomm.com>
Tue, 20 Jan 2026 22:03:28 +0000 (15:03 -0700)
committerJeff Law <jeffrey.law@oss.qualcomm.com>
Tue, 20 Jan 2026 22:03:28 +0000 (15:03 -0700)
In this issue we try to call gen_rtx_SUBREG with arguments that will trigger an
assertion failure.  In particular we're trying to create a paradoxical subreg
of an HFmode object where the paradoxical is in DImode.  That's obviously a
change in size.  validate_subreg returns false for that case, thus triggering
the assertion.

Like other cases in combine.cc and elsewhere we can check validate_subreg
before we call gen_rtx_SUBREG and if validate_subreg returns false, we can
return a safe value.  So that's all this patch does.

Bootstrapped and regression tested on x86_64, also regression tested on
riscv{32,64}-elf.  Pushing to the trunk.

PR rtl-optimization/123380
gcc/
* combine.cc (gen_lowpart_for_combine): Don't try to create a
paradoxical SUBREG if it's going to be rejected by validate_subreg.

gcc/testsuite/
* gcc.target/riscv/pr123380.c: New test.

gcc/combine.cc
gcc/testsuite/gcc.target/riscv/pr123380.c [new file with mode: 0644]

index 09e24347b342ba1fa8fc25703759684efde7aa60..573ed716ad635818b75fbf9967996a7bbf7f882d 100644 (file)
@@ -11856,7 +11856,8 @@ gen_lowpart_for_combine (machine_mode omode, rtx x)
       /* If we want to refer to something bigger than the original memref,
         generate a paradoxical subreg instead.  That will force a reload
         of the original memref X.  */
-      if (paradoxical_subreg_p (omode, imode))
+      if (paradoxical_subreg_p (omode, imode)
+         && validate_subreg (omode, GET_MODE (x), x, 0))
        return gen_rtx_SUBREG (omode, x, 0);
 
       poly_int64 offset = byte_lowpart_offset (omode, imode);
diff --git a/gcc/testsuite/gcc.target/riscv/pr123380.c b/gcc/testsuite/gcc.target/riscv/pr123380.c
new file mode 100644 (file)
index 0000000..1cbbc84
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc -mabi=ilp32d -O2" { target { rv32 } } } */
+
+void *p;
+int d;
+char c;
+
+void
+foo (_Float16 *fp)
+{
+  _Float16 f = *fp;
+  do {
+    __builtin_strcat (p, 0);
+    __builtin_memmove (1 + (char *) &f, &f, 1);
+  } while (d);
+  c = f;
+}