PrologEpilogInserter.cpp [plain text]
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/StackProtector.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <climits>
using namespace llvm;
#define DEBUG_TYPE "pei"
namespace {
class PEI : public MachineFunctionPass {
public:
static char ID;
PEI() : MachineFunctionPass(ID) {
initializePEIPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &Fn) override;
private:
RegScavenger *RS;
unsigned MinCSFrameIndex, MaxCSFrameIndex;
SmallVector<MachineBasicBlock *, 1> SaveBlocks;
SmallVector<MachineBasicBlock *, 4> RestoreBlocks;
bool FrameIndexVirtualScavenging;
void calculateSets(MachineFunction &Fn);
void calculateCallsInformation(MachineFunction &Fn);
void assignCalleeSavedSpillSlots(MachineFunction &Fn,
const BitVector &SavedRegs);
void insertCSRSpillsAndRestores(MachineFunction &Fn);
void calculateFrameObjectOffsets(MachineFunction &Fn);
void replaceFrameIndices(MachineFunction &Fn);
void replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn,
int &SPAdj);
void scavengeFrameVirtualRegs(MachineFunction &Fn);
void insertPrologEpilogCode(MachineFunction &Fn);
};
}
char PEI::ID = 0;
char &llvm::PrologEpilogCodeInserterID = PEI::ID;
static cl::opt<unsigned>
WarnStackSize("warn-stack-size", cl::Hidden, cl::init((unsigned)-1),
cl::desc("Warn for stack size bigger than the given"
" number"));
INITIALIZE_PASS_BEGIN(PEI, "prologepilog",
"Prologue/Epilogue Insertion", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(StackProtector)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_END(PEI, "prologepilog",
"Prologue/Epilogue Insertion & Frame Finalization",
false, false)
STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged");
STATISTIC(NumBytesStackSpace,
"Number of bytes used for stack in all functions");
void PEI::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addPreserved<MachineLoopInfo>();
AU.addPreserved<MachineDominatorTree>();
AU.addRequired<StackProtector>();
AU.addRequired<TargetPassConfig>();
MachineFunctionPass::getAnalysisUsage(AU);
}
void PEI::calculateSets(MachineFunction &Fn) {
const MachineFrameInfo *MFI = Fn.getFrameInfo();
if (MFI->getSavePoint()) {
SaveBlocks.push_back(MFI->getSavePoint());
assert(MFI->getRestorePoint() && "Both restore and save must be set");
MachineBasicBlock *RestoreBlock = MFI->getRestorePoint();
if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock())
RestoreBlocks.push_back(RestoreBlock);
return;
}
SaveBlocks.push_back(&Fn.front());
for (MachineBasicBlock &MBB : Fn) {
if (MBB.isEHFuncletEntry())
SaveBlocks.push_back(&MBB);
if (MBB.isReturnBlock())
RestoreBlocks.push_back(&MBB);
}
}
typedef SmallSetVector<int, 8> StackObjSet;
bool PEI::runOnMachineFunction(MachineFunction &Fn) {
const Function* F = Fn.getFunction();
const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
assert(!Fn.getRegInfo().getNumVirtRegs() && "Regalloc must assign all vregs");
RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr;
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
calculateCallsInformation(Fn);
BitVector SavedRegs;
TFI->determineCalleeSaves(Fn, SavedRegs, RS);
assignCalleeSavedSpillSlots(Fn, SavedRegs);
calculateSets(Fn);
if (!F->hasFnAttribute(Attribute::Naked))
insertCSRSpillsAndRestores(Fn);
TFI->processFunctionBeforeFrameFinalized(Fn, RS);
calculateFrameObjectOffsets(Fn);
if (!F->hasFnAttribute(Attribute::Naked))
insertPrologEpilogCode(Fn);
replaceFrameIndices(Fn);
if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging)
scavengeFrameVirtualRegs(Fn);
Fn.getRegInfo().clearVirtRegs();
MachineFrameInfo *MFI = Fn.getFrameInfo();
uint64_t StackSize = MFI->getStackSize();
if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {
DiagnosticInfoStackSize DiagStackSize(*F, StackSize);
F->getContext().diagnose(DiagStackSize);
}
delete RS;
SaveBlocks.clear();
RestoreBlocks.clear();
return true;
}
void PEI::calculateCallsInformation(MachineFunction &Fn) {
const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
MachineFrameInfo *MFI = Fn.getFrameInfo();
unsigned MaxCallFrameSize = 0;
bool AdjustsStack = MFI->adjustsStack();
unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
if (FrameSetupOpcode == ~0u && FrameDestroyOpcode == ~0u)
return;
std::vector<MachineBasicBlock::iterator> FrameSDOps;
for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
if (I->getOpcode() == FrameSetupOpcode ||
I->getOpcode() == FrameDestroyOpcode) {
assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo"
" instructions should have a single immediate argument!");
unsigned Size = I->getOperand(0).getImm();
if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
AdjustsStack = true;
FrameSDOps.push_back(I);
} else if (I->isInlineAsm()) {
unsigned ExtraInfo = I->getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
AdjustsStack = true;
}
MFI->setAdjustsStack(AdjustsStack);
MFI->setMaxCallFrameSize(MaxCallFrameSize);
for (std::vector<MachineBasicBlock::iterator>::iterator
i = FrameSDOps.begin(), e = FrameSDOps.end(); i != e; ++i) {
MachineBasicBlock::iterator I = *i;
if (TFI->canSimplifyCallFramePseudos(Fn))
TFI->eliminateCallFramePseudoInstr(Fn, *I->getParent(), I);
}
}
void PEI::assignCalleeSavedSpillSlots(MachineFunction &F,
const BitVector &SavedRegs) {
MinCSFrameIndex = INT_MAX;
MaxCSFrameIndex = 0;
if (SavedRegs.empty())
return;
const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo();
const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&F);
std::vector<CalleeSavedInfo> CSI;
for (unsigned i = 0; CSRegs[i]; ++i) {
unsigned Reg = CSRegs[i];
if (SavedRegs.test(Reg))
CSI.push_back(CalleeSavedInfo(Reg));
}
const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering();
MachineFrameInfo *MFI = F.getFrameInfo();
if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI, MinCSFrameIndex,
MaxCSFrameIndex)) {
if (CSI.empty())
return;
unsigned NumFixedSpillSlots;
const TargetFrameLowering::SpillSlot *FixedSpillSlots =
TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots);
for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end();
I != E; ++I) {
unsigned Reg = I->getReg();
const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);
int FrameIdx;
if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) {
I->setFrameIdx(FrameIdx);
continue;
}
const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots;
while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots &&
FixedSlot->Reg != Reg)
++FixedSlot;
if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) {
unsigned Align = RC->getAlignment();
unsigned StackAlign = TFI->getStackAlignment();
Align = std::min(Align, StackAlign);
FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true);
if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx;
if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx;
} else {
FrameIdx =
MFI->CreateFixedSpillStackObject(RC->getSize(), FixedSlot->Offset);
}
I->setFrameIdx(FrameIdx);
}
}
MFI->setCalleeSavedInfo(CSI);
}
static void updateLiveness(MachineFunction &MF) {
MachineFrameInfo *MFI = MF.getFrameInfo();
SmallPtrSet<MachineBasicBlock *, 8> Visited;
SmallVector<MachineBasicBlock *, 8> WorkList;
MachineBasicBlock *Entry = &MF.front();
MachineBasicBlock *Save = MFI->getSavePoint();
if (!Save)
Save = Entry;
if (Entry != Save) {
WorkList.push_back(Entry);
Visited.insert(Entry);
}
Visited.insert(Save);
MachineBasicBlock *Restore = MFI->getRestorePoint();
if (Restore)
WorkList.push_back(Restore);
while (!WorkList.empty()) {
const MachineBasicBlock *CurBB = WorkList.pop_back_val();
if (CurBB == Save && Save != Restore)
continue;
for (MachineBasicBlock *SuccBB : CurBB->successors())
if (Visited.insert(SuccBB).second)
WorkList.push_back(SuccBB);
}
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
for (MachineBasicBlock *MBB : Visited) {
MCPhysReg Reg = CSI[i].getReg();
if (!MBB->isLiveIn(Reg))
MBB->addLiveIn(Reg);
}
}
}
void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) {
MachineFrameInfo *MFI = Fn.getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
MFI->setCalleeSavedInfoValid(true);
if (CSI.empty())
return;
const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
MachineBasicBlock::iterator I;
for (MachineBasicBlock *SaveBlock : SaveBlocks) {
I = SaveBlock->begin();
if (!TFI->spillCalleeSavedRegisters(*SaveBlock, I, CSI, TRI)) {
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
TII.storeRegToStackSlot(*SaveBlock, I, Reg, true, CSI[i].getFrameIdx(),
RC, TRI);
}
}
updateLiveness(Fn);
}
for (MachineBasicBlock *MBB : RestoreBlocks) {
I = MBB->end();
MachineBasicBlock::iterator I2 = I;
while (I2 != MBB->begin() && (--I2)->isTerminator())
I = I2;
bool AtStart = I == MBB->begin();
MachineBasicBlock::iterator BeforeI = I;
if (!AtStart)
--BeforeI;
if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) {
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
unsigned Reg = CSI[i].getReg();
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
TII.loadRegFromStackSlot(*MBB, I, Reg, CSI[i].getFrameIdx(), RC, TRI);
assert(I != MBB->begin() &&
"loadRegFromStackSlot didn't insert any code!");
if (AtStart)
I = MBB->begin();
else {
I = BeforeI;
++I;
}
}
}
}
}
static inline void
AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx,
bool StackGrowsDown, int64_t &Offset,
unsigned &MaxAlign, unsigned Skew) {
if (StackGrowsDown)
Offset += MFI->getObjectSize(FrameIdx);
unsigned Align = MFI->getObjectAlignment(FrameIdx);
MaxAlign = std::max(MaxAlign, Align);
Offset = RoundUpToAlignment(Offset, Align, Skew);
if (StackGrowsDown) {
DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n");
MFI->setObjectOffset(FrameIdx, -Offset); } else {
DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n");
MFI->setObjectOffset(FrameIdx, Offset);
Offset += MFI->getObjectSize(FrameIdx);
}
}
static void
AssignProtectedObjSet(const StackObjSet &UnassignedObjs,
SmallSet<int, 16> &ProtectedObjs,
MachineFrameInfo *MFI, bool StackGrowsDown,
int64_t &Offset, unsigned &MaxAlign, unsigned Skew) {
for (StackObjSet::const_iterator I = UnassignedObjs.begin(),
E = UnassignedObjs.end(); I != E; ++I) {
int i = *I;
AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew);
ProtectedObjs.insert(i);
}
}
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering();
StackProtector *SP = &getAnalysis<StackProtector>();
bool StackGrowsDown =
TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;
MachineFrameInfo *MFI = Fn.getFrameInfo();
int LocalAreaOffset = TFI.getOffsetOfLocalArea();
if (StackGrowsDown)
LocalAreaOffset = -LocalAreaOffset;
assert(LocalAreaOffset >= 0
&& "Local area offset should be in direction of stack growth");
int64_t Offset = LocalAreaOffset;
unsigned Skew = TFI.getStackAlignmentSkew(Fn);
for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) {
int64_t FixedOff;
if (StackGrowsDown) {
FixedOff = -MFI->getObjectOffset(i);
} else {
FixedOff = MFI->getObjectOffset(i) + MFI->getObjectSize(i);
}
if (FixedOff > Offset) Offset = FixedOff;
}
if (StackGrowsDown) {
for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) {
Offset += MFI->getObjectSize(i);
unsigned Align = MFI->getObjectAlignment(i);
Offset = RoundUpToAlignment(Offset, Align, Skew);
MFI->setObjectOffset(i, -Offset); }
} else {
int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex;
for (int i = MaxCSFI; i >= MinCSFI ; --i) {
unsigned Align = MFI->getObjectAlignment(i);
Offset = RoundUpToAlignment(Offset, Align, Skew);
MFI->setObjectOffset(i, Offset);
Offset += MFI->getObjectSize(i);
}
}
unsigned MaxAlign = MFI->getMaxAlignment();
const TargetRegisterInfo *RegInfo = Fn.getSubtarget().getRegisterInfo();
bool EarlyScavengingSlots = (TFI.hasFP(Fn) &&
TFI.isFPCloseToIncomingSP() &&
RegInfo->useFPForScavengingIndex(Fn) &&
!RegInfo->needsStackRealignment(Fn));
if (RS && EarlyScavengingSlots) {
SmallVector<int, 2> SFIs;
RS->getScavengingFrameIndices(SFIs);
for (SmallVectorImpl<int>::iterator I = SFIs.begin(),
IE = SFIs.end(); I != IE; ++I)
AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew);
}
if (MFI->getUseLocalStackAllocationBlock()) {
unsigned Align = MFI->getLocalFrameMaxAlign();
Offset = RoundUpToAlignment(Offset, Align, Skew);
DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) {
std::pair<int, int64_t> Entry = MFI->getLocalFrameObjectMap(i);
int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second;
DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" <<
FIOffset << "]\n");
MFI->setObjectOffset(Entry.first, FIOffset);
}
Offset += MFI->getLocalFrameSize();
MaxAlign = std::max(Align, MaxAlign);
}
SmallSet<int, 16> ProtectedObjs;
if (MFI->getStackProtectorIndex() >= 0) {
StackObjSet LargeArrayObjs;
StackObjSet SmallArrayObjs;
StackObjSet AddrOfObjs;
AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown,
Offset, MaxAlign, Skew);
for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
if (MFI->isObjectPreAllocated(i) &&
MFI->getUseLocalStackAllocationBlock())
continue;
if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex)
continue;
if (RS && RS->isScavengingFrameIndex((int)i))
continue;
if (MFI->isDeadObjectIndex(i))
continue;
if (MFI->getStackProtectorIndex() == (int)i)
continue;
switch (SP->getSSPLayout(MFI->getObjectAllocation(i))) {
case StackProtector::SSPLK_None:
continue;
case StackProtector::SSPLK_SmallArray:
SmallArrayObjs.insert(i);
continue;
case StackProtector::SSPLK_AddrOf:
AddrOfObjs.insert(i);
continue;
case StackProtector::SSPLK_LargeArray:
LargeArrayObjs.insert(i);
continue;
}
llvm_unreachable("Unexpected SSPLayoutKind.");
}
AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
Offset, MaxAlign, Skew);
AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
Offset, MaxAlign, Skew);
AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown,
Offset, MaxAlign, Skew);
}
for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
if (MFI->isObjectPreAllocated(i) &&
MFI->getUseLocalStackAllocationBlock())
continue;
if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex)
continue;
if (RS && RS->isScavengingFrameIndex((int)i))
continue;
if (MFI->isDeadObjectIndex(i))
continue;
if (MFI->getStackProtectorIndex() == (int)i)
continue;
if (ProtectedObjs.count(i))
continue;
AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew);
}
if (RS && !EarlyScavengingSlots) {
SmallVector<int, 2> SFIs;
RS->getScavengingFrameIndices(SFIs);
for (SmallVectorImpl<int>::iterator I = SFIs.begin(),
IE = SFIs.end(); I != IE; ++I)
AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew);
}
if (!TFI.targetHandlesStackFrameRounding()) {
if (MFI->adjustsStack() && TFI.hasReservedCallFrame(Fn))
Offset += MFI->getMaxCallFrameSize();
unsigned StackAlign;
if (MFI->adjustsStack() || MFI->hasVarSizedObjects() ||
(RegInfo->needsStackRealignment(Fn) && MFI->getObjectIndexEnd() != 0))
StackAlign = TFI.getStackAlignment();
else
StackAlign = TFI.getTransientStackAlignment();
StackAlign = std::max(StackAlign, MaxAlign);
Offset = RoundUpToAlignment(Offset, StackAlign, Skew);
}
int64_t StackSize = Offset - LocalAreaOffset;
MFI->setStackSize(StackSize);
NumBytesStackSpace += StackSize;
}
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering();
for (MachineBasicBlock *SaveBlock : SaveBlocks)
TFI.emitPrologue(Fn, *SaveBlock);
for (MachineBasicBlock *RestoreBlock : RestoreBlocks)
TFI.emitEpilogue(Fn, *RestoreBlock);
if (Fn.shouldSplitStack()) {
for (MachineBasicBlock *SaveBlock : SaveBlocks)
TFI.adjustForSegmentedStacks(Fn, *SaveBlock);
}
if (Fn.getFunction()->getCallingConv() == CallingConv::HiPE)
for (MachineBasicBlock *SaveBlock : SaveBlocks)
TFI.adjustForHiPEPrologue(Fn, *SaveBlock);
}
void PEI::replaceFrameIndices(MachineFunction &Fn) {
const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering();
if (!TFI.needsFrameIndexResolution(Fn)) return;
SmallVector<int, 8> SPState;
SPState.resize(Fn.getNumBlockIDs());
SmallPtrSet<MachineBasicBlock*, 8> Reachable;
for (auto DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable);
DFI != DFE; ++DFI) {
int SPAdj = 0;
if (DFI.getPathLength() >= 2) {
MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2);
assert(Reachable.count(StackPred) &&
"DFS stack predecessor is already visited.\n");
SPAdj = SPState[StackPred->getNumber()];
}
MachineBasicBlock *BB = *DFI;
replaceFrameIndices(BB, Fn, SPAdj);
SPState[BB->getNumber()] = SPAdj;
}
for (auto &BB : Fn) {
if (Reachable.count(&BB))
continue;
int SPAdj = 0;
replaceFrameIndices(&BB, Fn, SPAdj);
}
}
void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn,
int &SPAdj) {
assert(Fn.getSubtarget().getRegisterInfo() &&
"getRegisterInfo() must be implemented!");
const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo();
const TargetRegisterInfo &TRI = *Fn.getSubtarget().getRegisterInfo();
const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();
unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode();
unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode();
if (RS && !FrameIndexVirtualScavenging) RS->enterBasicBlock(BB);
bool InsideCallSequence = false;
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) {
if (I->getOpcode() == FrameSetupOpcode ||
I->getOpcode() == FrameDestroyOpcode) {
InsideCallSequence = (I->getOpcode() == FrameSetupOpcode);
SPAdj += TII.getSPAdjust(I);
MachineBasicBlock::iterator PrevI = BB->end();
if (I != BB->begin()) PrevI = std::prev(I);
TFI->eliminateCallFramePseudoInstr(Fn, *BB, I);
if (PrevI == BB->end())
I = BB->begin(); else
I = std::next(PrevI);
continue;
}
MachineInstr *MI = I;
bool DoIncr = true;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
if (!MI->getOperand(i).isFI())
continue;
if (MI->isDebugValue()) {
assert(i == 0 && "Frame indices can only appear as the first "
"operand of a DBG_VALUE machine instruction");
unsigned Reg;
MachineOperand &Offset = MI->getOperand(1);
Offset.setImm(Offset.getImm() +
TFI->getFrameIndexReference(
Fn, MI->getOperand(0).getIndex(), Reg));
MI->getOperand(0).ChangeToRegister(Reg, false );
continue;
}
if (MI->getOpcode() == TargetOpcode::STATEPOINT) {
assert((!MI->isDebugValue() || i == 0) &&
"Frame indicies can only appear as the first operand of a "
"DBG_VALUE machine instruction");
unsigned Reg;
MachineOperand &Offset = MI->getOperand(i + 1);
const unsigned refOffset =
TFI->getFrameIndexReferenceFromSP(Fn, MI->getOperand(i).getIndex(),
Reg);
Offset.setImm(Offset.getImm() + refOffset);
MI->getOperand(i).ChangeToRegister(Reg, false );
continue;
}
bool AtBeginning = (I == BB->begin());
if (!AtBeginning) --I;
TRI.eliminateFrameIndex(MI, SPAdj, i,
FrameIndexVirtualScavenging ? nullptr : RS);
if (AtBeginning) {
I = BB->begin();
DoIncr = false;
}
MI = nullptr;
break;
}
if (MI && InsideCallSequence)
SPAdj += TII.getSPAdjust(MI);
if (DoIncr && I != BB->end()) ++I;
if (RS && !FrameIndexVirtualScavenging && MI) RS->forward(MI);
}
}
void
PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
for (MachineFunction::iterator BB = Fn.begin(),
E = Fn.end(); BB != E; ++BB) {
RS->enterBasicBlock(&*BB);
int SPAdj = 0;
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) {
if (I == MachineBasicBlock::iterator(nullptr))
I = BB->begin();
MachineInstr *MI = I;
MachineBasicBlock::iterator J = std::next(I);
MachineBasicBlock::iterator P =
I == BB->begin() ? MachineBasicBlock::iterator(nullptr)
: std::prev(I);
RS->forward(I);
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
if (MI->getOperand(i).isReg()) {
MachineOperand &MO = MI->getOperand(i);
unsigned Reg = MO.getReg();
if (Reg == 0)
continue;
if (!TargetRegisterInfo::isVirtualRegister(Reg))
continue;
assert(MI->getOperand(i).isDef() &&
"frame index virtual missing def!");
const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg);
unsigned ScratchReg = RS->scavengeRegister(RC, J, SPAdj);
++NumScavengedRegs;
assert (ScratchReg && "Missing scratch register!");
Fn.getRegInfo().replaceRegWith(Reg, ScratchReg);
RS->setRegUsed(ScratchReg);
}
}
if (I != std::prev(J)) {
BB->splice(J, &*BB, I);
assert(RS->getCurrentPosition() == I &&
"The register scavenger has an unexpected position");
I = P;
RS->unprocess(P);
} else
++I;
}
}
}