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

Andrea Pinski <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CALvbMcAyu1X21X0ekDz9iDxNa3s9zeXdP2vYdr4BTg9KrNGqAA@mail.gmail.com>
On Fri, Jul 31, 2026 at 4:36 AM Karl Mehltretter <[email protected]> wrote:
>
> 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?

I am not sure if we want to add hacks still to support reload. It
would be better if those targets are changed over to using LRA.  There
was a plan to remove reload for GCC 16 but it seems like it slipped
until this year at the earliest. Though I have not seen any movement
towards removing it but that is still the plan of record.

Thanks,
Andrea

>
>  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.