Skip to content

Commit

Permalink
[AArch64][PAC] Reduce the size of synchronous CFI (#96377)
Browse files Browse the repository at this point in the history
For synchronous unwind tables, the call frame information can be
slightly reduced by bundling the `.cfi_negate_ra_state` instruction with
other CFI instructions in the prolog, saving 1 byte per function used
for `DW_CFA_advance_loc`.

This was suggested in
[D156428](https://reviews.llvm.org/D156428#4554317).
  • Loading branch information
igorkudrin authored Jul 12, 2024
1 parent cdd29f5 commit 941f794
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 47 deletions.
13 changes: 13 additions & 0 deletions llvm/lib/Target/AArch64/AArch64PointerAuth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ void AArch64PointerAuth::signLR(MachineFunction &MF,
auto &MFnI = *MF.getInfo<AArch64FunctionInfo>();
bool UseBKey = MFnI.shouldSignWithBKey();
bool EmitCFI = MFnI.needsDwarfUnwindInfo(MF);
bool EmitAsyncCFI = MFnI.needsAsyncDwarfUnwindInfo(MF);
bool NeedsWinCFI = MF.hasWinCFI();

MachineBasicBlock &MBB = *MBBI->getParent();
Expand Down Expand Up @@ -137,6 +138,18 @@ void AArch64PointerAuth::signLR(MachineFunction &MF,
}

if (EmitCFI) {
if (!EmitAsyncCFI) {
// Reduce the size of the generated call frame information for synchronous
// CFI by bundling the new CFI instruction with others in the prolog, so
// that no additional DW_CFA_advance_loc is needed.
for (auto I = MBBI; I != MBB.end(); ++I) {
if (I->getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
I->getFlag(MachineInstr::FrameSetup)) {
MBBI = I;
break;
}
}
}
unsigned CFIIndex =
MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ define void @a() "sign-return-address"="all" "sign-return-address-key"="b_key" {
; CHECK-NEXT: .cfi_b_key_frame
; V8A-NEXT: hint #27
; V83A-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ define void @a() "sign-return-address"="all" {
; CHECK-LABEL: a: // @a
; V8A: hint #25
; V83A: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand Down Expand Up @@ -54,7 +55,8 @@ define void @c() "sign-return-address"="all" {
; CHECK-LABEL: c: // @c
; V8A: hint #25
; V83A: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ define i64 @a(i64 %x) "sign-return-address"="non-leaf" "sign-return-address-key"
; CHECK: .cfi_b_key_frame
; V8A-NEXT: hint #27
; V83A-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand All @@ -30,7 +31,8 @@ define i64 @b(i64 %x) "sign-return-address"="non-leaf" "sign-return-address-key"
; CHECK: .cfi_b_key_frame
; V8A-NEXT: hint #27
; V83A-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand All @@ -52,7 +54,8 @@ define i64 @c(i64 %x) "sign-return-address"="non-leaf" "sign-return-address-key"
; CHECK: .cfi_b_key_frame
; V8A-NEXT: hint #27
; V83A-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ body: |
# CHECK: bb.0:
# CHECK: frame-setup EMITBKEY
# CHECK-NEXT: frame-setup PACIBSP implicit-def $lr, implicit $lr, implicit $sp
# CHECK-NEXT: frame-setup CFI_INSTRUCTION negate_ra_sign_state
# CHECK: frame-setup CFI_INSTRUCTION negate_ra_sign_state
# CHECK-NEXT: frame-setup CFI_INSTRUCTION
# CHECK-NOT: OUTLINED_FUNCTION_
# CHECK: bb.1:
# CHECK-NOT: OUTLINED_FUNCTION_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ define void @a() "sign-return-address"="all" {
; CHECK-LABEL: a: // @a
; V8A: hint #25
; V83A: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand All @@ -31,7 +32,8 @@ define void @b() "sign-return-address"="all" "sign-return-address-key"="b_key" {
; CHECK: .cfi_b_key_frame
; V8A-NEXT: hint #27
; V83A-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand All @@ -55,7 +57,8 @@ define void @c() "sign-return-address"="all" {
; CHECK-LABEL: c: // @c
; V8A: hint #25
; V83A: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ define void @a() #0 {
; CHECK: // %bb.0:
; CHECK-NEXT: .cfi_b_key_frame
; CHECK-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; CHECK-NOT: OUTLINED_FUNCTION_
%1 = alloca i32, align 4
%2 = alloca i32, align 4
Expand All @@ -34,7 +35,8 @@ define void @b() #0 {
; CHECK: // %bb.0:
; CHECK-NEXT: .cfi_b_key_frame
; CHECK-NEXT: pacibsp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; CHECK-NOT: OUTLINED_FUNCTION_
%1 = alloca i32, align 4
%2 = alloca i32, align 4
Expand All @@ -58,7 +60,8 @@ define void @c() #1 {
; CHECK: // %bb.0:
; CHECK-NEXT: .cfi_b_key_frame
; CHECK-NEXT: hint #27
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; CHECK-NOT: OUTLINED_FUNCTION_
%1 = alloca i32, align 4
%2 = alloca i32, align 4
Expand Down
12 changes: 8 additions & 4 deletions llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-thunk.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ define i32 @a() #0 {
; CHECK: // %bb.0: // %entry
; V8A-NEXT: hint #25
; V83A-NEXT: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; V8A: hint #29
; V8A-NEXT: ret
; V83A: retaa
Expand All @@ -26,7 +27,8 @@ define i32 @b() #0 {
; CHECK: // %bb.0: // %entry
; V8A-NEXT: hint #25
; V83A-NEXT: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; V8A: hint #29
; V8A-NEXT: ret
; V83A: retaa
Expand All @@ -41,7 +43,8 @@ define hidden i32 @c(ptr %fptr) #0 {
; CHECK: // %bb.0: // %entry
; V8A-NEXT: hint #25
; V83A-NEXT: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; V8A: hint #29
; V8A-NEXT: ret
; V83A: retaa
Expand All @@ -56,7 +59,8 @@ define hidden i32 @d(ptr %fptr) #0 {
; CHECK: // %bb.0: // %entry
; V8A-NEXT: hint #25
; V83A-NEXT: paciasp
; CHECK-NEXT: .cfi_negate_ra_state
; CHECK: .cfi_negate_ra_state
; CHECK-NEXT: .cfi_def_cfa_offset
; V8A: hint #29
; V8A-NEXT: ret
; V83A: retaa
Expand Down
7 changes: 5 additions & 2 deletions llvm/test/CodeGen/AArch64/pacbti-llvm-generated-funcs-2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ entry:
;; CHECK-LABEL: __llvm_gcov_writeout:
;; CHECK: .cfi_b_key_frame
;; CHECK-NEXT: pacibsp
;; CHECK-NEXT: .cfi_negate_ra_state
;; CHECK: .cfi_negate_ra_state
;; CHECK-NEXT: .cfi_def_cfa_offset

define internal void @__llvm_gcov_reset() unnamed_addr #2 {
entry:
Expand All @@ -55,7 +56,9 @@ entry:
;; CHECK-LABEL: __llvm_gcov_init:
;; CHECK: .cfi_b_key_frame
;; CHECK-NEXT: pacibsp
;; CHECK-NEXT: .cfi_negate_ra_state
;; CHECK-NEXT: .cfi_negate_ra_state
;; CHECK-NOT: .cfi_
;; CHECK: .cfi_endproc

attributes #0 = { norecurse nounwind readnone "sign-return-address"="all" "sign-return-address-key"="b_key" }
attributes #1 = { noinline "sign-return-address"="all" "sign-return-address-key"="b_key" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ define dso_local i32 @_Z3fooi(i32 %x) #0 {
; CHECK-V8A-LABEL: _Z3fooi:
; CHECK-V8A: // %bb.0: // %entry
; CHECK-V8A-NEXT: hint #25
; CHECK-V8A-NEXT: .cfi_negate_ra_state
; CHECK-V8A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-V8A-NEXT: .cfi_negate_ra_state
; CHECK-V8A-NEXT: .cfi_def_cfa_offset 16
; CHECK-V8A-NEXT: .cfi_offset w30, -16
; CHECK-V8A-NEXT: str w0, [sp, #8]
Expand All @@ -28,8 +28,8 @@ define dso_local i32 @_Z3fooi(i32 %x) #0 {
; CHECK-V83A-LABEL: _Z3fooi:
; CHECK-V83A: // %bb.0: // %entry
; CHECK-V83A-NEXT: paciasp
; CHECK-V83A-NEXT: .cfi_negate_ra_state
; CHECK-V83A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-V83A-NEXT: .cfi_negate_ra_state
; CHECK-V83A-NEXT: .cfi_def_cfa_offset 16
; CHECK-V83A-NEXT: .cfi_offset w30, -16
; CHECK-V83A-NEXT: str w0, [sp, #8]
Expand Down Expand Up @@ -57,7 +57,8 @@ return: ; No predecessors!
}

; For asynchronous unwind tables, we need to flip the value of RA_SIGN_STATE
; before and after the tail call.
; before and after the tail call. In the prolog, RA_SIGN_STATE is updated right
; after the corresponding 'PACIASP' instruction.
define hidden noundef i32 @baz_async(i32 noundef %a) #0 uwtable(async) {
; CHECK-V8A-LABEL: baz_async:
; CHECK-V8A: // %bb.0: // %entry
Expand Down Expand Up @@ -137,12 +138,14 @@ return: ; preds = %if.else, %if.then
; around the tail call. The tail-called function might throw an exception, but
; at this point we are set up to return into baz's caller, so the unwinder will
; never see baz's unwind table for that exception.
; The '.cfi_negate_ra_state' instruction in the prolog can be bundled with other
; CFI instructions to avoid emitting superfluous DW_CFA_advance_loc.
define hidden noundef i32 @baz_sync(i32 noundef %a) #0 uwtable(sync) {
; CHECK-V8A-LABEL: baz_sync:
; CHECK-V8A: // %bb.0: // %entry
; CHECK-V8A-NEXT: hint #25
; CHECK-V8A-NEXT: .cfi_negate_ra_state
; CHECK-V8A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-V8A-NEXT: .cfi_negate_ra_state
; CHECK-V8A-NEXT: .cfi_def_cfa_offset 16
; CHECK-V8A-NEXT: .cfi_offset w30, -16
; CHECK-V8A-NEXT: cbz w0, .LBB2_2
Expand All @@ -162,8 +165,8 @@ define hidden noundef i32 @baz_sync(i32 noundef %a) #0 uwtable(sync) {
; CHECK-V83A-LABEL: baz_sync:
; CHECK-V83A: // %bb.0: // %entry
; CHECK-V83A-NEXT: paciasp
; CHECK-V83A-NEXT: .cfi_negate_ra_state
; CHECK-V83A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
; CHECK-V83A-NEXT: .cfi_negate_ra_state
; CHECK-V83A-NEXT: .cfi_def_cfa_offset 16
; CHECK-V83A-NEXT: .cfi_offset w30, -16
; CHECK-V83A-NEXT: cbz w0, .LBB2_2
Expand Down
Loading

0 comments on commit 941f794

Please sign in to comment.