Delay slot filling - what still matters, and what doesn't matter so much anymore?

Jeff Law law@redhat.com
Thu Apr 18 04:22:00 GMT 2013


On 04/17/2013 03:52 PM, Steven Bosscher wrote:
> First of all: What is still important to handle?
>
> It's clear that the expectations in reorg.c are "anything goes" but
> modern RISCs (everything since the PA-8000, say) probably have some
> limitations on what is helpful to have, or not have, in a delay slot.
> According to the comments in pa.h about MASK_JUMP_IN_DELAY, having
> jumps in delay slots of other jumps is one such thing: They don't
> bring benefit to the PA-8000 and they don't work with DWARF2 CFI. As
> far as I know, SPARC and MIPS don't allow jumps in delay slots, SH
> looks like it doesn't allow it either, and CRIS can do it for short
> branches but doesn't do because the trade-off between benefit and
> machine description complexity comes out negative.
Note that sparc and/or mips might use the adjust the return pointer 
trick.  I know it wasn't my idea when I added it to the PA.

Now the PA really can do jumps in the delay slot of another jump, but 
the  semantics are such that it's not all that helpful and we've never 
tried to model it.  You effectively get a single instruction executed at 
the first branch target, then you transfer to the second branch target 
IIRC.  It's actually pretty natural semantics once you look at the pc 
queues work on the PA.



  On the scheduler
> implementation side: Branches as delayed insns in delay slots of other
> branches is impossible to express in the CFG (at least in GCC, but I
> think in general it can't be done cleanly). Therefore I want to drop
> support for branches in delay slots. What do you think about this?
Certainly no need to support it in the generic case.  The only question 
is whether or not it's worth supporting the adjust the return pointer in 
the delay slot stuff.  Given an target without call/ret predictor stack, 
it can be a singificant advantage.  Such things might exist in the 
embedded space.




>
> What about multiple delay slots? It looks like reorg.c has code to
> handle insns with multiple delay slots, but there currently are no GCC
> targets in the FSF tree that have insns with multiple delay slots and
> that use define_delay.
Ping Hans, I think he was the last person who tried to deal with reorg 
and multiple delay slots (c4x?).  I certainly wouldn't lose any sleep if 
we killed the limit support for multiple delay slots.


>
>
> Another thing I completely fail to grasp, is how the pipeline
> scheduler and delay slots interact. Doesn't dbr_schedule destroy all
> the good work schedule_insns has tried to do? If so, how much does
> that hurt on modern RISCs?
It really depends on how the slot is filled and how far in the insn 
chain you had to look.  You're usually just ask likely to improve the 
schedule as you are to muck it up.  Also remember you're dealing stuff 
at block boundaries, where the scheduler really isn't helping much anyway.

There's always a tradeoff here.  It could always be improved by having 
the scheduler mark insns which are good candidates (scheduling-wise) for 
filling slots.  I certainly pondered this a couple decades ago when I 
cared about delay slot filling on in-order targets :-)  Oh yea, those 
hints have to be directional since it may be good to move an insn 
earlier to fill a path leading to the insn, but it may not be good to 
move it later to fill a branch after the insn.

>
>
> Related question: What, if anything, currently prevents dbr_schedule
> from causing pipeline stalls by stuffing a long-latency insn in a
> delay slot? I'm currently using a cost function using:
This has generally been left to ports to sort out.   My experience was 
that loads/stores were often OK to put into a delay slot.  A large part 
of the reason for this is when we fill via the backwards walk, we're not 
doing anything speculatively.

A nullified slot is different in that it's usually implemented by 
cancelling out the last stage in the pipeline.  So even if you nullify, 
you still have to go through the entire pipeline.  For something like an 
fpsqrt or fpdiv, that's *really* bad.

>
> What do you think will be a good strategy to deal with this (short of
> integrating delay slot filling in the scheduler proper)? Should I try
> to find cost==0 delay slot candidates, and only fill slots with cost>0
> candidates if nothing cheap is available? Prefer a nop over cost>0
> candidates? Ignore insn_default_latency?
It's really been left to the backends to deal with.  So for example, on 
the PA anything which touched the FPU was disallowed in a nullified slot.



>
>
> Another thing I noticed about targets with delay slots that can be
> nullified, is that at least some of the ifcvt.c transformations could
> be applied to fill more delay slots (obviously if_case_1 and
> if_case_2. In reorg.c, optimize_skip does some kind of if-conversion.
> Has anyone looked at whether optimize_skip still does something, and
> derived a test case for that?
I doubt anyone has looked at it recently.  It pre-dates our 
if-conversion code by a decade or more.


Jeff



More information about the Gcc mailing list