[llvm] 937ab6a - [ARM][MachineOutliner] Emit more CFI instructions
Momchil Velikov via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 9 07:26:43 PST 2020
Author: Momchil Velikov
Date: 2020-11-09T15:26:18Z
New Revision: 937ab6a7853ddb65373edec77f6d86741106cefb
URL: https://github.com/llvm/llvm-project/commit/937ab6a7853ddb65373edec77f6d86741106cefb
DIFF: https://github.com/llvm/llvm-project/commit/937ab6a7853ddb65373edec77f6d86741106cefb.diff
LOG: [ARM][MachineOutliner] Emit more CFI instructions
This patch make the outliner emit CFI instructions in a few more
places:
* after LR is restored, but before the return in an outlined
function
* around save/restore of LR to/from a register at calls to outlined
functions
* around save/restore of LR to/from the stack at calls to outlined
functions
The latter two only when the function does NOT spill LR. If the
function spills LR, then outliner generated saves/restores around
calls are not considered interesting for unwinding the frame.
Differential Revision: https://reviews.llvm.org/D89483
Added:
llvm/test/CodeGen/ARM/machine-outliner-cfi-1.ll
llvm/test/CodeGen/ARM/machine-outliner-cfi-2.ll
llvm/test/CodeGen/ARM/machine-outliner-cfi-3.ll
Modified:
llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
llvm/lib/Target/ARM/ARMBaseInstrInfo.h
llvm/test/CodeGen/ARM/machine-outliner-calls.mir
Removed:
################################################################################
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 6844b02b8528..12a04c5e9f31 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -6071,7 +6071,7 @@ ARMBaseInstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT,
}
void ARMBaseInstrInfo::saveLROnStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &It) const {
+ MachineBasicBlock::iterator It) const {
unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
int Align = -Subtarget.getStackAlignment().value();
BuildMI(MBB, It, DebugLoc(), get(Opc), ARM::SP)
@@ -6081,8 +6081,45 @@ void ARMBaseInstrInfo::saveLROnStack(MachineBasicBlock &MBB,
.add(predOps(ARMCC::AL));
}
+void ARMBaseInstrInfo::emitCFIForLRSaveOnStack(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const {
+ MachineFunction &MF = *MBB.getParent();
+ const MCRegisterInfo *MRI = Subtarget.getRegisterInfo();
+ unsigned DwarfLR = MRI->getDwarfRegNum(ARM::LR, true);
+ int Align = Subtarget.getStackAlignment().value();
+ // Add a CFI saying the stack was moved down.
+ int64_t StackPosEntry =
+ MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, Align));
+ BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
+ .addCFIIndex(StackPosEntry)
+ .setMIFlags(MachineInstr::FrameSetup);
+
+ // Add a CFI saying that the LR that we want to find is now higher than
+ // before.
+ int64_t LRPosEntry =
+ MF.addFrameInst(MCCFIInstruction::createOffset(nullptr, DwarfLR, -Align));
+ BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
+ .addCFIIndex(LRPosEntry)
+ .setMIFlags(MachineInstr::FrameSetup);
+}
+
+void ARMBaseInstrInfo::emitCFIForLRSaveToReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator It,
+ Register Reg) const {
+ MachineFunction &MF = *MBB.getParent();
+ const MCRegisterInfo *MRI = Subtarget.getRegisterInfo();
+ unsigned DwarfLR = MRI->getDwarfRegNum(ARM::LR, true);
+ unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
+
+ int64_t LRPosEntry = MF.addFrameInst(
+ MCCFIInstruction::createRegister(nullptr, DwarfLR, DwarfReg));
+ BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
+ .addCFIIndex(LRPosEntry)
+ .setMIFlags(MachineInstr::FrameSetup);
+}
+
void ARMBaseInstrInfo::restoreLRFromStack(
- MachineBasicBlock &MBB, MachineBasicBlock::iterator &It) const {
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const {
unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
MachineInstrBuilder MIB = BuildMI(MBB, It, DebugLoc(), get(Opc), ARM::LR)
.addReg(ARM::SP, RegState::Define)
@@ -6092,6 +6129,39 @@ void ARMBaseInstrInfo::restoreLRFromStack(
MIB.addImm(Subtarget.getStackAlignment().value()).add(predOps(ARMCC::AL));
}
+void ARMBaseInstrInfo::emitCFIForLRRestoreFromStack(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const {
+ // Now stack has moved back up...
+ MachineFunction &MF = *MBB.getParent();
+ const MCRegisterInfo *MRI = Subtarget.getRegisterInfo();
+ unsigned DwarfLR = MRI->getDwarfRegNum(ARM::LR, true);
+ int64_t StackPosEntry =
+ MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 0));
+ BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
+ .addCFIIndex(StackPosEntry)
+ .setMIFlags(MachineInstr::FrameDestroy);
+
+ // ... and we have restored LR.
+ int64_t LRPosEntry =
+ MF.addFrameInst(MCCFIInstruction::createRestore(nullptr, DwarfLR));
+ BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
+ .addCFIIndex(LRPosEntry)
+ .setMIFlags(MachineInstr::FrameDestroy);
+}
+
+void ARMBaseInstrInfo::emitCFIForLRRestoreFromReg(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator It) const {
+ MachineFunction &MF = *MBB.getParent();
+ const MCRegisterInfo *MRI = Subtarget.getRegisterInfo();
+ unsigned DwarfLR = MRI->getDwarfRegNum(ARM::LR, true);
+
+ int64_t LRPosEntry =
+ MF.addFrameInst(MCCFIInstruction::createRestore(nullptr, DwarfLR));
+ BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
+ .addCFIIndex(LRPosEntry)
+ .setMIFlags(MachineInstr::FrameDestroy);
+}
+
void ARMBaseInstrInfo::buildOutlinedFrame(
MachineBasicBlock &MBB, MachineFunction &MF,
const outliner::OutlinedFunction &OF) const {
@@ -6133,28 +6203,11 @@ void ARMBaseInstrInfo::buildOutlinedFrame(
// Insert a save before the outlined region
saveLROnStack(MBB, It);
-
- unsigned StackAlignment = Subtarget.getStackAlignment().value();
- const TargetSubtargetInfo &STI = MF.getSubtarget();
- const MCRegisterInfo *MRI = STI.getRegisterInfo();
- unsigned DwarfReg = MRI->getDwarfRegNum(ARM::LR, true);
- // Add a CFI saying the stack was moved down.
- int64_t StackPosEntry = MF.addFrameInst(
- MCCFIInstruction::cfiDefCfaOffset(nullptr, StackAlignment));
- BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
- .addCFIIndex(StackPosEntry)
- .setMIFlags(MachineInstr::FrameSetup);
-
- // Add a CFI saying that the LR that we want to find is now higher than
- // before.
- int64_t LRPosEntry = MF.addFrameInst(
- MCCFIInstruction::createOffset(nullptr, DwarfReg, StackAlignment));
- BuildMI(MBB, It, DebugLoc(), get(ARM::CFI_INSTRUCTION))
- .addCFIIndex(LRPosEntry)
- .setMIFlags(MachineInstr::FrameSetup);
+ emitCFIForLRSaveOnStack(MBB, It);
// Insert a restore before the terminator for the function. Restore LR.
restoreLRFromStack(MBB, Et);
+ emitCFIForLRRestoreFromStack(MBB, Et);
}
// If this is a tail call outlined function, then there's already a return.
@@ -6204,6 +6257,7 @@ MachineBasicBlock::iterator ARMBaseInstrInfo::insertOutlinedCall(
return It;
}
+ const ARMFunctionInfo &AFI = *C.getMF()->getInfo<ARMFunctionInfo>();
// Can we save to a register?
if (C.CallConstructionID == MachineOutlinerRegSave) {
unsigned Reg = findRegisterToSaveLRTo(C);
@@ -6211,15 +6265,23 @@ MachineBasicBlock::iterator ARMBaseInstrInfo::insertOutlinedCall(
// Save and restore LR from that register.
copyPhysReg(MBB, It, DebugLoc(), Reg, ARM::LR, true);
+ if (!AFI.isLRSpilled())
+ emitCFIForLRSaveToReg(MBB, It, Reg);
CallPt = MBB.insert(It, CallMIB);
copyPhysReg(MBB, It, DebugLoc(), ARM::LR, Reg, true);
+ if (!AFI.isLRSpilled())
+ emitCFIForLRRestoreFromReg(MBB, It);
It--;
return CallPt;
}
// We have the default case. Save and restore from SP.
saveLROnStack(MBB, It);
+ if (!AFI.isLRSpilled())
+ emitCFIForLRSaveOnStack(MBB, It);
CallPt = MBB.insert(It, CallMIB);
restoreLRFromStack(MBB, It);
+ if (!AFI.isLRSpilled())
+ emitCFIForLRRestoreFromStack(MBB, It);
It--;
return CallPt;
}
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
index 4132906d8bfa..bfcbe8e5a4f5 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -368,12 +368,33 @@ class ARMBaseInstrInfo : public ARMGenInstrInfo {
// Adds an instruction which saves the link register on top of the stack into
/// the MachineBasicBlock \p MBB at position \p It.
void saveLROnStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &It) const;
+ MachineBasicBlock::iterator It) const;
/// Adds an instruction which restores the link register from the top the
/// stack into the MachineBasicBlock \p MBB at position \p It.
void restoreLRFromStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &It) const;
+ MachineBasicBlock::iterator It) const;
+
+ /// Emit CFI instructions into the MachineBasicBlock \p MBB at position \p It,
+ /// for the case when the LR is saved on the stack.
+ void emitCFIForLRSaveOnStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator It) const;
+
+ /// Emit CFI instructions into the MachineBasicBlock \p MBB at position \p It,
+ /// for the case when the LR is saved in the register \p Reg.
+ void emitCFIForLRSaveToReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator It,
+ Register Reg) const;
+
+ /// Emit CFI instructions into the MachineBasicBlock \p MBB at position \p It,
+ /// after the LR is was restored from the stack.
+ void emitCFIForLRRestoreFromStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator It) const;
+
+ /// Emit CFI instructions into the MachineBasicBlock \p MBB at position \p It,
+ /// after the LR is was restored from a register.
+ void emitCFIForLRRestoreFromReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator It) const;
unsigned getInstBundleLength(const MachineInstr &MI) const;
diff --git a/llvm/test/CodeGen/ARM/machine-outliner-calls.mir b/llvm/test/CodeGen/ARM/machine-outliner-calls.mir
index 7880ddfb0051..a9a2a1357e10 100644
--- a/llvm/test/CodeGen/ARM/machine-outliner-calls.mir
+++ b/llvm/test/CodeGen/ARM/machine-outliner-calls.mir
@@ -295,7 +295,7 @@ body: |
; CHECK: liveins: $r11, $r10, $r9, $r8, $r7, $r6, $r5, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8, $lr
; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg
; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8
- ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, 8
+ ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -8
; CHECK: BL @bar, implicit-def dead $lr, implicit $sp
; CHECK: $r0 = MOVi 1, 14 /* CC::al */, $noreg, $noreg
; CHECK: $r1 = MOVi 1, 14 /* CC::al */, $noreg, $noreg
@@ -320,7 +320,7 @@ body: |
; CHECK: liveins: $r11, $r10, $r9, $r8, $r7, $r6, $r5, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8, $lr
; CHECK: early-clobber $sp = STR_PRE_IMM killed $lr, $sp, -8, 14 /* CC::al */, $noreg
; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8
- ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, 8
+ ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -8
; CHECK: BL @bar, implicit-def dead $lr, implicit $sp
; CHECK: $r0 = MOVi 2, 14 /* CC::al */, $noreg, $noreg
; CHECK: $r1 = MOVi 2, 14 /* CC::al */, $noreg, $noreg
@@ -335,7 +335,7 @@ body: |
; CHECK: liveins: $r11, $r10, $r9, $r8, $r6, $r5, $r4, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8, $lr
; CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg
; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8
- ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, 8
+ ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -8
; CHECK: tBL 14 /* CC::al */, $noreg, @bar, implicit-def dead $lr, implicit $sp
; CHECK: $r0 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg
; CHECK: $r1 = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg
@@ -348,7 +348,7 @@ body: |
; CHECK: liveins: $r11, $r10, $r9, $r8, $r6, $r5, $r4, $d15, $d14, $d13, $d12, $d11, $d10, $d9, $d8, $lr
; CHECK: early-clobber $sp = t2STR_PRE killed $lr, $sp, -8, 14 /* CC::al */, $noreg
; CHECK: frame-setup CFI_INSTRUCTION def_cfa_offset 8
- ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, 8
+ ; CHECK: frame-setup CFI_INSTRUCTION offset $lr, -8
; CHECK: tBL 14 /* CC::al */, $noreg, @bar, implicit-def dead $lr, implicit $sp
; CHECK: $r0 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg
; CHECK: $r1 = t2MOVi 2, 14 /* CC::al */, $noreg, $noreg
diff --git a/llvm/test/CodeGen/ARM/machine-outliner-cfi-1.ll b/llvm/test/CodeGen/ARM/machine-outliner-cfi-1.ll
new file mode 100644
index 000000000000..67c859c4bea8
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/machine-outliner-cfi-1.ll
@@ -0,0 +1,78 @@
+; RUN: llc --verify-machineinstrs --force-dwarf-frame-section %s -o - | FileCheck %s
+target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-unknown-unknown-eabi"
+
+; Derived from
+; volatile int a, b, c, d, e, f, g, h;
+;
+; int x() {
+; int r = (a + b) / (c + d) + e + f;
+; return r + 1;
+; }
+;
+;
+; int y() {
+; int r = (a + b) / (c + d) + e + f;
+; return r + 2;
+; }
+; Checks that CFI instruction are emitted around saves/restores of
+; the LR on stack.
+
+ at a = dso_local global i32 0, align 4
+ at b = dso_local global i32 0, align 4
+ at c = dso_local global i32 0, align 4
+ at d = dso_local global i32 0, align 4
+ at e = dso_local global i32 0, align 4
+ at f = dso_local global i32 0, align 4
+
+define dso_local i32 @x() local_unnamed_addr #0 {
+entry:
+ %0 = load volatile i32, i32* @a, align 4
+ %1 = load volatile i32, i32* @b, align 4
+ %add = add nsw i32 %1, %0
+ %2 = load volatile i32, i32* @c, align 4
+ %3 = load volatile i32, i32* @d, align 4
+ %add1 = add nsw i32 %3, %2
+ %div = sdiv i32 %add, %add1
+ %4 = load volatile i32, i32* @e, align 4
+ %5 = load volatile i32, i32* @f, align 4
+ %add2 = add i32 %div, 1
+ %add3 = add i32 %add2, %4
+ %add4 = add i32 %add3, %5
+ ret i32 %add4
+}
+; CHECK-LABEL: x:
+; CHECK: str lr, [sp, #-8]!
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: .cfi_offset lr, -8
+; CHECK-NEXT: bl OUTLINED_FUNCTION_0
+; CHECK-NEXT: ldr lr, [sp], #8
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: .cfi_restore lr
+
+define dso_local i32 @y() local_unnamed_addr #0 {
+entry:
+ %0 = load volatile i32, i32* @a, align 4
+ %1 = load volatile i32, i32* @b, align 4
+ %add = add nsw i32 %1, %0
+ %2 = load volatile i32, i32* @c, align 4
+ %3 = load volatile i32, i32* @d, align 4
+ %add1 = add nsw i32 %3, %2
+ %div = sdiv i32 %add, %add1
+ %4 = load volatile i32, i32* @e, align 4
+ %5 = load volatile i32, i32* @f, align 4
+ %add2 = add i32 %div, 2
+ %add3 = add i32 %add2, %4
+ %add4 = add i32 %add3, %5
+ ret i32 %add4
+}
+; CHECK-LABEL: y:
+; CHECK: str lr, [sp, #-8]!
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: .cfi_offset lr, -8
+; CHECK-NEXT: bl OUTLINED_FUNCTION_0
+; CHECK-NEXT: ldr lr, [sp], #8
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: .cfi_restore lr
+
+attributes #0 = { minsize nofree norecurse nounwind optsize }
diff --git a/llvm/test/CodeGen/ARM/machine-outliner-cfi-2.ll b/llvm/test/CodeGen/ARM/machine-outliner-cfi-2.ll
new file mode 100644
index 000000000000..e5dee8fd2938
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/machine-outliner-cfi-2.ll
@@ -0,0 +1,73 @@
+; RUN: llc --verify-machineinstrs --force-dwarf-frame-section %s -o - | FileCheck %s
+target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-unknown-unknown-eabi"
+
+; Derived from
+; volatile int a, b, c, d, e, f, g, h;
+;
+; int x() {
+; int r = a + b + c + d + e + f;
+; return r + 1;
+; }
+;
+;
+; int y() {
+; int r = a + b + c + d + e + f;
+; return r + 2;
+; }
+; Check CFI instructions when LR is saved/restored to/from a register.
+
+ at a = dso_local global i32 0, align 4
+ at b = dso_local global i32 0, align 4
+ at c = dso_local global i32 0, align 4
+ at d = dso_local global i32 0, align 4
+ at e = dso_local global i32 0, align 4
+ at f = dso_local global i32 0, align 4
+
+define dso_local i32 @x() local_unnamed_addr #0 {
+entry:
+ %0 = load volatile i32, i32* @a, align 4
+ %1 = load volatile i32, i32* @b, align 4
+ %2 = load volatile i32, i32* @c, align 4
+ %3 = load volatile i32, i32* @d, align 4
+ %4 = load volatile i32, i32* @e, align 4
+ %5 = load volatile i32, i32* @f, align 4
+ %add = add i32 %0, 1
+ %add1 = add i32 %add, %1
+ %add2 = add i32 %add1, %2
+ %add3 = add i32 %add2, %3
+ %add4 = add i32 %add3, %4
+ %add5 = add i32 %add4, %5
+ ret i32 %add5
+}
+; CHECK-LABEL: x:
+; CHECK: mov r3, lr
+; CHECK-NEXT: .cfi_register lr, r3
+; CHECK-NEXT: bl OUTLINED_FUNCTION_0
+; CHECK-NEXT: mov lr, r3
+; CHECK-NEXT: .cfi_restore lr
+
+define dso_local i32 @y() local_unnamed_addr #0 {
+entry:
+ %0 = load volatile i32, i32* @a, align 4
+ %1 = load volatile i32, i32* @b, align 4
+ %2 = load volatile i32, i32* @c, align 4
+ %3 = load volatile i32, i32* @d, align 4
+ %4 = load volatile i32, i32* @e, align 4
+ %5 = load volatile i32, i32* @f, align 4
+ %add = add i32 %0, 2
+ %add1 = add i32 %add, %1
+ %add2 = add i32 %add1, %2
+ %add3 = add i32 %add2, %3
+ %add4 = add i32 %add3, %4
+ %add5 = add i32 %add4, %5
+ ret i32 %add5
+}
+; CHECK-LABEL: y:
+; CHECK: mov r3, lr
+; CHECK-NEXT: .cfi_register lr, r3
+; CHECK-NEXT: bl OUTLINED_FUNCTION_0
+; CHECK-NEXT: mov lr, r3
+; CHECK-NEXT: .cfi_restore lr
+
+attributes #0 = { minsize nofree norecurse nounwind optsize }
diff --git a/llvm/test/CodeGen/ARM/machine-outliner-cfi-3.ll b/llvm/test/CodeGen/ARM/machine-outliner-cfi-3.ll
new file mode 100644
index 000000000000..13c055f811b7
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/machine-outliner-cfi-3.ll
@@ -0,0 +1,78 @@
+; RUN: llc --verify-machineinstrs --force-dwarf-frame-section %s -o - | FileCheck %s
+target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-unknown-unknown-eabi"
+
+; Derived from
+; __attribute__((noinline)) int h(int a, int b) { return a + b; }
+;
+; int f(int a, int b, int c, int d) {
+; if (a < 0)
+; return -1;
+; a = h(a, b);
+; return 2 + a * (a + b) / (c + d);
+; }
+;
+; int g(int a, int b, int c, int d) {
+; if (a < 0)
+; return -1;
+; a = h(a, b);
+; return 1 + a * (a + b) / (c + d);
+; }
+; Check CFI instructions inside the outlined function.
+
+define dso_local i32 @h(i32 %a, i32 %b) local_unnamed_addr #0 {
+entry:
+ %add = add nsw i32 %b, %a
+ ret i32 %add
+}
+
+define dso_local i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) local_unnamed_addr #1 {
+entry:
+ %cmp = icmp slt i32 %a, 0
+ br i1 %cmp, label %return, label %if.end
+
+if.end: ; preds = %entry
+ %call = tail call i32 @h(i32 %a, i32 %b) #2
+ %add = add nsw i32 %call, %b
+ %mul = mul nsw i32 %add, %call
+ %add1 = add nsw i32 %d, %c
+ %div = sdiv i32 %mul, %add1
+ %add2 = add nsw i32 %div, 2
+ br label %return
+
+return: ; preds = %entry, %if.end
+ %retval.0 = phi i32 [ %add2, %if.end ], [ -1, %entry ]
+ ret i32 %retval.0
+}
+
+define dso_local i32 @g(i32 %a, i32 %b, i32 %c, i32 %d) local_unnamed_addr #1 {
+entry:
+ %cmp = icmp slt i32 %a, 0
+ br i1 %cmp, label %return, label %if.end
+
+if.end: ; preds = %entry
+ %call = tail call i32 @h(i32 %a, i32 %b) #2
+ %add = add nsw i32 %call, %b
+ %mul = mul nsw i32 %add, %call
+ %add1 = add nsw i32 %d, %c
+ %div = sdiv i32 %mul, %add1
+ %add2 = add nsw i32 %div, 1
+ br label %return
+
+return: ; preds = %entry, %if.end
+ %retval.0 = phi i32 [ %add2, %if.end ], [ -1, %entry ]
+ ret i32 %retval.0
+}
+
+; CHECK-LABEL: OUTLINED_FUNCTION_0:
+; CHECK: str lr, [sp, #-8]!
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: .cfi_offset lr, -8
+; CHECK: ldr lr, [sp], #8
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: .cfi_restore lr
+; CHECK-NEXT: bx lr
+
+attributes #0 = { minsize noinline norecurse nounwind optsize readnone }
+attributes #1 = { minsize norecurse nounwind optsize readnone }
+attributes #2 = { minsize optsize }
More information about the llvm-commits
mailing list