This is an archive of the discontinued LLVM Phabricator instance.

[AArch64] Async unwind - do not schedule frame setup/destroy
ClosedPublic

Authored by chill on Oct 22 2021, 9:17 AM.

Diff Detail

Event Timeline

chill created this revision.Oct 22 2021, 9:17 AM
chill requested review of this revision.Oct 22 2021, 9:17 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 22 2021, 9:17 AM
chill updated this revision to Diff 389531.Nov 24 2021, 10:17 AM
chill retitled this revision from [AArch64] Async unwind (1/6) - do not schedule frame setup/destroy to [AArch64] Async unwind - do not schedule frame setup/destroy.
chill added reviewers: MaskRay, t.p.northover, efriedma.
efriedma added inline comments.Nov 24 2021, 11:48 AM
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
1102

Not sure I understand the logic here. Can we just make CFI directives a scheduling barrier, like we do for SEH directives? Why are instructions that modify the frame pointer special?

chill marked an inline comment as done.Dec 7 2021, 3:03 AM
chill updated this revision to Diff 399010.Jan 11 2022, 10:36 AM
chill marked an inline comment as not done.
chill marked an inline comment as done.Jan 12 2022, 4:19 AM
chill added inline comments.
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
1102

The CFI instructions are already a scheduling barrier (MachineIntsr::isPosition()), but that's not enough, as the PostRA scheduler can still reorder non-CFI instructions in a way that makes the unwind info not instruction precise. As an example, on

int g(int);

int f(int x) {
	__asm__(""::: "x20", "x21", "x22");
	return 1 + g(x - 1);
}

After PEI we get

bb.0.entry:
  liveins: $w0, $lr, $x22, $x20, $x21
  early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp(tied-def 0), -6 :: (store (s64) into %stack.4), (store (s64) into %stack.3)
  frame-setup STRXui killed $x22, $sp, 2 :: (store (s64) into %stack.2)
  frame-setup STPXi killed $x21, killed $x20, $sp, 4 :: (store (s64) into %stack.1), (store (s64) into %stack.0)
  $fp = frame-setup ADDXri $sp, 0, 0
  frame-setup CFI_INSTRUCTION def_cfa $w29, 48
...

but then after the PostRA scheduling one of the stores and the assignment to FP get reordered

bb.0.entry:
  liveins: $w0, $lr, $x22, $x20, $x21
  early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp(tied-def 0), -6 :: (store (s64) into %stack.4), (store (s64) into %stack.3)
  frame-setup STRXui killed $x22, $sp, 2 :: (store (s64) into %stack.2)
  $fp = frame-setup ADDXri $sp, 0, 0
  frame-setup STPXi killed $x21, killed $x20, $sp, 4 :: (store (s64) into %stack.1), (store (s64) into %stack.0)
  frame-setup CFI_INSTRUCTION def_cfa $w29, 48
...

or

f:                                      // @f
	.cfi_startproc
// %bb.0:                               // %entry
	stp	x29, x30, [sp, #-48]!           // 16-byte Folded Spill
	str	x22, [sp, #16]                  // 8-byte Folded Spill
	mov	x29, sp
	stp	x21, x20, [sp, #32]             // 16-byte Folded Spill
	.cfi_def_cfa w29, 48
...

so now while the PC is at the `stp	x21, x20, [sp, #32]` the unwind info tells that
the CFA register is still SP and the FP has its original value.

Instructions that modify FP (and SP, but it's already handled) are special in that they (potentially) affect
what the current CFA is.
chill marked an inline comment as done.Jan 19 2022, 8:55 AM

Ping?

Oh, I understand the issue; we need to ensure that any instruction annotated by a CFI directive is not rescheduled away from the directive. (This isn't a problem for Windows EH because there's never more than one instruction between two SEH markings.)

I don't see how this is specific to instructions that modify fp, though. We end up with inaccurate CFI if we put any instruction between an instruction and its associated CFI directive, whether or not that instruction modifies fp. Can we explicitly check for instructions followed by a CFI directive?

chill added a comment.Jan 21 2022, 3:14 AM

Oh, I understand the issue; we need to ensure that any instruction annotated by a CFI directive is not rescheduled away from the directive. (This isn't a problem for Windows EH because there's never more than one instruction between two SEH markings.)

I don't see how this is specific to instructions that modify fp, though.

We end up with inaccurate CFI if we put any instruction between an instruction and its associated CFI directive, whether or not that instruction modifies fp.

No, not necessarily, but, that said ...

Can we explicitly check for instructions followed by a CFI directive?

... I think this would work. I'll give it a try.

chill updated this revision to Diff 402048.Jan 21 2022, 11:11 AM
This revision is now accepted and ready to land.Jan 24 2022, 3:55 PM
chill updated this revision to Diff 408854.Feb 15 2022, 6:49 AM

Just rebasing the whole chain for the sake of the remaining unreviewed patches.