Hi Vladimir,

Could you have a look at this?  Any feedback is welcome.

Cheers,
Stefan

On Fri, Nov 07, 2025 at 09:26:21AM +0100, Stefan Schulze Frielinghaus wrote:
> Ping
> 
> On Mon, Oct 13, 2025 at 10:52:48AM +0200, Stefan Schulze Frielinghaus wrote:
> > From: Stefan Schulze Frielinghaus <[email protected]>
> > 
> > This fixes
> > 
> > asm-hard-reg-3.c:10:1: error: unrecognizable insn:
> >    10 | }
> >       | ^
> > (insn 9 18 14 2 (parallel [
> >             (set (reg:DI 0 ax [orig:99 x ] [99])
> >                 (asm_operands:DI ("") ("=r") 0 [
> >                         (reg:SI 0 ax [100])
> >                         (reg:DI 1 dx [105]) repeated x2
> >                     ]
> >                      [
> >                         (asm_input:SI ("0") asm-hard-reg-3.c:8)
> >                         (asm_input:DI ("r") asm-hard-reg-3.c:8)
> >                         (asm_input:DI ("{r8}") asm-hard-reg-3.c:8)
> >                     ]
> >                      [] asm-hard-reg-3.c:8))
> >             (clobber (reg:CC 17 flags))
> >         ]) "asm-hard-reg-3.c":8:3 -1
> >      (nil))
> > during RTL pass: reload
> > 
> > During get_reload_reg() a reload register may be reused and so far
> > exclude start hard registers were not taken into account.  For the test
> > case this means operands 2 and 3 use the same reload register which gets
> > dx assigned, although, the constraint of operand 3 refers to register
> > r8.  That in turn renders the insn unsatisfiable.
> > 
> > A conservative approach would be to simply not reuse any reload register
> > whenever the set of exclude start hard regs is non-empty.  However, this
> > would lead to some missed optimizations like in this example where
> > operands 2 and 3 would land in different registers.  Therefore, if both
> > share a start hard register, still reuse the reload and refine the
> > exclude start hard regs set.
> > 
> > I only have a test case for inputs.  However, I expect an analogue
> > problem for outputs which is why I adapted that case, too.
> > 
> > gcc/ChangeLog:
> > 
> >     * lra-constraints.cc (get_reload_reg): Honor exclude start regs
> >     while reusing reloads.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * gcc.dg/asm-hard-reg-9.c: New test.
> > ---
> >  Bootstrapped and regtested on s390 and x86_64.  Ok for mainline?
> > 
> > 
> >  gcc/lra-constraints.cc                | 21 ++++++++++++++++++++-
> >  gcc/testsuite/gcc.dg/asm-hard-reg-9.c | 15 +++++++++++++++
> >  2 files changed, 35 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/asm-hard-reg-9.c
> > 
> > diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> > index 48ce75781d4..f4223dd8e51 100644
> > --- a/gcc/lra-constraints.cc
> > +++ b/gcc/lra-constraints.cc
> > @@ -686,7 +686,11 @@ get_reload_reg (enum op_type type, machine_mode mode, 
> > rtx original,
> >       && (int) REGNO (original) >= new_regno_start
> >       && (INSN_UID (curr_insn) >= new_insn_uid_start
> >           || ira_former_scratch_p (REGNO (original)))
> > -     && in_class_p (original, rclass, &new_class, true))
> > +     && in_class_p (original, rclass, &new_class, true)
> > +     && (exclude_start_hard_regs == nullptr
> > +         || hard_reg_set_intersect_p (
> > +             ~lra_reg_info[REGNO (original)].exclude_start_hard_regs,
> > +             ~*exclude_start_hard_regs)))
> >     {
> >       unsigned int regno = REGNO (original);
> >       if (lra_dump_file != NULL)
> > @@ -698,6 +702,9 @@ get_reload_reg (enum op_type type, machine_mode mode, 
> > rtx original,
> >         lra_change_class (regno, new_class, ", change to", false);
> >       if (lra_dump_file != NULL)
> >         fprintf (lra_dump_file, "\n");
> > +     if (exclude_start_hard_regs)
> > +       lra_reg_info[regno].exclude_start_hard_regs
> > +         |= *exclude_start_hard_regs;
> >       *result_reg = original;
> >       return false;
> >     }
> > @@ -734,6 +741,18 @@ get_reload_reg (enum op_type type, machine_mode mode, 
> > rtx original,
> >             if (reg == NULL_RTX || GET_CODE (reg) != SUBREG)
> >               continue;
> >           }
> > +       /* If the existing reload and this have no start hard register in
> > +          common, then skip.  Otherwise update exclude_start_hard_regs.  */
> > +       if (exclude_start_hard_regs
> > +           && ! hard_reg_set_empty_p (*exclude_start_hard_regs))
> > +         {
> > +           HARD_REG_SET r = lra_reg_info[regno].exclude_start_hard_regs
> > +                            | *exclude_start_hard_regs;
> > +           if (hard_reg_set_empty_p (~r))
> > +             continue;
> > +           else
> > +             lra_reg_info[regno].exclude_start_hard_regs = r;
> > +         }
> >         *result_reg = reg;
> >         if (lra_dump_file != NULL)
> >           {
> > diff --git a/gcc/testsuite/gcc.dg/asm-hard-reg-9.c 
> > b/gcc/testsuite/gcc.dg/asm-hard-reg-9.c
> > new file mode 100644
> > index 00000000000..0866cb4554a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/asm-hard-reg-9.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile { target s390*-*-* x86_64-*-* } } */
> > +/* { dg-options "-O2" } */
> > +
> > +/* Ensure that if the reload register for operand 2 is resued for operand 
> > 3,
> > +   that exclude start hard regs coming from operand 3 are taken into 
> > account.
> > +   Otherwise a different register than r8 may be chosen rendering the insn
> > +   after LRA unsatisfiable.  */
> > +
> > +long
> > +test ()
> > +{
> > +  long x;
> > +  __asm__ ("" : "=r" (x) : "0" (1000), "r" (0l), "{r8}" (0l));
> > +  return x;
> > +}
> > -- 
> > 2.49.0
> > 

Reply via email to