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
>