-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[WIP][CodeGen] Allow register allocator to drive save/restore #170611
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_early_cfi
Are you sure you want to change the base?
[WIP][CodeGen] Allow register allocator to drive save/restore #170611
Conversation
This is needed for the cases when RDA has to run on a function that does not have live-ins info.
In `finalizeLowering` we copy all callee-saved registers from a physical register to a virtual one. In all return blocks we copy do the reverse. This has two effects: (1) It tells the optimizer that the value of callee-saved registers has to be preserved (2) Allows the optimizer to work on CSRs. In particular, we get shrink-wrapping "for free" - the register allocator will spill / restore CSRs if needed.
|
@llvm/pr-subscribers-backend-risc-v Author: Petr Penzin (ppenzin) ChangesUse register allocator to save callee-saved registers. This has been split out from https://github.com/mgudim/llvm-project/tree/save_csr_in_ra3, and is PR 5 out of 5. Co-authored-by: Mikhail Gudim <mgudim@ventanamicro.com> Full diff: https://github.com/llvm/llvm-project/pull/170611.diff 9 Files Affected:
diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
index b12a5bc64ca0b..7014fd4bf890b 100644
--- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
+++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
@@ -9,6 +9,8 @@
#include "llvm/CodeGen/ReachingDefAnalysis.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
@@ -288,6 +290,16 @@ void ReachingDefInfo::run(MachineFunction &mf) {
TRI = STI.getRegisterInfo();
TII = STI.getInstrInfo();
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n");
+
+ MachineFunctionProperties &Props = MF->getProperties();
+ if (!Props.hasTracksLiveness()) {
+ Props.setTracksLiveness();
+
+ SmallVector<MachineBasicBlock *> AllMBBsInPostOrder;
+ for (MachineBasicBlock *MBB : post_order(MF))
+ AllMBBsInPostOrder.push_back(MBB);
+ fullyRecomputeLiveIns(AllMBBsInPostOrder);
+ }
init();
traverse();
}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index ab2652eac3823..7e7af8d48da0b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -25827,3 +25827,95 @@ bool RISCVTargetLowering::isReassocProfitable(SelectionDAG &DAG, SDValue N0,
return true;
}
+
+static MachineInstr *findInstrWhichNeedAllCSRs(MachineBasicBlock &MBB) {
+ // Some instructions may require (implicitly) all CSRs to be saved.
+ // For example, call to __cxa_throw is noreturn, but expects that all CSRs are
+ // taken care of.
+ // TODO: try to speedup this?
+ for (MachineInstr &MI : MBB) {
+ unsigned Opc = MI.getOpcode();
+ if (Opc != RISCV::PseudoCALL && Opc != RISCV::PseudoTAIL)
+ continue;
+ MachineOperand &MO = MI.getOperand(0);
+ StringRef Name = "";
+ if (MO.isSymbol()) {
+ Name = MO.getSymbolName();
+ } else if (MO.isGlobal()) {
+ Name = MO.getGlobal()->getName();
+ } else {
+ llvm_unreachable("Unexpected operand type.");
+ }
+ if (Name == "__cxa_throw" || Name == "__cxa_rethrow" ||
+ Name == "_Unwind_Resume")
+ return &MI;
+ }
+ return nullptr;
+}
+
+void RISCVTargetLowering::finalizeLowering(MachineFunction &MF) const {
+ if (!Subtarget.savesCSRsEarly()) {
+ TargetLoweringBase::finalizeLowering(MF);
+ return;
+ }
+
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
+ const RISCVRegisterInfo &TRI = *Subtarget.getRegisterInfo();
+ const RISCVFrameLowering &TFI = *Subtarget.getFrameLowering();
+
+ SmallVector<MachineInstr *, 4> RestorePoints;
+ SmallVector<MachineBasicBlock *, 4> SaveMBBs;
+ SaveMBBs.push_back(&MF.front());
+ for (MachineBasicBlock &MBB : MF) {
+ if (MBB.isReturnBlock())
+ RestorePoints.push_back(&MBB.back());
+ if (MachineInstr *CallToCxaThrow = findInstrWhichNeedAllCSRs(MBB)) {
+ MachineBasicBlock::iterator MII = MBB.getFirstTerminator();
+ MachineInstr *NewRetMI = BuildMI(MBB, MII, CallToCxaThrow->getDebugLoc(),
+ TII.get(RISCV::UnreachableRET));
+ RestorePoints.push_back(NewRetMI);
+ MII = ++NewRetMI->getIterator();
+ MBB.erase(MII, MBB.end());
+ }
+ }
+
+ BitVector EarlyCSRs;
+ TFI.determineEarlyCalleeSaves(MF, EarlyCSRs);
+
+ SmallVector<Register, 4> VRegs;
+ for (MachineBasicBlock *SaveMBB : SaveMBBs) {
+ for (unsigned Reg = 0; Reg < EarlyCSRs.size(); ++Reg) {
+ if (!EarlyCSRs[Reg])
+ continue;
+ SaveMBB->addLiveIn(Reg);
+ Register VReg = MRI.createVirtualRegister(
+ TRI.getLargestLegalSuperClass(TRI.getMinimalPhysRegClass(Reg), MF));
+ VRegs.push_back(VReg);
+ BuildMI(*SaveMBB, SaveMBB->begin(),
+ SaveMBB->findDebugLoc(SaveMBB->begin()),
+ TII.get(TargetOpcode::COPY), VReg)
+ .addReg(Reg);
+ MRI.setSimpleHint(VReg, Reg);
+ }
+ }
+
+ for (MachineInstr *RestorePoint : RestorePoints) {
+ auto VRegI = VRegs.begin();
+ for (unsigned Reg = 0; Reg < EarlyCSRs.size(); ++Reg) {
+ if (!EarlyCSRs[Reg])
+ continue;
+ Register VReg = *VRegI;
+ BuildMI(*RestorePoint->getParent(), RestorePoint->getIterator(),
+ RestorePoint->getDebugLoc(), TII.get(TargetOpcode::COPY), Reg)
+ .addReg(VReg);
+ RestorePoint->addOperand(MF,
+ MachineOperand::CreateReg(Reg,
+ /*isDef=*/false,
+ /*isImplicit=*/true));
+ VRegI++;
+ }
+ }
+
+ TargetLoweringBase::finalizeLowering(MF);
+}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 8a55a5634452c..bd21bb9e8593e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -652,6 +652,8 @@ class RISCVTargetLowering : public TargetLowering {
std::pair<const TargetRegisterClass *, uint8_t>
findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const override;
+
+ void finalizeLowering(MachineFunction &MF) const override;
};
namespace RISCVVIntrinsicsTable {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 89ec4a2a4a3e1..5bbf558644987 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -5127,3 +5127,11 @@ bool RISCVInstrInfo::isHighLatencyDef(int Opc) const {
return true;
}
}
+
+bool RISCVInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+ if (MI.getOpcode() == RISCV::UnreachableRET) {
+ MI.eraseFromParent();
+ return true;
+ }
+ return false;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 0ffe015b9fac8..e98ec29d57446 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -343,6 +343,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
static bool isFromLoadImm(const MachineRegisterInfo &MRI,
const MachineOperand &Op, int64_t &Imm);
+ bool expandPostRAPseudo(MachineInstr &MI) const override;
+
protected:
const RISCVSubtarget &STI;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 84b962b2a8607..3cc6cb6567cfe 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1836,6 +1836,9 @@ let isBarrier = 1, isReturn = 1, isTerminator = 1 in
def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>,
PseudoInstExpansion<(JALR X0, X1, 0)>;
+let isBarrier = 1, isReturn = 1, isTerminator = 1, isMeta = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
+def UnreachableRET : Pseudo<(outs), (ins), []>;
+
// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
// expand to auipc and jalr while encoding.
// Define AsmString to print "tail" when compile with -S flag.
diff --git a/llvm/test/CodeGen/RISCV/pr53662.mir b/llvm/test/CodeGen/RISCV/pr53662.mir
index dccad40368111..834bcbc1cf82c 100644
--- a/llvm/test/CodeGen/RISCV/pr53662.mir
+++ b/llvm/test/CodeGen/RISCV/pr53662.mir
@@ -18,15 +18,19 @@ body: |
; CHECK-LABEL: name: b
; CHECK: bb.0:
; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: liveins: $x10
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: PseudoBR %bb.1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors: %bb.2(0x80000000)
+ ; CHECK-NEXT: liveins: $x10
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: DBG_VALUE $noreg
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: liveins: $x10
+ ; CHECK-NEXT: {{ $}}
; CHECK-NEXT: PseudoRET implicit killed $x10
bb.0 :
PseudoBR %bb.1
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-emergency-slot.mir b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-emergency-slot.mir
index c728fcb8d8b0d..44f60a43a2790 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-emergency-slot.mir
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-emergency-slot.mir
@@ -47,7 +47,7 @@ body: |
SD $x10, %stack.0, 0
SD $x10, %stack.2, 0
- dead renamable $x15 = PseudoVSETIVLI 1, 72, implicit-def $vl, implicit-def $vtype
+ renamable $x15 = PseudoVSETIVLI 1, 72, implicit-def $vl, implicit-def $vtype
VS1R_V killed renamable $v25, %stack.1 :: (store (<vscale x 1 x s64>) into %stack.1, align 8)
; This is here just to make all the eligible registers live at this point.
; This way when we replace the frame index %stack.1 with its actual address
diff --git a/llvm/test/CodeGen/RISCV/save-csr-early.ll b/llvm/test/CodeGen/RISCV/save-csr-early.ll
new file mode 100644
index 0000000000000..65feb5d867aab
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/save-csr-early.ll
@@ -0,0 +1,113 @@
+; 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: -stop-after=finalize-isel -o - | FileCheck %s
+
+define void @test0() {
+ ; CHECK-LABEL: name: test0
+ ; CHECK: bb.0 (%ir-block.0):
+ ; CHECK-NEXT: liveins: $x1, $x8, $x9, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x27
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x26
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x25
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x24
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sr07 = COPY $x23
+ ; CHECK-NEXT: [[COPY5:%[0-9]+]]:sr07 = COPY $x22
+ ; CHECK-NEXT: [[COPY6:%[0-9]+]]:sr07 = COPY $x21
+ ; CHECK-NEXT: [[COPY7:%[0-9]+]]:sr07 = COPY $x20
+ ; CHECK-NEXT: [[COPY8:%[0-9]+]]:sr07 = COPY $x19
+ ; CHECK-NEXT: [[COPY9:%[0-9]+]]:sr07 = COPY $x18
+ ; CHECK-NEXT: [[COPY10:%[0-9]+]]:gprc_and_sr07 = COPY $x9
+ ; CHECK-NEXT: [[COPY11:%[0-9]+]]:gprc_and_sr07 = COPY $x8
+ ; CHECK-NEXT: [[COPY12:%[0-9]+]]:gprx1 = COPY $x1
+ ; CHECK-NEXT: $x1 = COPY [[COPY12]]
+ ; CHECK-NEXT: $x8 = COPY [[COPY11]]
+ ; CHECK-NEXT: $x9 = COPY [[COPY10]]
+ ; CHECK-NEXT: $x18 = COPY [[COPY9]]
+ ; CHECK-NEXT: $x19 = COPY [[COPY8]]
+ ; CHECK-NEXT: $x20 = COPY [[COPY7]]
+ ; CHECK-NEXT: $x21 = COPY [[COPY6]]
+ ; CHECK-NEXT: $x22 = COPY [[COPY5]]
+ ; CHECK-NEXT: $x23 = COPY [[COPY4]]
+ ; CHECK-NEXT: $x24 = COPY [[COPY3]]
+ ; CHECK-NEXT: $x25 = COPY [[COPY2]]
+ ; CHECK-NEXT: $x26 = COPY [[COPY1]]
+ ; CHECK-NEXT: $x27 = COPY [[COPY]]
+ ; CHECK-NEXT: PseudoRET implicit $x1, implicit $x8, implicit $x9, implicit $x18, implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27
+ ret void
+}
+
+declare void @__cxa_throw(ptr, ptr, ptr)
+
+define void @test1(i1 %x, ptr %p0, ptr %p1, ptr %p2) {
+ ; CHECK-LABEL: name: test1
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.1(0x00000000), %bb.2(0x80000000)
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12, $x13, $x1, $x8, $x9, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x27
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x26
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x25
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gprjalrnonx7_and_gprnox31 = COPY $x24
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sr07 = COPY $x23
+ ; CHECK-NEXT: [[COPY5:%[0-9]+]]:sr07 = COPY $x22
+ ; CHECK-NEXT: [[COPY6:%[0-9]+]]:sr07 = COPY $x21
+ ; CHECK-NEXT: [[COPY7:%[0-9]+]]:sr07 = COPY $x20
+ ; CHECK-NEXT: [[COPY8:%[0-9]+]]:sr07 = COPY $x19
+ ; CHECK-NEXT: [[COPY9:%[0-9]+]]:sr07 = COPY $x18
+ ; CHECK-NEXT: [[COPY10:%[0-9]+]]:gprc_and_sr07 = COPY $x9
+ ; CHECK-NEXT: [[COPY11:%[0-9]+]]:gprc_and_sr07 = COPY $x8
+ ; CHECK-NEXT: [[COPY12:%[0-9]+]]:gprx1 = COPY $x1
+ ; CHECK-NEXT: [[COPY13:%[0-9]+]]:gpr = COPY $x13
+ ; CHECK-NEXT: [[COPY14:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY15:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY16:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY16]], 1
+ ; CHECK-NEXT: BEQ killed [[ANDI]], $x0, %bb.2
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1.throw:
+ ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2
+ ; CHECK-NEXT: $x10 = COPY [[COPY15]]
+ ; CHECK-NEXT: $x11 = COPY [[COPY14]]
+ ; CHECK-NEXT: $x12 = COPY [[COPY13]]
+ ; CHECK-NEXT: PseudoCALL target-flags(riscv-call) @__cxa_throw, csr_ilp32_lp64, implicit-def dead $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x2
+ ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2
+ ; CHECK-NEXT: $x1 = COPY [[COPY12]]
+ ; CHECK-NEXT: $x8 = COPY [[COPY11]]
+ ; CHECK-NEXT: $x9 = COPY [[COPY10]]
+ ; CHECK-NEXT: $x18 = COPY [[COPY9]]
+ ; CHECK-NEXT: $x19 = COPY [[COPY8]]
+ ; CHECK-NEXT: $x20 = COPY [[COPY7]]
+ ; CHECK-NEXT: $x21 = COPY [[COPY6]]
+ ; CHECK-NEXT: $x22 = COPY [[COPY5]]
+ ; CHECK-NEXT: $x23 = COPY [[COPY4]]
+ ; CHECK-NEXT: $x24 = COPY [[COPY3]]
+ ; CHECK-NEXT: $x25 = COPY [[COPY2]]
+ ; CHECK-NEXT: $x26 = COPY [[COPY1]]
+ ; CHECK-NEXT: $x27 = COPY [[COPY]]
+ ; CHECK-NEXT: UnreachableRET implicit $x1, implicit $x8, implicit $x9, implicit $x18, implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.return:
+ ; CHECK-NEXT: $x1 = COPY [[COPY12]]
+ ; CHECK-NEXT: $x8 = COPY [[COPY11]]
+ ; CHECK-NEXT: $x9 = COPY [[COPY10]]
+ ; CHECK-NEXT: $x18 = COPY [[COPY9]]
+ ; CHECK-NEXT: $x19 = COPY [[COPY8]]
+ ; CHECK-NEXT: $x20 = COPY [[COPY7]]
+ ; CHECK-NEXT: $x21 = COPY [[COPY6]]
+ ; CHECK-NEXT: $x22 = COPY [[COPY5]]
+ ; CHECK-NEXT: $x23 = COPY [[COPY4]]
+ ; CHECK-NEXT: $x24 = COPY [[COPY3]]
+ ; CHECK-NEXT: $x25 = COPY [[COPY2]]
+ ; CHECK-NEXT: $x26 = COPY [[COPY1]]
+ ; CHECK-NEXT: $x27 = COPY [[COPY]]
+ ; CHECK-NEXT: PseudoRET implicit $x1, implicit $x8, implicit $x9, implicit $x18, implicit $x19, implicit $x20, implicit $x21, implicit $x22, implicit $x23, implicit $x24, implicit $x25, implicit $x26, implicit $x27
+entry:
+ br i1 %x, label %throw, label %return
+throw:
+ call void @__cxa_throw(ptr %p0, ptr %p1, ptr %p2)
+ unreachable
+return:
+ ret void
+}
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions cpp,h -- llvm/lib/CodeGen/ReachingDefAnalysis.cpp llvm/lib/Target/RISCV/RISCVISelLowering.cpp llvm/lib/Target/RISCV/RISCVISelLowering.h llvm/lib/Target/RISCV/RISCVInstrInfo.cpp llvm/lib/Target/RISCV/RISCVInstrInfo.h --diff_from_common_commit
View the diff from clang-format here.diff --git a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
index 7014fd4bf..f36beabbd 100644
--- a/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
+++ b/llvm/lib/CodeGen/ReachingDefAnalysis.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/ReachingDefAnalysis.h"
+#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
|
🐧 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.otools/bolt/lib/Core/CMakeFiles/LLVMBOLTCore.dir/BinaryFunction.cpp.olib/Target/RISCV/CMakeFiles/LLVMRISCVCodeGen.dir/RISCVFrameLowering.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 |
Use register allocator to save callee-saved registers.
This has been split out from @mgudim's save_csr_in_ra3 (from #90819), and is PR 5 out of 5.
determineCalleeSaves#170609Co-authored-by: Mikhail Gudim mgudim@ventanamicro.com