[PATCH] ext-dce: Avoid multi-register paradoxical subregs for reload [PR122438]

Karl Mehltretter <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
ext-dce can turn an extension into a paradoxical subreg when the
upper bits are dead.  With classic reload, this can fail if the modes
use different numbers of hard registers.  On m68k, SI-to-DI creates an
invalid overlap and an ICE in postreload.

Skip the rewrite in that case.  This change also fixes PR119953
on MSP430.  LRA and same-register-count cases are unchanged.

Cross-tested on GCC trunk:

1) m68k-linux-gnu: the unpatched compiler reproduces PR122438.  The
gcc.target/m68k suite changes from 128 PASS / 9 FAIL / 1 unsupported
to 129 PASS / 9 FAIL / 1 unsupported with the new test.

2) msp430-elf: the new PR119953 test passes.

3) alpha-linux-gnu and vax-netbsdelf: the tested same-register-count
extension cases produce identical assembly with and without the patch.

Also tested on GCC 16.1.1 for m68k-linux-gnu.  The unpatched compiler
reproduces PR122438 while the new test passes with the patch.

Assisted-by: Codex gpt-5.6-terra

gcc/ChangeLog:

	PR rtl-optimization/122438
	PR target/119953
	* ext-dce.cc: Include regs.h.
	(ext_dce_try_optimize_extension): Avoid multi-register
	paradoxical subregs with classic reload.

gcc/testsuite/ChangeLog:

	PR rtl-optimization/122438
	PR target/119953
	* gcc.target/m68k/pr122438.c: New test.
	* g++.target/msp430/pr119953.C: New test.

Signed-off-by: Karl Mehltretter <[email protected]>
---
OK for trunk?

 gcc/ext-dce.cc                             |  8 +++++
 gcc/testsuite/g++.target/msp430/pr119953.C | 40 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/m68k/pr122438.c   | 23 +++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 gcc/testsuite/g++.target/msp430/pr119953.C
 create mode 100644 gcc/testsuite/gcc.target/m68k/pr122438.c

diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc
index 9e4b0a429b..8e0c5ab9db 100644
--- a/gcc/ext-dce.cc
+++ b/gcc/ext-dce.cc
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "memmodel.h"
 #include "insn-config.h"
 #include "emit-rtl.h"
+#include "regs.h"
 #include "expr.h"
 #include "recog.h"
 #include "cfganal.h"
@@ -533,6 +534,13 @@ ext_dce_try_optimize_extension (rtx_insn *insn, rtx set)
       return;
     }
 
+  /* Avoid known classic-reload problems with multi-register paradoxical
+     subregs (PR122438, PR119953).  */
+  if (!targetm.lra_p ()
+      && (hard_regno_nregs (0, GET_MODE (src))
+	  != hard_regno_nregs (0, GET_MODE (inner))))
+    return;
+
   /* Avoid (subreg (mem)) and other constructs which may be valid RTL, but
      not useful for this optimization.  */
   if (!(REG_P (inner) || (SUBREG_P (inner) && REG_P (SUBREG_REG (inner)))))
diff --git a/gcc/testsuite/g++.target/msp430/pr119953.C b/gcc/testsuite/g++.target/msp430/pr119953.C
new file mode 100644
index 0000000000..fd2562eff9
--- /dev/null
+++ b/gcc/testsuite/g++.target/msp430/pr119953.C
@@ -0,0 +1,40 @@
+/* PR target/119953 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+bool equals_tmp;
+int native ();
+
+struct path
+{
+  class iterator;
+  iterator begin ();
+  iterator end ();
+} p, hash_path;
+
+struct path::iterator
+{
+  path operator* () { return p; }
+  void operator++ () {}
+  friend bool operator!= (iterator lhs, iterator rhs)
+  {
+    return lhs.equals (rhs);
+  }
+  bool equals (iterator rhs)
+  {
+    if (equals_tmp)
+      return cur == rhs.cur;
+    return at_end == rhs.at_end;
+  }
+  char cur;
+  bool at_end;
+};
+
+int
+hash_value ()
+{
+  int seed;
+  for (auto x : hash_path)
+    seed ^= native () + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+  return seed;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/pr122438.c b/gcc/testsuite/gcc.target/m68k/pr122438.c
new file mode 100644
index 0000000000..353bcc1b8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr122438.c
@@ -0,0 +1,23 @@
+/* PR rtl-optimization/122438 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -w" } */
+
+long describeCell_nLocal;
+char describeCell_a;
+char describeCell_zDesc[];
+int strlen (char *);
+void describeContent (char *, char *);
+void localPayload (void);
+
+void
+describeCell (char cType)
+{
+  long long nDesc;
+  if (cType)
+    nDesc += nDesc;
+  localPayload ();
+  if (describeCell_nLocal)
+    nDesc += strlen (&describeCell_zDesc[nDesc]);
+  if (cType)
+    describeContent (&describeCell_a, &describeCell_zDesc[nDesc]);
+}
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.