invalid delayed slot filling

Christian BRUEL christian.bruel@st.com
Fri Jan 12 16:51:00 GMT 2007


Ian Lance Taylor wrote:
> Christian BRUEL <christian.bruel@st.com> writes:
> 
> 
>>that's the point, 'mark_target_live_regs' doesn't scan the insns until
>>the return statement, but until 'stop_insn' that is the first insns
>>after the delayed branch (the first insn in the fall thru block), so
>>'end_of_function_needs' wasn't looked at.
> 
> 
> That shouldn't matter.  mark_target_live_regs starts with the set of
> register live at the start of the block.  That set has already been
> computed and should be correct.  In particular, if FPSCR is live at
> the start of the block, it should be in that set.  Then
> mark_target_live_regs walks through the insns.  For each register it
> finds the dies, it removes it from the set of live registers.  For
> each register it finds that comes alive, it adds it to the set of live
> registers.
>
fpscr is livein at the start of the block. then mark_target_live_regs 
scans the insns, then it finds a call, then it is set dead by 
regs_invalidated_by_call.

> I don't know why you are focusing on the registers live in the
> epilogue.  The registers live in the epilogue of a function being
> called are not necessarily live in the function making the call.
> 

I was not talking about the called function. I was talking about the 
current function, for which end_of_function_needs pertains. If the 
register is live in the epilogue (of the current function, the one 
having the delayed branch) then there is possibly liverange between the 
begin (it was livein) and the end of the function.

Note that it has to be a conservative approach because it's possible to 
have interference between the prologue and the epilogue and it's 
possible than the value is not set with the same value at exit than in 
entry thanks to lcm. Also the value can be inherited from predecessors. 
So mark_target_live_regs must assume than the fpscr value is live after 
the call.

>>but ... I'm realizing that fpscr_reg is not in the global_regs set,
>>which is correctly looked at at the call stmt.
>>
>>So updating CONDITIONAL_REGISTER_USAGE in sh.md to have FPSCR_REG a
>>global_regs cleanly seem to fix this problem.
> 
> I'm sorry, that is not correct either.  The global_regs array exists
> only to hold global register variables declared by the user.  It would
> not be correct for a backend to add an entry to that array.
> 

ok, I figured out that they could also be used by the compiler to tell 
that the register is valid across calls. I saw some hack like this 
(arm.h or unicosmk.h) so I thought it was standard. I was wrong then :-)

> Let me ask again: why is the register considered to be dead?
> 

because it is marked in 'regs_invalidated_by_call', because it is in the 
CALL_USED_REGISTERS macro.

I tried to remove the fpscr register from CALL_REALLY_USED_REGNO_P but 
that gives very bad code (it is automatically saved on function entry 
and restored on function exit, as explained in the manual chapter 14.)

> Ian
> 

so to summarize there were the following solutions (for now)

- use define_delay and never slot this instruction. ok as a workaround

- mark calls with an explicit setting of fpscr. But what about extern 
declarations or preemptible functions ?  you need to assume than all 
calls as setting fpscr and you already have this information in 
EPILOGUE_USE. I'm sure there is something more central.

- in mark_target_live_regs, when scanning a CALL, merge EPILOGUE_USE 
with current_live_regs : we established it is a bad solution.

- in mark_target_live_regs, when scanning a CALL, merge 
end_of_function_needs AFTER registers are made dead by 
regs_invalidated_by_call. I like this one, is it ruled out ?

- use global_regs. I thought it was used at some other places. but ok, 
just for users :-)

Christian



More information about the Gcc-patches mailing list