Skip to content

Commit e0ff354

Browse files
[AArch64] Async unwind - Adjust unwind info in AArch64LoadStoreOptimizer
[Re-commit after fixing a dereference of "end" iterator] The AArch64LoadStoreOptimnizer pass may merge a register increment/decrement with a following memory operation. In doing so, it may break CFI by moving a stack pointer adjustment past the CFI instruction that described *that* adjustment. This patch fixes this issue by moving said CFI instruction after the merged instruction, where the SP increment/decrement actually takes place. Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D114547
1 parent 6f8feeb commit e0ff354

File tree

5 files changed

+46
-6
lines changed

5 files changed

+46
-6
lines changed

llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
// This file contains a pass that performs load / store related peephole
1010
// optimizations. This pass should be run after register allocation.
1111
//
12+
// The pass runs after the PrologEpilogInserter where we emit the CFI
13+
// instructions. In order to preserve the correctness of the unwind informaiton,
14+
// the pass should not change the order of any two instructions, one of which
15+
// has the FrameSetup/FrameDestroy flag or, alternatively, apply an add-hoc fix
16+
// to unwind information.
17+
//
1218
//===----------------------------------------------------------------------===//
1319

1420
#include "AArch64InstrInfo.h"
@@ -31,6 +37,7 @@
3137
#include "llvm/CodeGen/TargetRegisterInfo.h"
3238
#include "llvm/IR/DebugLoc.h"
3339
#include "llvm/MC/MCAsmInfo.h"
40+
#include "llvm/MC/MCDwarf.h"
3441
#include "llvm/MC/MCRegisterInfo.h"
3542
#include "llvm/Pass.h"
3643
#include "llvm/Support/CommandLine.h"
@@ -1762,6 +1769,28 @@ AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
17621769
return E;
17631770
}
17641771

