-
Notifications
You must be signed in to change notification settings - Fork 15.6k
[WIP][CodeGen] Enable early CFI #170610
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
base: users/ppenzin/ra_saverestore_split_calleesaves
Are you sure you want to change the base?
[WIP][CodeGen] Enable early CFI #170610
Conversation
Add ability to emit CFIs if the registers were saved / restored before prolog / epilog insertion.
|
@llvm/pr-subscribers-backend-risc-v Author: Petr Penzin (ppenzin) ChangesAdd ability to emit CFIs if the registers were saved / restored before prolog / epilog insertion. This has been split out from https://github.com/mgudim/llvm-project/tree/save_csr_in_ra3, and is PR 4 out of 5. Co-authored-by: Mikhail Gudim <mgudim@ventanamicro.com> Full diff: https://github.com/llvm/llvm-project/pull/170610.diff 8 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index c04cd33b3377a..fe3ebcd13b2bc 100644
--- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -25,16 +25,17 @@ namespace llvm {
class CalleeSavedInfo;
class MachineFunction;
class RegScavenger;
-
-namespace TargetStackID {
-enum Value {
- Default = 0,
- SGPRSpill = 1,
- ScalableVector = 2,
- WasmLocal = 3,
- ScalablePredicateVector = 4,
- NoAlloc = 255
-};
+ class ReachingDefInfo;
+
+ namespace TargetStackID {
+ enum Value {
+ Default = 0,
+ SGPRSpill = 1,
+ ScalableVector = 2,
+ WasmLocal = 3,
+ ScalablePredicateVector = 4,
+ NoAlloc = 255
+ };
}
/// Information about stack frame layout on the target. It holds the direction
@@ -212,6 +213,12 @@ class LLVM_ABI TargetFrameLowering {
/// for noreturn nounwind functions.
virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const;
+ /// If savesCSRsEarly is true, we don't really know where the CSRs are
+ /// saved. This function calculates where each CSR is at every point in the
+ /// function and inserts necessary CFIs. It has to run before frame indicies
+ /// are resolved.
+ virtual void emitCFIsEarly(MachineFunction &MF, ReachingDefInfo &RDA) const {}
+
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
virtual void emitPrologue(MachineFunction &MF,
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 2639edcfed0a2..b97c5cd4e98d5 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -36,6 +36,7 @@
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PEI.h"
+#include "llvm/CodeGen/ReachingDefAnalysis.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
@@ -79,6 +80,7 @@ namespace {
class PEIImpl {
RegScavenger *RS = nullptr;
+ ReachingDefInfo &RDI;
// MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee saved
// stack frame indexes.
@@ -125,7 +127,8 @@ class PEIImpl {
void insertZeroCallUsedRegs(MachineFunction &MF);
public:
- PEIImpl(MachineOptimizationRemarkEmitter *ORE) : ORE(ORE) {}
+ PEIImpl(ReachingDefInfo &RDI, MachineOptimizationRemarkEmitter *ORE)
+ : RDI(RDI), ORE(ORE) {}
bool run(MachineFunction &MF);
};
@@ -155,6 +158,7 @@ INITIALIZE_PASS_BEGIN(PEILegacy, DEBUG_TYPE, "Prologue/Epilogue Insertion",
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass)
+INITIALIZE_PASS_DEPENDENCY(ReachingDefInfoWrapperPass)
INITIALIZE_PASS_END(PEILegacy, DEBUG_TYPE,
"Prologue/Epilogue Insertion & Frame Finalization", false,
false)
@@ -171,6 +175,7 @@ void PEILegacy::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addPreserved<MachineLoopInfoWrapperPass>();
AU.addPreserved<MachineDominatorTreeWrapperPass>();
AU.addRequired<MachineOptimizationRemarkEmitterPass>();
+ AU.addRequired<ReachingDefInfoWrapperPass>();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -361,7 +366,8 @@ bool PEIImpl::run(MachineFunction &MF) {
bool PEILegacy::runOnMachineFunction(MachineFunction &MF) {
MachineOptimizationRemarkEmitter *ORE =
&getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
- return PEIImpl(ORE).run(MF);
+ auto &RDI = getAnalysis<ReachingDefInfoWrapperPass>().getRDI();
+ return PEIImpl(RDI, ORE).run(MF);
}
PreservedAnalyses
@@ -369,7 +375,8 @@ PrologEpilogInserterPass::run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM) {
MachineOptimizationRemarkEmitter &ORE =
MFAM.getResult<MachineOptimizationRemarkEmitterAnalysis>(MF);
- if (!PEIImpl(&ORE).run(MF))
+ auto &RDI = MFAM.getResult<ReachingDefAnalysis>(MF);
+ if (!PEIImpl(RDI, &ORE).run(MF))
return PreservedAnalyses::all();
return getMachineFunctionPassPreservedAnalyses()
@@ -1188,6 +1195,11 @@ void PEIImpl::calculateFrameObjectOffsets(MachineFunction &MF) {
void PEIImpl::insertPrologEpilogCode(MachineFunction &MF) {
const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
+ if (MF.getSubtarget().savesCSRsEarly()) {
+ RDI.reset();
+ TFI.emitCFIsEarly(MF, RDI);
+ }
+
// Add prologue to the function...
for (MachineBasicBlock *SaveBlock : SaveBlocks)
TFI.emitPrologue(MF, *SaveBlock);
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index f780375454b2a..17f4d0beabe31 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -14,6 +14,7 @@
#include "MCTargetDesc/RISCVBaseInfo.h"
#include "RISCVMachineFunctionInfo.h"
#include "RISCVSubtarget.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/CFIInstBuilder.h"
#include "llvm/CodeGen/LivePhysRegs.h"
@@ -21,6 +22,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/ReachingDefAnalysis.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/MC/MCDwarf.h"
@@ -2379,6 +2381,153 @@ bool RISCVFrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
return SuccMBB->isReturnBlock() && SuccMBB->size() == 1;
}
+struct CFIBuildInfo {
+ MachineBasicBlock *MBB;
+ MachineInstr *InsertAfterMI; // nullptr means insert at MBB.begin()
+ DebugLoc DL;
+ unsigned CFIIndex;
+};
+
+class EarlyCFIEmitter {
+public:
+ EarlyCFIEmitter(MachineFunction &MF_, const ReachingDefInfo &RDI_,
+ const RISCVInstrInfo &TII_, const RISCVRegisterInfo &TRI_,
+ const RISCVFrameLowering &TFI_)
+ : MF{MF_}, RDI{RDI_}, TII{TII_}, TRI{TRI_}, TFI{TFI_} {};
+ void trackRegisterAndEmitCFIs(
+ Register Reg, int64_t DwarfEHRegNum, MachineInstr &MI,
+ SmallVectorImpl<CFIBuildInfo> &CFIBuildInfos,
+ SmallPtrSetImpl<MachineInstr *> &VisitedRestorePoints,
+ SmallPtrSetImpl<MachineInstr *> &VisitedDefs);
+
+private:
+ MachineFunction &MF;
+ const ReachingDefInfo &RDI;
+ const RISCVInstrInfo &TII;
+ const RISCVRegisterInfo &TRI;
+ const RISCVFrameLowering &TFI;
+};
+
+void EarlyCFIEmitter::trackRegisterAndEmitCFIs(
+ Register Reg, int64_t DwarfEHRegNum, MachineInstr &MI,
+ SmallVectorImpl<CFIBuildInfo> &CFIBuildInfos,
+ SmallPtrSetImpl<MachineInstr *> &VisitedRestorePoints,
+ SmallPtrSetImpl<MachineInstr *> &VisitedDefs) {
+ if (VisitedRestorePoints.find(&MI) != VisitedRestorePoints.end())
+ return;
+ VisitedRestorePoints.insert(&MI);
+
+ SmallPtrSet<MachineInstr *, 2> Defs;
+ RDI.getGlobalReachingDefs(&MI, Reg, Defs);
+ if (Defs.empty())
+ // it's a live-in register at the entry block.
+ return;
+
+ int FrameIndex = std::numeric_limits<int>::min();
+ for (MachineInstr *Def : Defs) {
+ if (VisitedDefs.find(Def) != VisitedDefs.end())
+ continue;
+ VisitedDefs.insert(Def);
+
+ MachineBasicBlock &MBB = *Def->getParent();
+ const DebugLoc &DL = Def->getDebugLoc();
+
+ if (Register StoredReg = TII.isStoreToStackSlot(*Def, FrameIndex)) {
+ assert(FrameIndex == Reg.stackSlotIndex());
+
+ Register FrameReg;
+ StackOffset Offset = TFI.getFrameIndexReference(MF, FrameIndex, FrameReg);
+ int64_t FixedOffset = Offset.getFixed();
+ int64_t ScalableOffset = Offset.getScalable();
+
+ std::string CommentBuffer;
+ llvm::raw_string_ostream Comment(CommentBuffer);
+ int DwarfEHFrameReg = TRI.getDwarfRegNum(FrameReg, true);
+ Register LLVMReg = *TRI.getLLVMRegNum(DwarfEHRegNum, true);
+ Comment << printReg(LLVMReg, &TRI) << " @";
+ Comment << printReg(FrameReg, &TRI) << " + ";
+ Comment << "vlenb * " << ScalableOffset << " + ";
+ Comment << FixedOffset;
+ unsigned CFIIndex = MF.addFrameInst(
+ MCCFIInstruction::createLLVMRegAtScalableOffsetFromReg(
+ nullptr, DwarfEHRegNum, DwarfEHFrameReg, ScalableOffset,
+ FixedOffset, SMLoc(), Comment.str()));
+
+ CFIBuildInfos.push_back({&MBB, Def, DL, CFIIndex});
+ trackRegisterAndEmitCFIs(StoredReg, DwarfEHRegNum, *Def, CFIBuildInfos,
+ VisitedRestorePoints, VisitedDefs);
+ } else if (Register LoadedReg = TII.isLoadFromStackSlot(*Def, FrameIndex)) {
+ assert(LoadedReg == Reg);
+
+ unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRegister(
+ nullptr, DwarfEHRegNum, TRI.getDwarfRegNum(LoadedReg, true)));
+ CFIBuildInfos.push_back({&MBB, Def, DL, CFIIndex});
+ trackRegisterAndEmitCFIs(Register::index2StackSlot(FrameIndex),
+ DwarfEHRegNum, *Def, CFIBuildInfos,
+ VisitedRestorePoints, VisitedDefs);
+ } else if (auto DstSrc = TII.isCopyInstr(*Def)) {
+ Register DstReg = DstSrc->Destination->getReg();
+ Register SrcReg = DstSrc->Source->getReg();
+ assert(DstReg == Reg);
+
+ unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRegister(
+ nullptr, DwarfEHRegNum, TRI.getDwarfRegNum(DstReg, true)));
+ CFIBuildInfos.push_back({&MBB, Def, DL, CFIIndex});
+ trackRegisterAndEmitCFIs(SrcReg, DwarfEHRegNum, *Def, CFIBuildInfos,
+ VisitedRestorePoints, VisitedDefs);
+ } else
+ llvm_unreachable("Unexpected instruction");
+ }
+ return;
+}
+
+void RISCVFrameLowering::emitCFIsEarly(MachineFunction &MF,
+ ReachingDefInfo &RDI) const {
+ BitVector EarlyCSRs;
+ determineEarlyCalleeSaves(MF, EarlyCSRs);
+
+ SmallVector<MachineInstr *, 4> RestorePoints;
+ for (MachineBasicBlock &MBB : MF) {
+ if (MBB.isReturnBlock())
+ RestorePoints.push_back(&MBB.back());
+ }
+ SmallVector<CFIBuildInfo, 32> CFIBuildInfos;
+ const RISCVInstrInfo &TII = *STI.getInstrInfo();
+ const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
+ EarlyCFIEmitter EarlyCFIE(MF, RDI, TII, TRI, *STI.getFrameLowering());
+ const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
+ for (unsigned i = 0; CSRegs[i]; ++i) {
+ unsigned Reg = CSRegs[i];
+ if (!EarlyCSRs[Reg])
+ continue;
+ SmallPtrSet<MachineInstr *, 32> VisitedDefs;
+ for (MachineInstr *RestorePoint : RestorePoints) {
+ SmallPtrSet<MachineInstr *, 32> VisitedRestorePoints;
+ EarlyCFIE.trackRegisterAndEmitCFIs(Reg, TRI.getDwarfRegNum(Reg, true),
+ *RestorePoint, CFIBuildInfos,
+ VisitedRestorePoints, VisitedDefs);
+ }
+ }
+ for (CFIBuildInfo &Info : CFIBuildInfos) {
+ MachineBasicBlock *MBB = Info.MBB;
+ if (Info.InsertAfterMI) {
+ auto Bundler =
+ MIBundleBuilder(*MBB, ++(Info.InsertAfterMI->getIterator()));
+ Bundler.append(Info.InsertAfterMI->removeFromParent());
+ Bundler.append(
+ BuildMI(MBB, Info.DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(Info.CFIIndex)
+ ->removeFromParent());
+ finalizeBundle(*MBB, Bundler.begin(), Bundler.end());
+ } else {
+ BuildMI(*MBB, MBB->begin(), Info.DL,
+ TII.get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(Info.CFIIndex);
+ }
+ }
+ return;
+}
+
bool RISCVFrameLowering::isSupportedStackID(TargetStackID::Value ID) const {
switch (ID) {
case TargetStackID::Default:
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index b1835877ecd31..0658203def349 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -74,6 +74,8 @@ class RISCVFrameLowering : public TargetFrameLowering {
bool enableShrinkWrapping(const MachineFunction &MF) const override;
+ void emitCFIsEarly(MachineFunction &MF, ReachingDefInfo &RDI) const override;
+
bool isSupportedStackID(TargetStackID::Value ID) const override;
TargetStackID::Value getStackIDForScalableVectors() const override;
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index 3dcad527304a6..ef1576db80bd5 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -75,9 +75,10 @@ static cl::opt<bool> EnablePExtCodeGen(
"only partial codegen is currently supported)"),
cl::init(false), cl::Hidden);
-static cl::opt<bool> SaveCSREarly("riscv-save-csrs-early",
- cl::desc("Save CSRs early"),
- cl::init(false), cl::Hidden);
+static cl::opt<bool> RISCVSaveCSRsEarly(
+ "riscv-save-csrs-early",
+ cl::desc("Let register alloctor do csr saves/restores"), cl::init(false),
+ cl::Hidden);
void RISCVSubtarget::anchor() {}
@@ -221,8 +222,8 @@ bool RISCVSubtarget::enableMachinePipeliner() const {
return getSchedModel().hasInstrSchedModel();
}
- /// Enable use of alias analysis during code generation (during MI
- /// scheduling, DAGCombine, etc.).
+/// Enable use of alias analysis during code generation (during MI
+/// scheduling, DAGCombine, etc.).
bool RISCVSubtarget::useAA() const { return UseAA; }
unsigned RISCVSubtarget::getMinimumJumpTableEntries() const {
@@ -270,6 +271,4 @@ bool RISCVSubtarget::useMIPSCCMovInsn() const {
return UseMIPSCCMovInsn && HasVendorXMIPSCMov;
}
-bool RISCVSubtarget::savesCSRsEarly() const {
- return SaveCSREarly;
-}
+bool RISCVSubtarget::savesCSRsEarly() const { return RISCVSaveCSRsEarly; }
diff --git a/llvm/test/CodeGen/RISCV/O0-pipeline.ll b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
index 8714b286374a5..b308fc82a5489 100644
--- a/llvm/test/CodeGen/RISCV/O0-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
@@ -54,6 +54,7 @@
; CHECK-NEXT: Fixup Statepoint Caller Saved
; CHECK-NEXT: Lazy Machine Block Frequency Analysis
; CHECK-NEXT: Machine Optimization Remark Emitter
+; CHECK-NEXT: Reaching Definitions Analysis
; CHECK-NEXT: Prologue/Epilogue Insertion & Frame Finalization
; CHECK-NEXT: Post-RA pseudo instruction expansion pass
; CHECK-NEXT: RISC-V post-regalloc pseudo instruction expansion pass
diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
index 3e2de780524b6..5111971f18cc2 100644
--- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
@@ -175,6 +175,7 @@
; CHECK-NEXT: Lazy Machine Block Frequency Analysis
; CHECK-NEXT: Machine Optimization Remark Emitter
; CHECK-NEXT: Shrink Wrapping analysis
+; CHECK-NEXT: Reaching Definitions Analysis
; CHECK-NEXT: Prologue/Epilogue Insertion & Frame Finalization
; CHECK-NEXT: Machine Late Instructions Cleanup Pass
; CHECK-NEXT: Control Flow Optimizer
diff --git a/llvm/test/CodeGen/RISCV/emit-early-cfis.mir b/llvm/test/CodeGen/RISCV/emit-early-cfis.mir
new file mode 100644
index 0000000000000..6788f1d6548be
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/emit-early-cfis.mir
@@ -0,0 +1,108 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc %s -mtriple=riscv64 -riscv-save-csrs-early=true \
+# RUN: -run-pass=prologepilog -o - | FileCheck %s
+---
+name: test0
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ bb.0.entry:
+ liveins: $x18
+ ; CHECK-LABEL: name: test0
+ ; CHECK: liveins: $x18
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; CHECK-NEXT: BUNDLE implicit $x18 {
+ ; CHECK-NEXT: SD $x18, %stack.0, 0 :: (store (s64))
+ ; CHECK-NEXT: CFI_INSTRUCTION llvm_reg_at_scalable_offset_from_reg $x18, $x2, 0, 12
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: BUNDLE implicit-def $x18 {
+ ; CHECK-NEXT: $x18 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-NEXT: CFI_INSTRUCTION register $x18, $x18
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16
+ ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
+ ; CHECK-NEXT: PseudoRET
+ SD $x18, %stack.0, 0 :: (store (s64))
+ $x18 = LD %stack.0, 0 :: (load (s64))
+ PseudoRET
+
+...
+
+---
+name: test1
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ bb.0.entry:
+ liveins: $x18
+ ; CHECK-LABEL: name: test1
+ ; CHECK: liveins: $x18
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; CHECK-NEXT: BUNDLE implicit-def $x5, implicit $x18 {
+ ; CHECK-NEXT: $x5 = COPY $x18
+ ; CHECK-NEXT: CFI_INSTRUCTION register $x18, $x5
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: BUNDLE implicit-def $x18, implicit $x5 {
+ ; CHECK-NEXT: $x18 = COPY $x5
+ ; CHECK-NEXT: CFI_INSTRUCTION register $x18, $x18
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16
+ ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
+ ; CHECK-NEXT: PseudoRET
+ $x5 = COPY $x18
+ $x18 = COPY $x5
+ PseudoRET
+
+...
+
+---
+name: test2
+tracksRegLiveness: true
+stack:
+ - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4,
+ stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+ debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+body: |
+ bb.0.entry:
+ liveins: $x18
+ ; CHECK-LABEL: name: test2
+ ; CHECK: liveins: $x18
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16
+ ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
+ ; CHECK-NEXT: BUNDLE implicit-def $x5, implicit $x18 {
+ ; CHECK-NEXT: $x5 = COPY $x18
+ ; CHECK-NEXT: CFI_INSTRUCTION register $x18, $x5
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: BUNDLE implicit $x5 {
+ ; CHECK-NEXT: SD $x5, %stack.0, 0 :: (store (s64))
+ ; CHECK-NEXT: CFI_INSTRUCTION llvm_reg_at_scalable_offset_from_reg $x18, $x2, 0, 12
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: BUNDLE implicit-def $x5 {
+ ; CHECK-NEXT: $x5 = LD %stack.0, 0 :: (load (s64))
+ ; CHECK-NEXT: CFI_INSTRUCTION register $x18, $x5
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: BUNDLE implicit-def $x18, implicit $x5 {
+ ; CHECK-NEXT: $x18 = COPY $x5
+ ; CHECK-NEXT: CFI_INSTRUCTION register $x18, $x18
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16
+ ; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
+ ; CHECK-NEXT: PseudoRET
+ $x5 = COPY $x18
+ SD $x5, %stack.0, 0 :: (store (s64))
+ $x5 = LD %stack.0, 0 :: (load (s64))
+ $x18 = COPY $x5
+ PseudoRET
+
+...
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions cpp,h -- llvm/include/llvm/CodeGen/TargetFrameLowering.h llvm/lib/CodeGen/PrologEpilogInserter.cpp llvm/lib/Target/RISCV/RISCVFrameLowering.cpp llvm/lib/Target/RISCV/RISCVFrameLowering.h llvm/lib/Target/RISCV/RISCVSubtarget.cpp --diff_from_common_commit
View the diff from clang-format here.diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index fe3ebcd13..d5e42d873 100644
--- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -36,7 +36,7 @@ namespace llvm {
ScalablePredicateVector = 4,
NoAlloc = 255
};
-}
+ }
/// Information about stack frame layout on the target. It holds the direction
/// of stack growth, the known stack alignment on entry to each function, and
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index ef1576db8..82d68ba96 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -75,10 +75,10 @@ static cl::opt<bool> EnablePExtCodeGen(
"only partial codegen is currently supported)"),
cl::init(false), cl::Hidden);
-static cl::opt<bool> RISCVSaveCSRsEarly(
- "riscv-save-csrs-early",
- cl::desc("Let register alloctor do csr saves/restores"), cl::init(false),
- cl::Hidden);
+static cl::opt<bool>
+ RISCVSaveCSRsEarly("riscv-save-csrs-early",
+ cl::desc("Let register alloctor do csr saves/restores"),
+ cl::init(false), cl::Hidden);
void RISCVSubtarget::anchor() {}
|
🐧 Linux x64 Test Results
All tests passed but another part of the build failed. Click on a failure below to see the details. lib/DWARFCFIChecker/CMakeFiles/LLVMDWARFCFIChecker.dir/DWARFCFIState.cpp.olib/Target/AArch64/CMakeFiles/LLVMAArch64CodeGen.dir/AArch64FrameLowering.cpp.olib/Target/RISCV/CMakeFiles/LLVMRISCVCodeGen.dir/RISCVFrameLowering.cpp.otools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/BinaryFunction.cpp.oIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
Add ability to emit CFIs if the registers were saved / restored before prolog / epilog insertion.
This has been split out from @mgudim's save_csr_in_ra3 (from #90819), and is PR 4 out of 5.
determineCalleeSaves#170609Co-authored-by: Mikhail Gudim mgudim@ventanamicro.com