-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ARM] Do not emit unwind tables when saving LR around outlined call #69611
Conversation
@llvm/pr-subscribers-backend-arm Author: None (ostannard) ChangesIn some cases, the machine outliner needs to preserve LR across an The outliner code already avoided generating CFI instructions, but EHABI This is my first multi-commit change done through github, it it OK to do this as one PR, or should I raise separate PRs for the two preparatory commits? Patch is 40.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/69611.diff 6 Files Affected:
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 1ffdde0360cf623..bc94b4cd2079caa 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -6450,20 +6450,21 @@ void ARMBaseInstrInfo::saveLROnStack(MachineBasicBlock &MBB,
MachineBasicBlock::iterator It, bool CFI,
bool Auth) const {
int Align = std::max(Subtarget.getStackAlignment().value(), uint64_t(8));
+ unsigned MIFlags = CFI ? MachineInstr::FrameSetup : 0;
assert(Align >= 8 && Align <= 256);
if (Auth) {
assert(Subtarget.isThumb2());
// Compute PAC in R12. Outlining ensures R12 is dead across the outlined
// sequence.
BuildMI(MBB, It, DebugLoc(), get(ARM::t2PAC))
- .setMIFlags(MachineInstr::FrameSetup);
+ .setMIFlags(MIFlags);
BuildMI(MBB, It, DebugLoc(), get(ARM::t2STRD_PRE), ARM::SP)
.addReg(ARM::R12, RegState::Kill)
.addReg(ARM::LR, RegState::Kill)
.addReg(ARM::SP)
.addImm(-Align)
.add(predOps(ARMCC::AL))
- .setMIFlags(MachineInstr::FrameSetup);
+ .setMIFlags(MIFlags);
} else {
unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;
BuildMI(MBB, It, DebugLoc(), get(Opc), ARM::SP)
@@ -6471,7 +6472,7 @@ void ARMBaseInstrInfo::saveLROnStack(MachineBasicBlock &MBB,
.addReg(ARM::SP)
.addImm(-Align)
.add(predOps(ARMCC::AL))
- .setMIFlags(MachineInstr::FrameSetup);
+ .setMIFlags(MIFlags);
}
if (!CFI)
@@ -6526,6 +6527,7 @@ void ARMBaseInstrInfo::restoreLRFromStack(MachineBasicBlock &MBB,
MachineBasicBlock::iterator It,
bool CFI, bool Auth) const {
int Align = Subtarget.getStackAlignment().value();
+ unsigned MIFlags = CFI ? MachineInstr::FrameDestroy : 0;
if (Auth) {
assert(Subtarget.isThumb2());
// Restore return address PAC and LR.
@@ -6536,7 +6538,7 @@ void ARMBaseInstrInfo::restoreLRFromStack(MachineBasicBlock &MBB,
.addReg(ARM::SP)
.addImm(Align)
.add(predOps(ARMCC::AL))
- .setMIFlags(MachineInstr::FrameDestroy);
+ .setMIFlags(MIFlags);
// LR authentication is after the CFI instructions, below.
} else {
unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
@@ -6547,7 +6549,7 @@ void ARMBaseInstrInfo::restoreLRFromStack(MachineBasicBlock &MBB,
MIB.addReg(0);
MIB.addImm(Subtarget.getStackAlignment().value())
.add(predOps(ARMCC::AL))
- .setMIFlags(MachineInstr::FrameDestroy);
+ .setMIFlags(MIFlags);
}
if (CFI) {
diff --git a/llvm/lib/Target/ARM/ARMMachineFunctionInfo.cpp b/llvm/lib/Target/ARM/ARMMachineFunctionInfo.cpp
index aa9d8b54d963607..e842715445124c5 100644
--- a/llvm/lib/Target/ARM/ARMMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMMachineFunctionInfo.cpp
@@ -13,6 +13,18 @@ using namespace llvm;
void ARMFunctionInfo::anchor() {}
+yaml::ARMFunctionInfo::ARMFunctionInfo(const llvm::ARMFunctionInfo &MFI)
+ : LRSpilled(MFI.isLRSpilled()) {}
+
+void yaml::ARMFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
+ MappingTraits<ARMFunctionInfo>::mapping(YamlIO, *this);
+}
+
+void ARMFunctionInfo::initializeBaseYamlFields(
+ const yaml::ARMFunctionInfo &YamlMFI) {
+ LRSpilled = YamlMFI.LRSpilled;
+}
+
static bool GetBranchTargetEnforcement(const Function &F,
const ARMSubtarget *Subtarget) {
if (!Subtarget->isMClass() || !Subtarget->hasV7Ops())
diff --git a/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h b/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
index f7531ce78ccae4e..eea12a7d3f56874 100644
--- a/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
+++ b/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h
@@ -16,12 +16,17 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/Support/ErrorHandling.h"
#include <utility>
namespace llvm {
+namespace yaml {
+struct ARMFunctionInfo;
+} // end namespace yaml
+
class ARMSubtarget;
/// ARMFunctionInfo - This class is derived from MachineFunctionInfo and
@@ -293,8 +298,29 @@ class ARMFunctionInfo : public MachineFunctionInfo {
}
bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
+
+ void initializeBaseYamlFields(const yaml::ARMFunctionInfo &YamlMFI);
};
+namespace yaml {
+struct ARMFunctionInfo final : public yaml::MachineFunctionInfo {
+ bool LRSpilled;
+
+ ARMFunctionInfo() = default;
+ ARMFunctionInfo(const llvm::ARMFunctionInfo &MFI);
+
+ void mappingImpl(yaml::IO &YamlIO) override;
+ ~ARMFunctionInfo() = default;
+};
+
+template <> struct MappingTraits<ARMFunctionInfo> {
+ static void mapping(IO &YamlIO, ARMFunctionInfo &MFI) {
+ YamlIO.mapOptional("isLRSpilled", MFI.LRSpilled);
+ }
+};
+
+} // end namespace yaml
+
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index a80d485e750beba..0348ae20fbf1eb5 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -30,6 +30,7 @@
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
+#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/CodeGen/Passes.h"
@@ -619,3 +620,23 @@ void ARMPassConfig::addPreEmitPass2() {
addPass(createEHContGuardCatchretPass());
}
}
+
+yaml::MachineFunctionInfo *
+ARMBaseTargetMachine::createDefaultFuncInfoYAML() const {
+ return new yaml::ARMFunctionInfo();
+}
+
+yaml::MachineFunctionInfo *
+ARMBaseTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
+ const auto *MFI = MF.getInfo<ARMFunctionInfo>();
+ return new yaml::ARMFunctionInfo(*MFI);
+}
+
+bool ARMBaseTargetMachine::parseMachineFunctionInfo(
+ const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
+ SMDiagnostic &Error, SMRange &SourceRange) const {
+ const auto &YamlMFI = static_cast<const yaml::ARMFunctionInfo &>(MFI);
+ MachineFunction &MF = PFS.MF;
+ MF.getInfo<ARMFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
+ return false;
+}
diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.h b/llvm/lib/Target/ARM/ARMTargetMachine.h
index 1754382692baadb..69d8fa8ada64983 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.h
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.h
@@ -83,6 +83,14 @@ class ARMBaseTargetMachine : public LLVMTargetMachine {
// Addrspacecasts are always noops.
return true;
}
+
+ yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const override;
+ yaml::MachineFunctionInfo *
+ convertFuncInfoToYAML(const MachineFunction &MF) const override;
+ bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &,
+ PerFunctionMIParsingState &PFS,
+ SMDiagnostic &Error,
+ SMRange &SourceRange) const override;
};
/// ARM/Thumb little endian target machine.
diff --git a/llvm/test/CodeGen/ARM/machine-outliner-noreturn.mir b/llvm/test/CodeGen/ARM/machine-outliner-noreturn.mir
new file mode 100644
index 000000000000000..922b3e77b42a785
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/machine-outliner-noreturn.mir
@@ -0,0 +1,645 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -run-pass=machine-outliner %s -o - | FileCheck %s
+
+--- |
+ source_filename = "test.cpp"
+ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ target triple = "thumbv8.1m.main-arm-none-eabi"
+
+ @__stack_chk_guard = external dso_local global ptr
+
+ define hidden void @_Z2F3v() #0 {
+ entry:
+ %StackGuardSlot = alloca ptr, align 4
+ %i1 = alloca i8, i32 undef, align 8
+ ret void
+ }
+
+ declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #1
+
+ define hidden void @_Z3F38i(i32 noundef %P0) #0 {
+ entry:
+ %StackGuardSlot = alloca ptr, align 4
+ unreachable
+
+ cond.false: ; preds = %entry
+ ret void
+
+ cond.end: ; preds = %entry
+ ret void
+ }
+
+ declare void @__aeabi_assert(ptr, ptr, i32)
+
+ define hidden void @_Z3F63v(ptr %agg.result) #0 {
+ entry:
+ %StackGuardSlot = alloca ptr, align 4
+ ret void
+ }
+
+ define hidden void @_Z3F94iiz(i32 %P0, i32 %P1, ...) #0 {
+ entry:
+ %StackGuardSlot = alloca ptr, align 4
+ unreachable
+
+ cond.false: ; preds = %entry
+ unreachable
+
+ cond.end: ; preds = %cond.false, %entry
+ unreachable
+
+ cond.false3: ; preds = %cond.end
+ unreachable
+
+ cond.end4: ; preds = %cond.false3, %cond.end
+ unreachable
+ }
+
+ declare ptr @llvm.returnaddress(i32 immarg) #2
+
+ declare void @llvm.va_start(ptr) #3
+
+ declare void @__cxa_throw(ptr, ptr, ptr)
+
+ declare ptr @llvm.stackguard() #3
+
+ declare void @llvm.stackprotector(ptr, ptr) #3
+
+ attributes #0 = { minsize sspreq }
+ attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }
+ attributes #2 = { nocallback nofree nosync nounwind willreturn memory(none) }
+ attributes #3 = { nocallback nofree nosync nounwind willreturn }
+ attributes #4 = { noreturn }
+
+...
+---
+name: _Z2F3v
+alignment: 4
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHCatchret: false
+hasEHScopes: false
+hasEHFunclets: false
+isOutlined: false
+debugInstrRef: false
+failsVerification: false
+tracksDebugUserValues: true
+registers: []
+liveins: []
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 24
+ offsetAdjustment: -16
+ maxAlignment: 4
+ adjustsStack: true
+ hasCalls: true
+ stackProtector: '%stack.0.StackGuardSlot'
+ functionContext: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: false
+ localFrameSize: 4
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack:
+ - { id: 0, name: StackGuardSlot, type: default, offset: -20, size: 4,
+ alignment: 4, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ local-offset: -4, debug-info-variable: '', debug-info-expression: '',
+ debug-info-location: '' }
+ - { id: 1, name: i1, type: variable-sized, offset: -20, alignment: 1,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ local-offset: -4, debug-info-variable: '', debug-info-expression: '',
+ debug-info-location: '' }
+ - { id: 2, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 3, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '$r7', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 4, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '$r6', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 5, name: '', type: spill-slot, offset: -16, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '$r4', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+entry_values: []
+callSites: []
+debugValueSubstitutions: []
+constants:
+ - id: 0
+ value: i32 -23388
+ alignment: 4
+ isTargetSpecific: false
+machineFunctionInfo:
+ isLRSpilled: true
+body: |
+ ; CHECK-LABEL: name: _Z2F3v
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: liveins: $r4, $r6, $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: frame-setup tPUSH 14 /* CC::al */, $noreg, undef $r2, undef $r3, killed $r4, killed $r6, $r7, killed $lr, implicit-def $sp, implicit $sp
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 24
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $r7, -8
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $r6, -12
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $r4, -16
+ ; CHECK-NEXT: $r7 = frame-setup tADDrSPi $sp, 4, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa $r7, 8
+ ; CHECK-NEXT: $r0 = t2MOVi16 target-flags(arm-lo16) @__stack_chk_guard, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: renamable $r1 = t2MVNi 91, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK-NEXT: $r0 = t2MOVTi16 killed $r0, target-flags(arm-hi16) @__stack_chk_guard, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: $r0 = tLDRi killed $r0, 0, 14 /* CC::al */, $noreg :: (dereferenceable invariant load (s32) from @__stack_chk_guard)
+ ; CHECK-NEXT: t2STRi8 killed renamable $r0, $r7, -12, 14 /* CC::al */, $noreg :: (volatile store (s32) into %stack.0.StackGuardSlot)
+ ; CHECK-NEXT: $r0 = tMOVr $sp, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: tSTRBi killed renamable $r1, renamable $r0, 2, 14 /* CC::al */, $noreg :: (store (s8) into %ir.i1 + 2, align 2, basealign 8)
+ ; CHECK-NEXT: renamable $r1 = tLDRpci %const.0, 14 /* CC::al */, $noreg :: (load (s32) from constant-pool)
+ ; CHECK-NEXT: tSTRHi killed renamable $r1, killed renamable $r0, 0, 14 /* CC::al */, $noreg :: (store (s16) into %ir.i1, align 8)
+ ; CHECK-NEXT: tBL 14 /* CC::al */, $noreg, @OUTLINED_FUNCTION_1, implicit-def $lr, implicit $sp, implicit-def $r1, implicit-def $lr, implicit $noreg, implicit $sp
+ ; CHECK-NEXT: renamable $r0 = t2LDRi8 $r7, -12, 14 /* CC::al */, $noreg :: (volatile load (s32) from %stack.0.StackGuardSlot)
+ ; CHECK-NEXT: $r1 = tLDRi killed $r1, 0, 14 /* CC::al */, $noreg :: (dereferenceable invariant load (s32) from @__stack_chk_guard)
+ ; CHECK-NEXT: tCMPr killed renamable $r1, killed renamable $r0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ ; CHECK-NEXT: t2IT 0, 2, implicit-def $itstate
+ ; CHECK-NEXT: $r4 = frame-destroy t2SUBri $r7, 8, 0 /* CC::eq */, $cpsr, $noreg, implicit $itstate
+ ; CHECK-NEXT: $sp = frame-destroy tMOVr $r4, 0 /* CC::eq */, $cpsr, implicit $itstate
+ ; CHECK-NEXT: frame-destroy tPOP_RET 0 /* CC::eq */, killed $cpsr, def $r4, def $r6, def $r7, def $pc, implicit killed $r4, implicit killed $itstate
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1.entry:
+ ; CHECK-NEXT: tBL 14 /* CC::al */, $noreg, &__stack_chk_fail, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+ bb.0.entry:
+ successors: %bb.1(0x00000800)
+ liveins: $r4, $r6, $lr
+
+ frame-setup tPUSH 14 /* CC::al */, $noreg, undef $r2, undef $r3, killed $r4, killed $r6, $r7, killed $lr, implicit-def $sp, implicit $sp
+ frame-setup CFI_INSTRUCTION def_cfa_offset 24
+ frame-setup CFI_INSTRUCTION offset $lr, -4
+ frame-setup CFI_INSTRUCTION offset $r7, -8
+ frame-setup CFI_INSTRUCTION offset $r6, -12
+ frame-setup CFI_INSTRUCTION offset $r4, -16
+ $r7 = frame-setup tADDrSPi $sp, 4, 14 /* CC::al */, $noreg
+ frame-setup CFI_INSTRUCTION def_cfa $r7, 8
+ $r0 = t2MOVi16 target-flags(arm-lo16) @__stack_chk_guard, 14 /* CC::al */, $noreg
+ renamable $r1 = t2MVNi 91, 14 /* CC::al */, $noreg, $noreg
+ $r0 = t2MOVTi16 killed $r0, target-flags(arm-hi16) @__stack_chk_guard, 14 /* CC::al */, $noreg
+ $r0 = tLDRi killed $r0, 0, 14 /* CC::al */, $noreg :: (dereferenceable invariant load (s32) from @__stack_chk_guard)
+ t2STRi8 killed renamable $r0, $r7, -12, 14 /* CC::al */, $noreg :: (volatile store (s32) into %stack.0.StackGuardSlot)
+ $r0 = tMOVr $sp, 14 /* CC::al */, $noreg
+ tSTRBi killed renamable $r1, renamable $r0, 2, 14 /* CC::al */, $noreg :: (store (s8) into %ir.i1 + 2, align 2, basealign 8)
+ renamable $r1 = tLDRpci %const.0, 14 /* CC::al */, $noreg :: (load (s32) from constant-pool)
+ tSTRHi killed renamable $r1, killed renamable $r0, 0, 14 /* CC::al */, $noreg :: (store (s16) into %ir.i1, align 8)
+ $r1 = t2MOVi16 target-flags(arm-lo16) @__stack_chk_guard, 14 /* CC::al */, $noreg
+ $r1 = t2MOVTi16 killed $r1, target-flags(arm-hi16) @__stack_chk_guard, 14 /* CC::al */, $noreg
+ renamable $r0 = t2LDRi8 $r7, -12, 14 /* CC::al */, $noreg :: (volatile load (s32) from %stack.0.StackGuardSlot)
+ $r1 = tLDRi killed $r1, 0, 14 /* CC::al */, $noreg :: (dereferenceable invariant load (s32) from @__stack_chk_guard)
+ tCMPr killed renamable $r1, killed renamable $r0, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ t2IT 0, 2, implicit-def $itstate
+ $r4 = frame-destroy t2SUBri $r7, 8, 0 /* CC::eq */, $cpsr, $noreg, implicit $itstate
+ $sp = frame-destroy tMOVr $r4, 0 /* CC::eq */, $cpsr, implicit $itstate
+ frame-destroy tPOP_RET 0 /* CC::eq */, killed $cpsr, def $r4, def $r6, def $r7, def $pc, implicit killed $r4, implicit killed $itstate
+
+ bb.1.entry:
+ tBL 14 /* CC::al */, $noreg, &__stack_chk_fail, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+
+...
+---
+name: _Z3F38i
+alignment: 4
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+callsEHReturn: false
+callsUnwindInit: false
+hasEHCatchret: false
+hasEHScopes: false
+hasEHFunclets: false
+isOutlined: false
+debugInstrRef: false
+failsVerification: false
+tracksDebugUserValues: true
+registers: []
+liveins:
+ - { reg: '$r0', virtual-reg: '' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 16
+ offsetAdjustment: 0
+ maxAlignment: 4
+ adjustsStack: true
+ hasCalls: true
+ stackProtector: '%stack.0.StackGuardSlot'
+ functionContext: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ hasTailCall: true
+ localFrameSize: 4
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack:
+ - { id: 0, name: StackGuardSlot, type: default, offset: -12, size: 4,
+ alignment: 4, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ local-offset: -4, debug-info-variable: '', debug-info-expression: '',
+ debug-info-location: '' }
+ - { id: 1, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+ - { id: 2, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '$r7', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+entry_values: []
+callSites: []
+debugValueSubstitutions: []
+constants: []
+machineFunctionInfo:
+ isLRSpilled: true
+body: |
+ ; CHECK-LABEL: name: _Z3F38i
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.3(0x40000000)
+ ; CHECK-NEXT: liveins: $r0, $r7, $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: frame-setup tPUSH 14 /* CC::al */, $noreg, undef $r5, und...
[truncated]
|
|
Code makes sense. The testcase is long, and it's hard to read because the outlined parts aren't obviously repetitive. How hard would it be to simplify? |
69a5dc1
to
2f24b0b
Compare
Simplified test case. |
Change-Id: Ib9cd2467dd262738652ffe1dbf0de579938f10b5
Change-Id: Ib9695cae262e7858de620329428e8496c2a0ec8c
In some cases, the machine outliner needs to preserve LR across an outlined call by pushing it onto the stack. Previously, this also generated unwind table instructions, which is incorrect because EHABI unwind tables cannot represent different stack frames a different points in the function, so the extra unwind info applied to the entire function. The outliner code already avoided generating CFI instructions, but EHABI unwind data is generated later from the actual instructions, so we need to avoid using the FrameSetup and FrameDestroy flags to prevent unwind data being generated. Change-Id: I2fa574f0d1b2138818c1ebd8997c7dcf51d274b7
2f24b0b
to
e340f2e
Compare
LGTM |
In some cases, the machine outliner needs to preserve LR across an
outlined call by pushing it onto the stack. Previously, this also
generated unwind table instructions, which is incorrect because EHABI
unwind tables cannot represent different stack frames a different points
in the function, so the extra unwind info applied to the entire
function.
The outliner code already avoided generating CFI instructions, but EHABI
unwind data is generated later from the actual instructions, so we need
to avoid using the FrameSetup and FrameDestroy flags to prevent unwind
data being generated.
This is my first multi-commit change done through github, it it OK to do this as one PR, or should I raise separate PRs for the two preparatory commits?