1772+
static MachineBasicBlock::iterator
1773+
maybeMoveCFI(MachineInstr &MI, MachineBasicBlock::iterator MaybeCFI) {
1774+
auto End = MI.getParent()->end();
1775+
if (MaybeCFI == End ||
1776+
MaybeCFI->getOpcode() != TargetOpcode::CFI_INSTRUCTION ||
1777+
!(MI.getFlag(MachineInstr::FrameSetup) ||
1778+
MI.getFlag(MachineInstr::FrameDestroy)) ||
1779+
getLdStBaseOp(MI).getReg() != AArch64::SP)
1780+
return End;
1781+
1782+
const MachineFunction &MF = *MI.getParent()->getParent();
1783+
unsigned CFIIndex = MaybeCFI->getOperand(0).getCFIIndex();
1784+
const MCCFIInstruction &CFI = MF.getFrameInstructions()[CFIIndex];
1785+
switch (CFI.getOperation()) {
1786+
case MCCFIInstruction::OpDefCfa:
1787+
case MCCFIInstruction::OpDefCfaOffset:
1788+
return MaybeCFI;
1789+
default:
1790+
return End;
1791+
}
1792+
}
1793+
17651794
MachineBasicBlock::iterator
17661795
AArch64LoadStoreOpt::mergeUpdateInsn(MachineBasicBlock::iterator I,
17671796
MachineBasicBlock::iterator Update,
@@ -1771,6 +1800,12 @@ AArch64LoadStoreOpt::mergeUpdateInsn(MachineBasicBlock::iterator I,
17711800
"Unexpected base register update instruction to merge!");
17721801
MachineBasicBlock::iterator E = I->getParent()->end();
17731802
MachineBasicBlock::iterator NextI = next_nodbg(I, E);
1803+
1804+
// If updating the SP and the following instruction is CFA offset related CFI
1805+
// instruction move it after the merged instruction.
1806+
MachineBasicBlock::iterator CFI =
1807+
IsPreIdx ? maybeMoveCFI(*Update, next_nodbg(Update, E)) : E;
1808+
17741809
// Return the instruction following the merged instruction, which is
17751810
// the instruction following our unmerged load. Unless that's the add/sub
17761811
// instruction we're merging, in which case it's the one after that.
@@ -1808,7 +1843,10 @@ AArch64LoadStoreOpt::mergeUpdateInsn(MachineBasicBlock::iterator I,
18081843
.setMemRefs(I->memoperands())
18091844
.setMIFlags(I->mergeFlagsWith(*Update));
18101845
}
1811-
(void)MIB;
1846+
if (CFI != E) {
1847+
MachineBasicBlock *MBB = I->getParent();
1848+
MBB->splice(std::next(MIB.getInstr()->getIterator()), MBB, CFI);
1849+
}
18121850

18131851
if (IsPreIdx) {
18141852
++NumPreFolded;

llvm/test/CodeGen/AArch64/arm64-fp128.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,8 @@ define dso_local void @test_extend() {
420420
define fp128 @test_neg(fp128 %in) {
421421
; CHECK-LABEL: test_neg:
422422
; CHECK: // %bb.0:
423-
; CHECK-NEXT: .cfi_def_cfa_offset 16
424423
; CHECK-NEXT: str q0, [sp, #-16]!
424+
; CHECK-NEXT: .cfi_def_cfa_offset 16
425425
; CHECK-NEXT: ldrb w8, [sp, #15]
426426
; CHECK-NEXT: eor w8, w8, #0x80
427427
; CHECK-NEXT: strb w8, [sp, #15]

llvm/test/CodeGen/AArch64/fcopysign.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ declare half @llvm.copysign.f16(half %a, half %b)
1616
define fp128 @copysign0() {
1717
; CHECK-LABEL: copysign0:
1818
; CHECK: // %bb.0: // %entry
19-
; CHECK-NEXT: .cfi_def_cfa_offset 16
2019
; CHECK-NEXT: adrp x8, .LCPI0_0
2120
; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI0_0]
2221
; CHECK-NEXT: adrp x8, val_double
2322
; CHECK-NEXT: str q0, [sp, #-16]!
23+
; CHECK-NEXT: .cfi_def_cfa_offset 16
2424
; CHECK-NEXT: ldr x8, [x8, :lo12:val_double]
2525
; CHECK-NEXT: ldrb w9, [sp, #15]
2626
; CHECK-NEXT: and x8, x8, #0x8000000000000000
@@ -32,11 +32,11 @@ define fp128 @copysign0() {
3232
;
3333
; CHECK-NONEON-LABEL: copysign0:
3434
; CHECK-NONEON: // %bb.0: // %entry
35-
; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
3635
; CHECK-NONEON-NEXT: adrp x8, .LCPI0_0
3736
; CHECK-NONEON-NEXT: ldr q0, [x8, :lo12:.LCPI0_0]
3837
; CHECK-NONEON-NEXT: adrp x8, val_double
3938
; CHECK-NONEON-NEXT: str q0, [sp, #-16]!
39+
; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
4040
; CHECK-NONEON-NEXT: ldr x8, [x8, :lo12:val_double]
4141
; CHECK-NONEON-NEXT: ldrb w9, [sp, #15]
4242
; CHECK-NONEON-NEXT: and x8, x8, #0x8000000000000000
@@ -55,11 +55,11 @@ entry:
5555
define fp128@copysign1() {
5656
; CHECK-LABEL: copysign1:
5757
; CHECK: // %bb.0: // %entry
58-
; CHECK-NEXT: .cfi_def_cfa_offset 16
5958
; CHECK-NEXT: adrp x8, val_fp128
6059
; CHECK-NEXT: ldr q0, [x8, :lo12:val_fp128]
6160
; CHECK-NEXT: adrp x8, val_float
6261
; CHECK-NEXT: str q0, [sp, #-16]!
62+
; CHECK-NEXT: .cfi_def_cfa_offset 16
6363
; CHECK-NEXT: ldr w8, [x8, :lo12:val_float]
6464
; CHECK-NEXT: ldrb w9, [sp, #15]
6565
; CHECK-NEXT: and w8, w8, #0x80000000
@@ -71,11 +71,11 @@ define fp128@copysign1() {
7171
;
7272
; CHECK-NONEON-LABEL: copysign1:
7373
; CHECK-NONEON: // %bb.0: // %entry
74-
; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
7574
; CHECK-NONEON-NEXT: adrp x8, val_fp128
7675
; CHECK-NONEON-NEXT: ldr q0, [x8, :lo12:val_fp128]
7776
; CHECK-NONEON-NEXT: adrp x8, val_float
7877
; CHECK-NONEON-NEXT: str q0, [sp, #-16]!
78+
; CHECK-NONEON-NEXT: .cfi_def_cfa_offset 16
7979
; CHECK-NONEON-NEXT: ldr w8, [x8, :lo12:val_float]
8080
; CHECK-NONEON-NEXT: ldrb w9, [sp, #15]
8181
; CHECK-NONEON-NEXT: and w8, w8, #0x80000000

llvm/test/CodeGen/AArch64/swifttail-call.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ define swifttailcc void @caller_to8_from0() #0 {
3636
ret void
3737

3838
; COMMON: str {{x[0-9]+}}, [sp, #-16]!
39+
; COMMON-NEXT: .cfi_def_cfa_offset 16
3940
; COMMON-NEXT: b callee_stack8
4041
}
4142

llvm/test/CodeGen/AArch64/tail-call.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ define fastcc void @caller_to8_from0() #0 {
3636
ret void
3737

3838
; COMMON: str {{x[0-9]+}}, [sp, #-16]!
39+
; COMMON-NEXT: .cfi_def_cfa_offset 16
3940
; COMMON-NEXT: b callee_stack8
4041
}
4142

0 commit comments

Comments
 (0)