-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV][WIP] Let RA do the CSR saves. #90819
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: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,8 +114,11 @@ class ReachingDefAnalysis : public MachineFunctionPass { | |
private: | ||
MachineFunction *MF = nullptr; | ||
const TargetRegisterInfo *TRI = nullptr; | ||
const TargetInstrInfo *TII = nullptr; | ||
LoopTraversal::TraversalOrder TraversedMBBOrder; | ||
unsigned NumRegUnits = 0; | ||
unsigned NumStackObjects = 0; | ||
int ObjectIndexBegin = 0; | ||
/// Instruction that defined each register, relative to the beginning of the | ||
/// current basic block. When a LiveRegsDefInfo is used to represent a | ||
/// live-out register, this value is relative to the end of the basic block, | ||
|
@@ -138,6 +141,9 @@ class ReachingDefAnalysis : public MachineFunctionPass { | |
DenseMap<MachineInstr *, int> InstIds; | ||
|
||
MBBReachingDefsInfo MBBReachingDefs; | ||
using MBBFrameObjsReachingDefsInfo = | ||
std::vector<std::vector<std::vector<int>>>; | ||
MBBFrameObjsReachingDefsInfo MBBFrameObjsReachingDefs; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to add a docstring that describes this object. My understanding is that this is representing a map of MBBNumber -> Frame Object Index -> reaching def instruction numbers, since it is not clear by the data type definition. |
||
|
||
/// Default values are 'nothing happened a long time ago'. | ||
const int ReachingDefDefaultVal = -(1 << 21); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,15 +24,16 @@ namespace llvm { | |
class CalleeSavedInfo; | ||
class MachineFunction; | ||
class RegScavenger; | ||
|
||
namespace TargetStackID { | ||
enum Value { | ||
Default = 0, | ||
SGPRSpill = 1, | ||
ScalableVector = 2, | ||
WasmLocal = 3, | ||
NoAlloc = 255 | ||
}; | ||
class ReachingDefAnalysis; | ||
|
||
namespace TargetStackID { | ||
enum Value { | ||
Default = 0, | ||
SGPRSpill = 1, | ||
ScalableVector = 2, | ||
WasmLocal = 3, | ||
NoAlloc = 255 | ||
}; | ||
} | ||
|
||
/// Information about stack frame layout on the target. It holds the direction | ||
|
@@ -210,6 +211,11 @@ class TargetFrameLowering { | |
/// for noreturn nounwind functions. | ||
virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const; | ||
|
||
virtual void emitCFIsForCSRsHandledByRA(MachineFunction &MF, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need a comment here to tell backend authors what they are supposed to do with this hook and when they should consider implementing it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @qcolombet I'll make sure I'll add a comment when I create a separate MR for it. |
||
ReachingDefAnalysis *RDA) const { | ||
return; | ||
} | ||
|
||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into | ||
/// the function. | ||
virtual void emitPrologue(MachineFunction &MF, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -317,6 +317,8 @@ class TargetSubtargetInfo : public MCSubtargetInfo { | |
return false; | ||
} | ||
|
||
virtual bool doCSRSavesInRA() const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto missing comments |
||
|
||
/// Classify a global function reference. This mainly used to fetch target | ||
/// special flags for lowering a function address. For example mark a function | ||
/// call should be plt or pc-related addressing. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -262,15 +262,21 @@ namespace { | |
void HoistOutOfLoop(MachineDomTreeNode *HeaderN, MachineLoop *CurLoop, | ||
MachineBasicBlock *CurPreheader); | ||
|
||
void InitRegPressure(MachineBasicBlock *BB); | ||
void InitRegPressure(MachineBasicBlock *BB, const MachineLoop *Loop); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the original shrink wrapping paper:
I'm not sure I fully understand what's going on here but I wanted to check and see if this patch allows shrink wrapping on a per register basis inside loops. If so, is this something we should avoid? Is this concept at all related to this code? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also help me understand why this patch (without this machine-licm change) leads to longer live ranges? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
with this patch, shrink-wrapping becomes regular spilling. The change to the register allocator was made because it gets rid of a spill inside a loop that I saw due to this patch. Probably we will see other spills inside loops, but we will be fixing them in RA now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
because on entry to the function we copy each CSR into a virtual register which will be live for the entire function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Was it not the case that when we spilled the CSR in PrologEpilogInserter that the register was also live for the entire function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was no single virtual register corresponding to each Callee Saved Register. The PrologEpilogEmitter approach looks after regalloc to see which callee saved registers are used in the function and spills/restores them. |
||
|
||
SmallDenseMap<unsigned, int> calcRegisterCost(const MachineInstr *MI, | ||
bool ConsiderSeen, | ||
bool ConsiderUnseenAsDef); | ||
bool ConsiderUnseenAsDef, | ||
bool IgnoreDefs = false); | ||
|
||
bool allDefsAreOnlyUsedOutsideOfTheLoop(const MachineInstr &MI, | ||
const MachineLoop *Loop); | ||
void UpdateRegPressure(const MachineInstr *MI, | ||
bool ConsiderUnseenAsDef = false); | ||
bool ConsiderUnseenAsDef = false, | ||
bool IgnoreDefs = false); | ||
|
||
void UpdateRegPressureForUsesOnly(const MachineInstr *MI, | ||
bool ConsiderUnseenAsDef = false); | ||
MachineInstr *ExtractHoistableLoad(MachineInstr *MI, MachineLoop *CurLoop); | ||
|
||
MachineInstr *LookForDuplicate(const MachineInstr *MI, | ||
|
@@ -884,7 +890,7 @@ void MachineLICMImpl::HoistOutOfLoop(MachineDomTreeNode *HeaderN, | |
// Compute registers which are livein into the loop headers. | ||
RegSeen.clear(); | ||
BackTrace.clear(); | ||
InitRegPressure(Preheader); | ||
InitRegPressure(Preheader, CurLoop); | ||
|
||
// Now perform LICM. | ||
for (MachineDomTreeNode *Node : Scopes) { | ||
|
@@ -934,7 +940,8 @@ static bool isOperandKill(const MachineOperand &MO, MachineRegisterInfo *MRI) { | |
/// Find all virtual register references that are liveout of the preheader to | ||
/// initialize the starting "register pressure". Note this does not count live | ||
/// through (livein but not used) registers. | ||
void MachineLICMImpl::InitRegPressure(MachineBasicBlock *BB) { | ||
void MachineLICMImpl::InitRegPressure(MachineBasicBlock *BB, | ||
const MachineLoop *Loop) { | ||
std::fill(RegPressure.begin(), RegPressure.end(), 0); | ||
|
||
// If the preheader has only a single predecessor and it ends with a | ||
|
@@ -945,17 +952,34 @@ void MachineLICMImpl::InitRegPressure(MachineBasicBlock *BB) { | |
MachineBasicBlock *TBB = nullptr, *FBB = nullptr; | ||
SmallVector<MachineOperand, 4> Cond; | ||
if (!TII->analyzeBranch(*BB, TBB, FBB, Cond, false) && Cond.empty()) | ||
InitRegPressure(*BB->pred_begin()); | ||
InitRegPressure(*BB->pred_begin(), Loop); | ||
} | ||
|
||
for (const MachineInstr &MI : *BB) | ||
UpdateRegPressure(&MI, /*ConsiderUnseenAsDef=*/true); | ||
for (const MachineInstr &MI : *BB) { | ||
bool IgnoreDefs = allDefsAreOnlyUsedOutsideOfTheLoop(MI, Loop); | ||
UpdateRegPressure(&MI, /*ConsiderUnseenAsDef=*/true, IgnoreDefs); | ||
} | ||
} | ||
|
||
bool MachineLICMImpl::allDefsAreOnlyUsedOutsideOfTheLoop( | ||
const MachineInstr &MI, const MachineLoop *Loop) { | ||
for (const MachineOperand DefMO : MI.all_defs()) { | ||
if (!DefMO.isReg()) | ||
continue; | ||
for (const MachineInstr &UseMI : MRI->use_instructions(DefMO.getReg())) { | ||
if (Loop->contains(UseMI.getParent())) | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
/// Update estimate of register pressure after the specified instruction. | ||
void MachineLICMImpl::UpdateRegPressure(const MachineInstr *MI, | ||
bool ConsiderUnseenAsDef) { | ||
auto Cost = calcRegisterCost(MI, /*ConsiderSeen=*/true, ConsiderUnseenAsDef); | ||
bool ConsiderUnseenAsDef, | ||
bool IgnoreDefs) { | ||
auto Cost = calcRegisterCost(MI, /*ConsiderSeen=*/true, ConsiderUnseenAsDef, | ||
IgnoreDefs); | ||
for (const auto &RPIdAndCost : Cost) { | ||
unsigned Class = RPIdAndCost.first; | ||
if (static_cast<int>(RegPressure[Class]) < -RPIdAndCost.second) | ||
|
@@ -973,7 +997,7 @@ void MachineLICMImpl::UpdateRegPressure(const MachineInstr *MI, | |
/// FIXME: Figure out a way to consider 'RegSeen' from all code paths. | ||
SmallDenseMap<unsigned, int> | ||
MachineLICMImpl::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen, | ||
bool ConsiderUnseenAsDef) { | ||
bool ConsiderUnseenAsDef, bool IgnoreDefs) { | ||
SmallDenseMap<unsigned, int> Cost; | ||
if (MI->isImplicitDef()) | ||
return Cost; | ||
|
@@ -991,7 +1015,7 @@ MachineLICMImpl::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen, | |
|
||
RegClassWeight W = TRI->getRegClassWeight(RC); | ||
int RCCost = 0; | ||
if (MO.isDef()) | ||
if (MO.isDef() && !IgnoreDefs) | ||
RCCost = W.RegWeight; | ||
else { | ||
bool isKill = isOperandKill(MO, MRI); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ | |
#include "llvm/CodeGen/MachineOperand.h" | ||
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" | ||
#include "llvm/CodeGen/MachineRegisterInfo.h" | ||
#include "llvm/CodeGen/ReachingDefAnalysis.h" | ||
#include "llvm/CodeGen/RegisterScavenging.h" | ||
#include "llvm/CodeGen/TargetFrameLowering.h" | ||
#include "llvm/CodeGen/TargetInstrInfo.h" | ||
|
@@ -95,6 +96,7 @@ class PEI : public MachineFunctionPass { | |
bool runOnMachineFunction(MachineFunction &MF) override; | ||
|
||
private: | ||
ReachingDefAnalysis *RDA = nullptr; | ||
RegScavenger *RS = nullptr; | ||
|
||
// MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee saved | ||
|
@@ -153,6 +155,7 @@ INITIALIZE_PASS_BEGIN(PEI, DEBUG_TYPE, "Prologue/Epilogue Insertion", false, | |
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass) | ||
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) | ||
INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass) | ||
INITIALIZE_PASS_DEPENDENCY(ReachingDefAnalysis) | ||
INITIALIZE_PASS_END(PEI, DEBUG_TYPE, | ||
"Prologue/Epilogue Insertion & Frame Finalization", false, | ||
false) | ||
|
@@ -169,6 +172,7 @@ void PEI::getAnalysisUsage(AnalysisUsage &AU) const { | |
AU.addPreserved<MachineLoopInfoWrapperPass>(); | ||
AU.addPreserved<MachineDominatorTreeWrapperPass>(); | ||
AU.addRequired<MachineOptimizationRemarkEmitterPass>(); | ||
AU.addRequired<ReachingDefAnalysis>(); | ||
MachineFunctionPass::getAnalysisUsage(AU); | ||
} | ||
|
||
|
@@ -227,6 +231,7 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { | |
RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : nullptr; | ||
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF); | ||
ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); | ||
RDA = &getAnalysis<ReachingDefAnalysis>(); | ||
|
||
// Spill frame pointer and/or base pointer registers if they are clobbered. | ||
// It is placed before call frame instruction elimination so it will not mess | ||
|
@@ -262,6 +267,7 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { | |
// called functions. Because of this, calculateCalleeSavedRegisters() | ||
// must be called before this function in order to set the AdjustsStack | ||
// and MaxCallFrameSize variables. | ||
RDA->reset(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is a call to
|
||
if (!F.hasFnAttribute(Attribute::Naked)) | ||
insertPrologEpilogCode(MF); | ||
|
||
|
@@ -1164,6 +1170,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { | |
void PEI::insertPrologEpilogCode(MachineFunction &MF) { | ||
const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering(); | ||
|
||
TFI.emitCFIsForCSRsHandledByRA(MF, RDA); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be nice to add a comment explaining that CSRs that are handled by RA still need CFI information and emitPrologue does not emit CFI info for those, since the CSRs may no longer be located in the prologue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a separate note, RISCVFrameLowering::emitPrologue has code to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only the registers added by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the CFIInserter pass needed if we are inserting CFI information here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suppose we had the following code (before block layout is finalized):
after the block layout the code may look like this (now
The cfi directives apply to all the code below it in the layout, so the cfi's are wrong now. The CFIInserter compares the CFI info from the layout successor to what it has to be and corrects it if necessary. I basically copied that pass from the existing one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Is it possible to modify There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's possible. In some cases (notably when we have vector spills), we need to use cfi expression instead of simple Here, I recorded cfi info into |
||
// Add prologue to the function... | ||
for (MachineBasicBlock *SaveBlock : SaveBlocks) | ||
TFI.emitPrologue(MF, *SaveBlock); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ | |
#include "llvm/ADT/SetOperations.h" | ||
#include "llvm/ADT/SmallSet.h" | ||
#include "llvm/CodeGen/LiveRegUnits.h" | ||
#include "llvm/CodeGen/MachineFrameInfo.h" | ||
#include "llvm/CodeGen/TargetInstrInfo.h" | ||
#include "llvm/CodeGen/TargetRegisterInfo.h" | ||
#include "llvm/CodeGen/TargetSubtargetInfo.h" | ||
#include "llvm/Support/Debug.h" | ||
|
@@ -48,12 +50,28 @@ static bool isValidRegDefOf(const MachineOperand &MO, MCRegister PhysReg, | |
return TRI->regsOverlap(MO.getReg(), PhysReg); | ||
} | ||
|
||
static bool isFIDef(const MachineInstr &MI, int FrameIndex, | ||
const TargetInstrInfo *TII) { | ||
int DefFrameIndex = 0; | ||
int SrcFrameIndex = 0; | ||
if (TII->isStoreToStackSlot(MI, DefFrameIndex) || | ||
TII->isStackSlotCopy(MI, DefFrameIndex, SrcFrameIndex)) { | ||
return DefFrameIndex == FrameIndex; | ||
} | ||
return false; | ||
} | ||
|
||
void ReachingDefAnalysis::enterBasicBlock(MachineBasicBlock *MBB) { | ||
unsigned MBBNumber = MBB->getNumber(); | ||
assert(MBBNumber < MBBReachingDefs.numBlockIDs() && | ||
"Unexpected basic block number."); | ||
MBBReachingDefs.startBasicBlock(MBBNumber, NumRegUnits); | ||
|
||
MBBFrameObjsReachingDefs[MBBNumber].resize(NumStackObjects); | ||
for (unsigned FOIdx = 0; FOIdx < NumStackObjects; ++FOIdx) { | ||
MBBFrameObjsReachingDefs[MBBNumber][FOIdx].push_back(-1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid initializing with |
||
} | ||
|
||
// Reset instruction counter in each basic block. | ||
CurInstr = 0; | ||
|
||
|
@@ -126,6 +144,13 @@ void ReachingDefAnalysis::processDefs(MachineInstr *MI) { | |
"Unexpected basic block number."); | ||
|
||
for (auto &MO : MI->operands()) { | ||
if (MO.isFI()) { | ||
int FrameIndex = MO.getIndex(); | ||
if (!isFIDef(*MI, FrameIndex, TII)) | ||
continue; | ||
MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin] | ||
.push_back(CurInstr); | ||
} | ||
if (!isValidRegDef(MO)) | ||
continue; | ||
for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) { | ||
|
@@ -211,7 +236,9 @@ void ReachingDefAnalysis::processBasicBlock( | |
|
||
bool ReachingDefAnalysis::runOnMachineFunction(MachineFunction &mf) { | ||
MF = &mf; | ||
TRI = MF->getSubtarget().getRegisterInfo(); | ||
const TargetSubtargetInfo &STI = MF->getSubtarget(); | ||
TRI = STI.getRegisterInfo(); | ||
TII = STI.getInstrInfo(); | ||
LLVM_DEBUG(dbgs() << "********** REACHING DEFINITION ANALYSIS **********\n"); | ||
init(); | ||
traverse(); | ||
|
@@ -222,6 +249,7 @@ void ReachingDefAnalysis::releaseMemory() { | |
// Clear the internal vectors. | ||
MBBOutRegsInfos.clear(); | ||
MBBReachingDefs.clear(); | ||
MBBFrameObjsReachingDefs.clear(); | ||
InstIds.clear(); | ||
LiveRegs.clear(); | ||
} | ||
|
@@ -234,7 +262,10 @@ void ReachingDefAnalysis::reset() { | |
|
||
void ReachingDefAnalysis::init() { | ||
NumRegUnits = TRI->getNumRegUnits(); | ||
NumStackObjects = MF->getFrameInfo().getNumObjects(); | ||
ObjectIndexBegin = MF->getFrameInfo().getObjectIndexBegin(); | ||
MBBReachingDefs.init(MF->getNumBlockIDs()); | ||
MBBFrameObjsReachingDefs.resize(MF->getNumBlockIDs()); | ||
// Initialize the MBBOutRegsInfos | ||
MBBOutRegsInfos.resize(MF->getNumBlockIDs()); | ||
LoopTraversal Traversal; | ||
|
@@ -269,6 +300,19 @@ int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, | |
assert(MBBNumber < MBBReachingDefs.numBlockIDs() && | ||
"Unexpected basic block number."); | ||
int LatestDef = ReachingDefDefaultVal; | ||
|
||
if (Register::isStackSlot(PhysReg)) { | ||
int FrameIndex = Register::stackSlot2Index(PhysReg); | ||
for (int Def : | ||
MBBFrameObjsReachingDefs[MBBNumber][FrameIndex - ObjectIndexBegin]) { | ||
if (Def >= InstId) | ||
break; | ||
DefRes = Def; | ||
} | ||
LatestDef = std::max(LatestDef, DefRes); | ||
return LatestDef; | ||
} | ||
|
||
for (MCRegUnit Unit : TRI->regunits(PhysReg)) { | ||
for (int Def : MBBReachingDefs.defs(MBBNumber, Unit)) { | ||
if (Def >= InstId) | ||
|
@@ -425,7 +469,7 @@ void ReachingDefAnalysis::getLiveOuts(MachineBasicBlock *MBB, | |
VisitedBBs.insert(MBB); | ||
LiveRegUnits LiveRegs(*TRI); | ||
LiveRegs.addLiveOuts(*MBB); | ||
if (LiveRegs.available(PhysReg)) | ||
if (Register::isPhysicalRegister(PhysReg) && LiveRegs.available(PhysReg)) | ||
return; | ||
|
||
if (auto *Def = getLocalLiveOutMIDef(MBB, PhysReg)) | ||
|
@@ -508,7 +552,7 @@ bool ReachingDefAnalysis::isReachingDefLiveOut(MachineInstr *MI, | |
MachineBasicBlock *MBB = MI->getParent(); | ||
LiveRegUnits LiveRegs(*TRI); | ||
LiveRegs.addLiveOuts(*MBB); | ||
if (LiveRegs.available(PhysReg)) | ||
if (Register::isPhysicalRegister(PhysReg) && LiveRegs.available(PhysReg)) | ||
return false; | ||
|
||
auto Last = MBB->getLastNonDebugInstr(); | ||
|
@@ -529,14 +573,21 @@ ReachingDefAnalysis::getLocalLiveOutMIDef(MachineBasicBlock *MBB, | |
MCRegister PhysReg) const { | ||
LiveRegUnits LiveRegs(*TRI); | ||
LiveRegs.addLiveOuts(*MBB); | ||
if (LiveRegs.available(PhysReg)) | ||
if (Register::isPhysicalRegister(PhysReg) && LiveRegs.available(PhysReg)) | ||
return nullptr; | ||
|
||
auto Last = MBB->getLastNonDebugInstr(); | ||
if (Last == MBB->end()) | ||
return nullptr; | ||
|
||
int Def = getReachingDef(&*Last, PhysReg); | ||
|
||
if (Register::isStackSlot(PhysReg)) { | ||
int FrameIndex = Register::stackSlot2Index(PhysReg); | ||
if (isFIDef(*Last, FrameIndex, TII)) | ||
return &*Last; | ||
} | ||
|
||
for (auto &MO : Last->operands()) | ||
if (isValidRegDefOf(MO, PhysReg, TRI)) | ||
return &*Last; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
NumStackObjects
andObjectIndexBegin
are available inenterBasicBlock
throughMBB->getParent()->getFrameInfo().getNumObjects()
andMBB->getParent()->getFrameInfo().getObjectIndexBegin()
.We could probably avoid storing them as member variables in ReachingDefAnalysis to keep the object smaller.