This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 3/6] Allow jumps in epilogues
On 03/23/2011 09:48 AM, Bernd Schmidt wrote:
>> With no more code than this, I cannot believe you're generating correct
>> unwind info anymore.
>
> Why not? Are you worried about the code at the destination of the jump?
> That should be preceded by another block falling through into it which
> also has a NOTE_INSN_EPILOGUE_BEG.
>
> If that isn't the problem you have in mind, what is and how can we test
> for it?
body
body
restore r1 XXX
restore r2 XXX
jmp L2 XXX
L1: body YYY
body YYY
restore r2
L2: restore r3
return
Assume for the moment that "restore" on this target is something that
can't be delayed or repeated. E.g. a pop, rather than a move which
leaves the saved value in memory at a unknown offset from the CFA.
This means we have to emit unwind directives immediately after the
restore insn and cannot delay the epilogue unwind until we deallocate
the entire stack frame.
This means that your patch either gets the unwind info wrong for
the XXX sequence or the YYY sequence.
Correct unwind info would look like
body
body
.cfi_remember_state
restore r1
.cfi_restore r1
restore r2
.cfi_restore r2
jmp L2
.cfi_restore_state
L1: body
body
restore r2
.cfi_restore r2
L2: // validate the unwind info across the CFG making sure that the incoming
// edges contain the same unwind info here.
restore r3
.cfi_restore r3
return
In general, with shrink-wrapping, we can have essentially arbitrary
differences in unwind info between blocks that are sequential. We have
to be prepared to fully adjust the unwind state between blocks.
Assume a { x } is the set of registers saved into the stack frame in a
given block. We have both incoming and outgoing sets.
foo: // in: { }
cmp r1,r2
jne L1 // out: { }
L0: // in: { }
save r8
save r9
body
... // out: { r8, r9 }
L2: // in: { r8, r9, r10 }
body
body
... // out: { r8, r9, r10 }
L1: // in: { }
save r8
save r9
save r10
body
... // out: { r8, r9, r10 }
L3: // in: { r8, r9, r10 }
restore r10 // out: { r8, r9 }
L4: // in: { r8, r9 }
restore r9
restore r8
return
This layout requires more than just .cfi_remember_state/restore_state
between blocks. We have to be prepared to emit full unwind info at
any point. Assume cfi info marked with XXX exists between basic blocks
to fixup the transition points:
L0: save r8
save r9
.cfi_offset r8,x
.cfi_offset r9,y
body
.cfi_offset r10,z XXX
L2: body
body
.cfi_restore r8 XXX
.cfi_restore r9 XXX
.cfi_restore r10 XXX
L1: save r8
save r9
save r10
.cfi_offset r8,x
.cfi_offset r9,y
.cfi_offset r10,z
body
If this isn't clear, please ask questions. The problem of unwinding is
way more complicated than what you appear to be assuming.
r~