* register_operand in non-strict RTL
@ 2026-05-29 9:28 Georg-Johann Lay
2026-05-30 14:48 ` Segher Boessenkool
0 siblings, 1 reply; 6+ messages in thread
From: Georg-Johann Lay @ 2026-05-29 9:28 UTC (permalink / raw)
To: GCC Development
My question is this:
Is it allowed in non-strict RTL that a register_operand contains
a REG_P register that doesn't satisfy the constraint of the
operand? Given that the REG meets register_operand of course,
and that the machine mode matches.
To all of my knowledge, the answer is "yes": Prior to register
allocation, what matters are the insn predicates, not the insn
constraints.
In particular, a pass that operates on non-strict RTL map propagate
a (hard) register into a register_operand provided the predicate is
true, even in cases where the constraint doesn't match.
It's clear that such a transformation makes the register allocator's
life harder, but RA is supposed to handle that. Correct?
Context is that I am getting ICEs from RA for some __RTL test cases
that start at "ira".
Kind regards,
Johann
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: register_operand in non-strict RTL
2026-05-29 9:28 register_operand in non-strict RTL Georg-Johann Lay
@ 2026-05-30 14:48 ` Segher Boessenkool
2026-05-31 13:32 ` Georg-Johann Lay
2026-05-31 15:03 ` Georg-Johann Lay
0 siblings, 2 replies; 6+ messages in thread
From: Segher Boessenkool @ 2026-05-30 14:48 UTC (permalink / raw)
To: Georg-Johann Lay; +Cc: GCC Development
Hi!
On Fri, May 29, 2026 at 11:28:21AM +0200, Georg-Johann Lay via Gcc wrote:
> Is it allowed in non-strict RTL that a register_operand contains
> a REG_P register that doesn't satisfy the constraint of the
> operand? Given that the REG meets register_operand of course,
> and that the machine mode matches.
After reload (or LRA, the same thing really) has finished, all pseudos
are assigned hard registers, and predicates no longer have meaning,
indtead we now use constraints. This is what people sometimes call
"strict RTL", a terrible name (not in the least because it actually is
quite a bit more lenient! But it also doesn't describe at all anything
that is different, and it doesn't even say this is "late in the
pipeline" or something like that).
> To all of my knowledge, the answer is "yes": Prior to register
> allocation, what matters are the insn predicates, not the insn
> constraints.
Prior to RA you have the predicates only. During RA and reload you
have to satisfy both the predicates and tha constraints. After reload
only the constraints matter.
RA assigns hard registers to whatever it can. Not more though! That
is what reload (called "LRA" nowadays, although register allocation is
a tiny and relatively trivial part of its job) is for: it makes sure
the instruction stream will semantically do the same, don't look too
hard at performance though :-)
So after reload there are only real ("hardware") registers. "Strict
mode".
> In particular, a pass that operates on non-strict RTL map propagate
> a (hard) register into a register_operand provided the predicate is
> true, even in cases where the constraint doesn't match.
Yes, constraints aren't looked at at all so early.
> It's clear that such a transformation makes the register allocator's
> life harder, but RA is supposed to handle that. Correct?
Register alocation __tries to__ assign hard registers to all pseudos.
It cannot always, for various reasons (capacity problems is the
unavoidable one of course, but various conflict situations are nasty to
handle as well).
The reload pass will make things work. Traditional reload did
everything in one fell swoop, having a big to-the-side representation
that nothing else kept up-to-date. LRA instead works on tiny things at
a time (it is called the "Local RA" because of that), allowing it to
work directly on the RTL stream, there is no state anywhere else.
> Context is that I am getting ICEs from RA for some __RTL test cases
> that start at "ira".
Interesting! PR #s? (Hint hint hint :-) )
Segher
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: register_operand in non-strict RTL
2026-05-30 14:48 ` Segher Boessenkool
@ 2026-05-31 13:32 ` Georg-Johann Lay
2026-05-31 14:45 ` Segher Boessenkool
2026-05-31 15:03 ` Georg-Johann Lay
1 sibling, 1 reply; 6+ messages in thread
From: Georg-Johann Lay @ 2026-05-31 13:32 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: GCC Development
Am 30.05.26 um 16:48 schrieb Segher Boessenkool:
> Hi!
>
> On Fri, May 29, 2026 at 11:28:21AM +0200, Georg-Johann Lay via Gcc wrote:
>> Is it allowed in non-strict RTL that a register_operand contains
>> a REG_P register that doesn't satisfy the constraint of the
>> operand? Given that the REG meets register_operand of course,
>> and that the machine mode matches.
>
> After reload (or LRA, the same thing really) has finished, all pseudos
> are assigned hard registers, and predicates no longer have meaning,
> instead we now use constraints. This is what people sometimes call
> "strict RTL", a terrible name (not in the least because it actually is
> quite a bit more lenient! But it also doesn't describe at all anything
> that is different, and it doesn't even say this is "late in the
> pipeline" or something like that).
>
>> To all of my knowledge, the answer is "yes": Prior to register
>> allocation, what matters are the insn predicates, not the insn
>> constraints.
>
> Prior to RA you have the predicates only. During RA and reload you
> have to satisfy both the predicates and the constraints. After reload
> only the constraints matter.
>
> RA assigns hard registers to whatever it can. Not more though! That
> is what reload (called "LRA" nowadays, although register allocation is
> a tiny and relatively trivial part of its job) is for: it makes sure
> the instruction stream will semantically do the same, don't look too
> hard at performance though :-)
>
> So after reload there are only real ("hardware") registers. "Strict
> mode".
>
>> In particular, a pass that operates on non-strict RTL may propagate
>> a (hard) register into a register_operand provided the predicate is
>> true, even in cases where the constraint doesn't match.
>
> Yes, constraints aren't looked at at all so early.
>
>> It's clear that such a transformation makes the register allocator's
>> life harder, but RA is supposed to handle that. Correct?
>
> Register allocation __tries to__ assign hard registers to all pseudos.
> It cannot always, for various reasons (capacity problems is the
> unavoidable one of course, but various conflict situations are nasty to
> handle as well).
>
> The reload pass will make things work. Traditional reload did
> everything in one fell swoop, having a big to-the-side representation
> that nothing else kept up-to-date. LRA instead works on tiny things at
> a time (it is called the "Local RA" because of that), allowing it to
> work directly on the RTL stream, there is no state anywhere else.
>
>> Context is that I am getting ICEs from RA for some __RTL test cases
>> that start at "ira".
>
> Interesting! PR #s? (Hint hint hint :-) )
>
>
> Segher
Okay, so I opened https://gcc.gnu.org/PR125518 for that.
The similar https://gcc.gnu.org/PR121426 has been resolved by pulling
the sledge hammer as Stefan calls it: combine.cc rejects all insn
combinations that involve hard-reg constraints.
I understand that fixing RA stuff is hard and only a hand-full of
guys can do it, yet it would be great if insns with hard-reg
constraints could be insn-combined.
What's confusing is that IRA doesn't seem to care at all about the
upcoming conflict, and leaves the mess to LRA which must solve
it as an afterthought. And test cases like from PR125518 might
be much easier to track and resolve than bug reports with
real-world test cases with 1000 lines of code or more...
What my be related are similar "conflicts" with local register vars.
Suppose:
register int arg1 __asm("r24") = 0;
register int arg2 __asm("r22") = a / b;
where the division clobbers R24 or sets it as a side effect.
The docs say that this code is not supported, though it *could*
be supported if each register var was assigned its own pseudo,
and RA would handle it properly. The pseudos would be moved to
the respective hard reg right before the inline asm that uses them.
Would be nice if the users could write their code without knowing
whether an initialization / assignment triggers some libcall.
Johann
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: register_operand in non-strict RTL
2026-05-31 13:32 ` Georg-Johann Lay
@ 2026-05-31 14:45 ` Segher Boessenkool
0 siblings, 0 replies; 6+ messages in thread
From: Segher Boessenkool @ 2026-05-31 14:45 UTC (permalink / raw)
To: Georg-Johann Lay; +Cc: GCC Development
Hi!
On Sun, May 31, 2026 at 03:32:00PM +0200, Georg-Johann Lay via Gcc wrote:
> Am 30.05.26 um 16:48 schrieb Segher Boessenkool:
> > Interesting! PR #s? (Hint hint hint :-) )
Thank you!
> Okay, so I opened https://gcc.gnu.org/PR125518 for that.
>
> The similar https://gcc.gnu.org/PR121426 has been resolved by pulling
> the sledge hammer as Stefan calls it: combine.cc rejects all insn
> combinations that involve hard-reg constraints.
I don't agree with that patch at all, and I am the sole combine
maintainer, so I wonder what happened here.
The problem description itself already is nonsensical: "Fixed by pulling
the sledge hammer and rejecting any resulting insn which makes use of
hard register constraints." No instruction pattern ever "makes use of
constraints", that is confusing some basic concepts :-(
> I understand that fixing RA stuff is hard and only a hand-full of
> guys can do it, yet it would be great if insns with hard-reg
> constraints could be insn-combined.
And they can be, there is absolutely no reason to make such an
artificial limitation.
> What's confusing is that IRA doesn't seem to care at all about the
> upcoming conflict, and leaves the mess to LRA which must solve
> it as an afterthought. And test cases like from PR125518 might
> be much easier to track and resolve than bug reports with
> real-world test cases with 1000 lines of code or more...
The comflict partially is hand-written by the user unfortunately. It
isn't very surprising (or even unwanted!) that IRA gives up in some of
those cases. But reload (LRA now) should be able to handle this always.
> What my be related are similar "conflicts" with local register vars.
> Suppose:
>
> register int arg1 __asm("r24") = 0;
> register int arg2 __asm("r22") = a / b;
>
> where the division clobbers R24 or sets it as a side effect.
> The docs say that this code is not supported, though it *could*
> be supported if each register var was assigned its own pseudo,
> and RA would handle it properly.
That is how things were done years ago. Note I don't say "how things
worked back then": it didn't work.
> The pseudos would be moved to
> the respective hard reg right before the inline asm that uses them.
Local register vars are meaningless except when used in inline asm,
since quite a few years already (and that is because they didn't
actually work in other contexts since way longer already, and there was
absolutely no way to make them work, only on happy cases).
> Would be nice if the users could write their code without knowing
> whether an initialization / assignment triggers some libcall.
You cannot know in general, but usually you trivially do know.
Segher
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: register_operand in non-strict RTL
2026-05-30 14:48 ` Segher Boessenkool
2026-05-31 13:32 ` Georg-Johann Lay
@ 2026-05-31 15:03 ` Georg-Johann Lay
2026-05-31 19:21 ` Segher Boessenkool
1 sibling, 1 reply; 6+ messages in thread
From: Georg-Johann Lay @ 2026-05-31 15:03 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: GCC Development
Am 30.05.26 um 16:48 schrieb Segher Boessenkool:
> Prior to RA you have the predicates only. During RA and reload you
> have to satisfy both the predicates and the constraints. After reload
> only the constraints matter.
As far as I know there's at least one exception: RTL peepholes.
They use the predicates for matching, ignoring the constrains.
Such a peephole2 must FAIL when it can't digest some operand combo.
Johann
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: register_operand in non-strict RTL
2026-05-31 15:03 ` Georg-Johann Lay
@ 2026-05-31 19:21 ` Segher Boessenkool
0 siblings, 0 replies; 6+ messages in thread
From: Segher Boessenkool @ 2026-05-31 19:21 UTC (permalink / raw)
To: Georg-Johann Lay; +Cc: GCC Development
Hi!
On Sun, May 31, 2026 at 05:03:10PM +0200, Georg-Johann Lay wrote:
> Am 30.05.26 um 16:48 schrieb Segher Boessenkool:
> > Prior to RA you have the predicates only. During RA and reload you
> > have to satisfy both the predicates and the constraints. After reload
> > only the constraints matter.
>
> As far as I know there's at least one exception: RTL peepholes.
peephole2's, surely :-) Old peepholes are a lot of fun, but even I do
not trust people who think such fun is fun :-)
> They use the predicates for matching, ignoring the constrains.
Maybe some do, but in general the condition is just any piece of C code
resulting in zero or non-zero. Reusing existing predicates is not such
a great idea, see the confusion it apparently causes :-)
> Such a peephole2 must FAIL when it can't digest some operand combo.
In the preparation statement, yeah. Exacly like in define_expand and
define_split as well :-) Some things in GCC are nice and regular, as
unbelievable as that may sound!
Segher
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-05-31 19:21 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-29 9:28 register_operand in non-strict RTL Georg-Johann Lay
2026-05-30 14:48 ` Segher Boessenkool
2026-05-31 13:32 ` Georg-Johann Lay
2026-05-31 14:45 ` Segher Boessenkool
2026-05-31 15:03 ` Georg-Johann Lay
2026-05-31 19:21 ` Segher Boessenkool
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).