[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