On Wed, Jan 14, 2026 at 08:37:25PM +0100, Georg-Johann Lay wrote:
> Am 14.01.26 um 14:55 schrieb Stefan Schulze Frielinghaus:
> > From: Stefan Schulze Frielinghaus <[email protected]>
> > 
> > I have put the check into cant_combine_insn_p().  However, I still
> > haven't convinced myself that this is a full fledged solution.  Even the
> > current behaviour for constraints associated a single register class
> > seems like only partially solved to me.  For the current case it would
> > solve the problem because we are substituting into a reg-reg move.
> > However, my current understanding is that I could actually make use of
> > hard registers in arbitrary patterns which wouldn't be dealt with.
> > 
> > With this patch I'm conservative when hard register constraints are
> > involved and skip any combination.
> > 
> > In light of not having real world examples were it breaks also for
> > constraints associated a single register class and being in stage 4, I'm
> > limiting this to hard register constraints for now.
> > 
> > @Jeff ok for mainline assuming that bootstrap and regtest are successful
> > for x86_64 and s390?
> > 
> > @Johann if you have a larger test than what you provided in the PR,
> > could you give this patch a try?  I can confirm that with the machine
> > description patch provided in the PR, the example from the PR compiles
> > fine if this patch is applied.  If you still see failures in more
> > complex examples you might also want to apply
> > https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705494.html
> > https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705495.html
> 
> IIUC, these patches have already been approved and will be upstream soon?

Not the second one.

> 
> So best will be I wait until all 3/3 patches are upstream?
> 
> Great to see progress on this PR, though IMO it's a bit too late to
> use HRCs in the avr backend since we are in stage 4 already, and I guess
> avr is the only backend that would use HRCs in many insns.

This was not a recommendation to switch to hard register constraints so
late.  This is more about testing and reporting problems as soon as possible.
I would love to see hard register constraints in a good shape for GCC
16.  I was just wondering whether you have a slightly larger test.  If
not, don't feel inclined to come up with some.  I will do some more
testing anyway.

Cheers,
Stefan

> 
> Johann
> 
> > Note, I haven't tested hard register constraints in clobbers so far, and
> > would rather assume that they do not work as expected.  Once I find some
> > time, I will look into this.
> > 
> > -- 8< --
> > 
> > This fixes
> > 
> > t.c:6:1: error: unable to find a register to spill
> >      6 | }
> >        | ^
> > 
> > for target avr.  In the PR we are given a patch which makes use of hard
> > register constraints in the machine description for divmodhi4.  Prior
> > combine we have for the test from the PR
> > 
> > (insn 7 6 8 2 (parallel [
> >              (set (reg:HI 46 [ _1 ])
> >                  (div:HI (reg/v:HI 44 [ k ])
> >                      (reg:HI 48)))
> >              (set (reg:HI 47)
> >                  (mod:HI (reg/v:HI 44 [ k ])
> >                      (reg:HI 48)))
> >              (clobber (scratch:HI))
> >              (clobber (scratch:QI))
> >          ]) "t.c":5:5 602 {divmodhi4}
> >       (expr_list:REG_DEAD (reg:HI 48)
> >          (expr_list:REG_DEAD (reg/v:HI 44 [ k ])
> >              (expr_list:REG_UNUSED (reg:HI 47)
> >                  (nil)))))
> > (insn 8 7 9 2 (set (reg:HI 22 r22)
> >          (symbol_ref/f:HI ("*.LC0") [flags 0x2]  <var_decl 0x3fff7950d10 
> > *.LC0>)) "t.c":5:5 128 {*movhi_split}
> >       (nil))
> > (insn 9 8 10 2 (set (reg:HI 24 r24)
> >          (reg:HI 46 [ _1 ])) "t.c":5:5 128 {*movhi_split}
> >       (expr_list:REG_DEAD (reg:HI 46 [ _1 ])
> >          (nil)))
> > 
> > The patched instruction divmodhi4 constraints operand 2 (here pseudo
> > 48) to hard register 22.  Combine merges insn 7 into 9 by crossing a
> > hard register assignment of register 22.
> > 
> > (note 7 6 8 2 NOTE_INSN_DELETED)
> > (insn 8 7 9 2 (set (reg:HI 22 r22)
> >          (symbol_ref/f:HI ("*.LC0") [flags 0x2]  <var_decl 0x3fff7950d10 
> > *.LC0>)) "t.c":5:5 128 {*movhi_split}
> >       (nil))
> > (insn 9 8 10 2 (parallel [
> >              (set (reg:HI 24 r24)
> >                  (div:HI (reg:HI 49 [ k ])
> >                      (reg:HI 48)))
> >              (set (reg:HI 47)
> >                  (mod:HI (reg:HI 49 [ k ])
> >                      (reg:HI 48)))
> >              (clobber (scratch:HI))
> >              (clobber (scratch:QI))
> >          ]) "t.c":5:5 602 {divmodhi4}
> >       (expr_list:REG_DEAD (reg:HI 48)
> >          (expr_list:REG_DEAD (reg:HI 49 [ k ])
> >              (nil))))
> > 
> > This leaves us with a conflict for pseudo 48 in the updated insn 9 since
> > register 22 is live here.
> > 
> > Fixed by pulling the sledge hammer and skipping any potential
> > combination if a hard register constraint is involved.  Ideally we would
> > skip based on the fact whether there is any usage of a hard register
> > referred by any hard register constraint between potentially combined
> > insns.
> > 
> > gcc/ChangeLog:
> > 
> >     * combine.cc (cant_combine_insn_p): Do not try to combine insns
> >     if hard register constraints are involved.
> > ---
> >   gcc/combine.cc | 21 +++++++++++++++++++++
> >   1 file changed, 21 insertions(+)
> > 
> > diff --git a/gcc/combine.cc b/gcc/combine.cc
> > index 816324f4735..a4e7aff971d 100644
> > --- a/gcc/combine.cc
> > +++ b/gcc/combine.cc
> > @@ -2229,6 +2229,27 @@ cant_combine_insn_p (rtx_insn *insn)
> >     if (!NONDEBUG_INSN_P (insn))
> >       return true;
> > +  /* Do not try to combine insns which make use of hard register 
> > constraints.
> > +     For example, assume that in the first insn operand r100 of exp_a is
> > +     constrained to hard register %5.
> > +
> > +     r101=exp_a(r100)
> > +     %5=...
> > +     r102=exp_b(r101)
> > +
> > +     Then combining the first insn into the last one creates a conflict for
> > +     pseudo r100 since hard register %5 is live for the last insn.  
> > Therefore,
> > +     skip for now.  This is a sledge hammer approach.  Ideally we would 
> > skip
> > +     based on the fact whether there is any definition of a hard register 
> > used
> > +     in a single register constraint between potentially combined insns.  
> > */
> > +
> > +  extract_insn (insn);
> > +  for (int nop = recog_data.n_operands - 1; nop >= 0; --nop)
> > +    {
> > +      if (strchr (recog_data.constraints[nop], '{'))
> > +   return true;
> > +    }
> > +
> >     /* Never combine loads and stores involving hard regs that are likely
> >        to be spilled.  The register allocator can usually handle such
> >        reg-reg moves by tying.  If we allow the combiner to make
> 

Reply via email to