Hi!

On Sun, Aug 16, 2020 at 06:28:44PM +0000, Pip Cet wrote:
> > > IIUC, the idea is that references to REG_CC, except for clobbers, are
> > > only introduced in the post-reload split pass, so it cannot be live
> > > before our define_split runs. Does that make sense?
> >
> > Yes, it does.  It has some huge restrictions (using the reg in inline
> > assembler can never work reliably, for example, so you'll have to
> > disallow that).
> 
> Is there any approach that doesn't suffer from that problem? My
> understanding was that we need to allow reload to insert CC-clobbering
> insns on this (and many other) architectures, and that there are so
> many places where reload might choose to do so (including before and
> after inline asm) that using the register prior to reload just isn't
> possible. I'd be glad to be wrong, though :-)

You can insert the clobber at expand time already.  That probably works
worse if most of your insns clobber the flags, but better if many do
not.

> Is it true that reload chooses which constraint alternative is used
> for each insn?

Register allocation does, yes (reload (or LRA) is the last step of that,
it has the last say).

> Is that information available somehow to post-reload
> splits?

In the "which_alternative" variable (not an attribute, an actual
variable; so use it from a C block or C expression).  There also is the
"alternative" attribute (which uses "which_alternative" under the hood),
which is handy for defining *other* attributes.

> The problem is that the "X" constraint matches whatever's
> there already, and doesn't replace it with the (scratch:CC) expression
> that would work, so I can't rewrite those insns not to clobber the CC
> reg.
> 
> For example, here's what I currently have:
> 
> (define_expand "mov<mode>"
>   [(parallel [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "")
>            (match_operand:MOVMODE 1 "general_operand" ""))
>           (clobber (reg:CC REG_CC))])]
>   ...)

Yeah, if you use a hard register at expand time already, it won't be
changed by register allocation.

> (define_insn "mov<mode>_insn"
>    [(set (match_operand:ALL1 0 "nonimmediate_operand" "=r,r  ,d    ,Qm
>   ,r ,q,r,*r")
>         (match_operand:ALL1 1 "nox_general_operand"   "r,Y00,n Ynn,r
> Y00,Qm,r,q,i"))
>    (clobber (match_scratch:CC 2 "=X,c,X,c,c,X,X,c"))]
>   ...)
> 
> That works, but it results in an incorrect CC clobber for, say,
> register-to-register movqi. For that, I'd need something like
> 
> (define_split
>   [(parallel [(set (match_operand:ALL1 0 "nonimmediate_operand")
>              (match_operand:ALL1 1 "nox_general_operand"))
>           (clobber (reg:CC REG_CC))])]
>   "reload_completed && REG_P (operands[0]) && REG_P (operands[1])"
>   [(parallel [(set (match_dup 0)
>            (match_dup 1))
>           (clobber (scratch:CC))])])
> 
> and so on, for all four constraint alternatives that don't actually
> clobber REG_CC (and also for a fifth which only rarely clobbers
> REG_CC). That's duplicated code, of course.

You can make it a define_insn_and_split where the condition can look
at the actual operands, or can use which_alternative.

> All this is at least somewhat academic: the code produced isn't
> drastically better after my cc conversion, but it's not usually any
> worse, and I'm still looking at assembler examples that are pessimized
> a little to find out how to fix them...

Great :-)

> > And earlier passes (like combine) cannot optimise this,
> 
> I'm not sure what "this" refers to: my understanding is that the idea
> is to let combine see CC-free code, or code with CC clobbers only,
> which it can then optimize, and only add "real" CC references after
> reload, so many optimizations should just work.

"This" was meant to refer to "anything to do with the CC reg".  If it
doesn't yet exist until after reload, of course no pass before it can do
anything with it :-)

> > But it is a pretty straightforward way to move from CC0 to the
> > modern world!
> 
> With the limitations of the reload pass being as they are, I don't
> really see a dramatically better alternative. I suppose we could
> explicitly save and restore CC flags around insns emitted when
> reload_in_progress is true, to simulate non-CC-clobbering add/mov insn
> patterns? That sounds like it would reduce code quality a lot, unless
> great care were taken to make sure all of the save/restore CC flags
> insns were optimized away in later passes.

Do you have move insns that do not clobber the CC reg?  If not, good
luck :-)

> In any case, thanks for the answers so far!

My pleasure.


Segher

Reply via email to