[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] [PR rtl-optimization/123380] Avoid creating bogus SUBREG in combine
Jeff Law
law@gcc.gnu.org
Wed Jan 28 15:08:11 GMT 2026
https://gcc.gnu.org/g:6844a7d0de6bb0928a039ee2d7fd7e20546e3f22
commit 6844a7d0de6bb0928a039ee2d7fd7e20546e3f22
Author: Jeff Law <jeffrey.law@oss.qualcomm.com>
Date: Tue Jan 20 15:03:28 2026 -0700
[PR rtl-optimization/123380] Avoid creating bogus SUBREG in combine
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.
(cherry picked from commit 1bede52d8c4ba434a8f4786f84f85922cc0c6152)
Diff:
---
gcc/combine.cc | 3 ++-
gcc/testsuite/gcc.target/riscv/pr123380.c | 18 ++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/gcc/combine.cc b/gcc/combine.cc
index 9794f98b946a..9ac872137e48 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -11849,7 +11849,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
index 000000000000..1cbbc8436156
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr123380.c
@@ -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;
+}
More information about the Gcc-cvs
mailing list