50#define DEBUG_TYPE "stack-slot-coloring"
55 cl::desc(
"Suppress slot sharing during stack coloring"));
59STATISTIC(NumEliminated,
"Number of stack slots eliminated due to coloring");
60STATISTIC(NumDead,
"Number of trivially dead stack accesses eliminated");
64class StackSlotColoring {
72 std::vector<LiveInterval *> SSIntervals;
100 class ColorAssignmentInfo {
102 LiveInterval *SingleLI =
nullptr;
104 LiveIntervalUnion *LIU =
nullptr;
107 uint8_t LIUPad[
sizeof(LiveIntervalUnion)];
110 ~ColorAssignmentInfo() {
112 LIU->~LiveIntervalUnion();
117 bool overlaps(LiveInterval *LI)
const {
119 return LiveIntervalUnion::Query(*LI, *LIU).checkInterference();
120 return SingleLI ? SingleLI->overlaps(*LI) :
false;
127 LIU->unify(*LI, *LI);
128 }
else if (SingleLI) {
129 LIU =
new (LIUPad) LiveIntervalUnion(
Alloc);
130 LIU->unify(*SingleLI, *SingleLI);
131 LIU->unify(*LI, *LI);
144 StackSlotColoring(MachineFunction &MF, LiveStacks *LS,
145 MachineBlockFrequencyInfo *MBFI, SlotIndexes *Indexes)
146 : MFI(&MF.getFrameInfo()), TII(MF.getSubtarget().getInstrInfo()), LS(LS),
147 MBFI(MBFI), Indexes(Indexes) {}
148 bool run(MachineFunction &MF);
151 void InitializeSlots();
152 void ScanForSpillSlotRefs(MachineFunction &MF);
153 int ColorSlot(LiveInterval *li);
154 bool ColorSlots(MachineFunction &MF);
155 void RewriteInstruction(MachineInstr &
MI, SmallVectorImpl<int> &SlotMapping,
156 MachineFunction &MF);
157 bool RemoveDeadStores(MachineBasicBlock *
MBB);
164 StackSlotColoringLegacy() : MachineFunctionPass(ID) {}
166 void getAnalysisUsage(AnalysisUsage &AU)
const override {
171 AU.
addRequired<MachineBlockFrequencyInfoWrapperPass>();
172 AU.
addPreserved<MachineBlockFrequencyInfoWrapperPass>();
185 bool runOnMachineFunction(MachineFunction &MF)
override;
190char StackSlotColoringLegacy::ID = 0;
195 "Stack Slot Coloring",
false,
false)
208 return LHS->weight() > RHS->weight();
220 for (MachineBasicBlock &
MBB : MF) {
221 for (MachineInstr &
MI :
MBB) {
222 for (
const MachineOperand &MO :
MI.operands()) {
225 int FI = MO.getIndex();
228 if (!
LS->hasInterval(FI))
230 LiveInterval &li =
LS->getInterval(FI);
231 if (!
MI.isDebugInstr())
235 for (MachineMemOperand *MMO :
MI.memoperands()) {
236 if (
const FixedStackPseudoSourceValue *FSV =
238 MMO->getPseudoValue())) {
239 int FI = FSV->getFrameIndex();
250void StackSlotColoring::InitializeSlots() {
257 OrigAlignments.
resize(LastFI);
259 AllColors[0].
resize(LastFI);
260 UsedColors[0].
resize(LastFI);
261 Assignments.resize(LastFI);
263 using Pair = std::iterator_traits<LiveStacks::iterator>::value_type;
267 Intervals.
reserve(
LS->getNumIntervals());
271 [](Pair *
LHS, Pair *
RHS) {
return LHS->first <
RHS->first; });
275 for (
auto *
I : Intervals) {
276 LiveInterval &li =
I->second;
282 SSIntervals.push_back(&li);
288 if (StackID >= AllColors.
size()) {
289 AllColors.
resize(StackID + 1);
290 UsedColors.
resize(StackID + 1);
292 AllColors[StackID].
resize(LastFI);
293 UsedColors[StackID].
resize(LastFI);
296 AllColors[StackID].set(FI);
306 for (
unsigned I = 0,
E = AllColors.
size();
I !=
E; ++
I)
307 NextColors[
I] = AllColors[
I].find_first();
311int StackSlotColoring::ColorSlot(LiveInterval *li) {
320 Color = UsedColors[StackID].find_first();
321 while (Color != -1) {
322 if (!Assignments[Color].overlaps(li)) {
327 Color = UsedColors[StackID].find_next(Color);
332 LLVM_DEBUG(
dbgs() <<
"cannot share FIs with different stack IDs\n");
339 assert(NextColors[StackID] != -1 &&
"No more spill slots?");
340 Color = NextColors[StackID];
341 UsedColors[StackID].set(Color);
342 NextColors[StackID] = AllColors[StackID].find_next(NextColors[StackID]);
348 Assignments[Color].add(li, LIUAlloc);
349 LLVM_DEBUG(
dbgs() <<
"Assigning fi#" << FI <<
" to fi#" << Color <<
"\n");
354 Align Alignment = OrigAlignments[FI];
357 int64_t
Size = OrigSizes[FI];
365bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
367 SmallVector<int, 16> SlotMapping(NumObjs, -1);
370 BitVector UsedColors(NumObjs);
374 for (LiveInterval *li : SSIntervals) {
376 int NewSS = ColorSlot(li);
377 assert(NewSS >= 0 &&
"Stack coloring failed?");
378 SlotMapping[
SS] = NewSS;
379 RevMap[NewSS].push_back(SS);
380 SlotWeights[NewSS] += li->
weight();
381 UsedColors.set(NewSS);
386 for (LiveInterval *li : SSIntervals) {
394 for (LiveInterval *li : SSIntervals)
403 for (
unsigned SS = 0, SE = SSRefs.
size(); SS != SE; ++SS) {
404 int NewFI = SlotMapping[
SS];
405 if (NewFI == -1 || (NewFI == (
int)SS))
409 SmallVectorImpl<MachineMemOperand *> &RefMMOs = SSRefs[
SS];
410 for (MachineMemOperand *MMO : RefMMOs)
411 MMO->setValue(NewSV);
415 for (MachineBasicBlock &
MBB : MF) {
416 for (MachineInstr &
MI :
MBB)
417 RewriteInstruction(
MI, SlotMapping, MF);
418 RemoveDeadStores(&
MBB);
422 for (
int StackID = 0,
E = AllColors.
size(); StackID !=
E; ++StackID) {
423 int NextColor = NextColors[StackID];
424 while (NextColor != -1) {
425 LLVM_DEBUG(
dbgs() <<
"Removing unused stack object fi#" << NextColor <<
"\n");
427 NextColor = AllColors[StackID].find_next(NextColor);
436void StackSlotColoring::RewriteInstruction(MachineInstr &
MI,
437 SmallVectorImpl<int> &SlotMapping,
438 MachineFunction &MF) {
440 for (MachineOperand &MO :
MI.operands()) {
443 int OldFI = MO.getIndex();
446 int NewFI = SlotMapping[OldFI];
447 if (NewFI == -1 || NewFI == OldFI)
462bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock*
MBB) {
465 bool changed =
false;
467 SmallVector<MachineInstr*, 4> toErase;
473 int FirstSS, SecondSS;
474 if (
TII->isStackSlotCopy(*
I, FirstSS, SecondSS) && FirstSS == SecondSS &&
492 while ((NextMI !=
E) && NextMI->isDebugInstr()) {
496 if (NextMI ==
E)
continue;
499 if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1 ||
506 if (NextMI->findRegisterUseOperandIdx(LoadReg,
nullptr,
true) !=
516 for (MachineInstr *
MI : toErase) {
519 MI->eraseFromParent();
525bool StackSlotColoring::run(MachineFunction &MF) {
527 dbgs() <<
"********** Stack Slot Coloring **********\n"
528 <<
"********** Function: " << MF.
getName() <<
'\n';
533 unsigned NumSlots =
LS->getNumIntervals();
545 ScanForSpillSlotRefs(MF);
549 for (
int &
Next : NextColors)
553 for (
auto &RefMMOs : SSRefs)
556 OrigAlignments.
clear();
565bool StackSlotColoringLegacy::runOnMachineFunction(MachineFunction &MF) {
569 LiveStacks *
LS = &getAnalysis<LiveStacksWrapperLegacy>().getLS();
570 MachineBlockFrequencyInfo *MBFI =
571 &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
572 SlotIndexes *Indexes = &getAnalysis<SlotIndexesWrapperPass>().getSI();
573 StackSlotColoring Impl(MF, LS, MBFI, Indexes);
584 StackSlotColoring Impl(MF, LS, MBFI, Indexes);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the BitVector class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
static cl::opt< bool > DisableSharing("no-stack-slot-sharing", cl::init(false), cl::Hidden, cl::desc("Suppress slot sharing during stack coloring"))
static cl::opt< int > DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
TargetInstrInfo overrides.
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
If the specified machine instruction is a direct store to a stack slot, return the virtual or physica...
LiveSegments::Allocator Allocator
LiveInterval - This class represents the liveness of a register, or stack slot.
LLVM_ABI void dump() const
void incrementWeight(float Inc)
void setWeight(float Value)
static LLVM_ABI float getSpillWeight(bool isDef, bool isUse, const MachineBlockFrequencyInfo *MBFI, const MachineInstr &MI, ProfileSummaryInfo *PSI=nullptr)
Calculate the spill weight to assign to a single instruction.
MachineInstrBundleIterator< MachineInstr > iterator
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
Analysis pass which computes a MachineDominatorTree.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setObjectSize(int ObjectIdx, int64_t Size)
Change the size of the specified stack object.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
bool isSpillSlotObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a spill slot.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
void RemoveStackObject(int ObjectIdx)
Remove or mark dead a statically sized stack object.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
uint8_t getStackID(int ObjectIdx) const
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
PseudoSourceValueManager & getPSVManager() const
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
bool exposesReturnsTwice() const
exposesReturnsTwice - Returns true if the function calls setjmp or any other similar functions with a...
Function & getFunction()
Return the LLVM function that this machine code represents.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
LLVM_ABI const PseudoSourceValue * getFixedStack(int FI)
Return a pseudo source value referencing a fixed stack frame entry, e.g., a spill slot.
int stackSlotIndex() const
Compute the frame index from a register value representing a stack slot.
LLVM_ABI void removeMachineInstrFromMaps(MachineInstr &MI, bool AllowBundled=false)
Removes machine instruction (bundle) MI from the mapping.
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
TargetInstrInfo - Interface to description of machine instruction set.
static constexpr TypeSize getZero()
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
LLVM_ABI char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto dyn_cast_or_null(const Y &Val)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI char & StackSlotColoringID
StackSlotColoring - This pass performs stack slot coloring.
FunctionAddr VTableAddr Next
bool operator()(LiveInterval *LHS, LiveInterval *RHS) const