51#define DEBUG_TYPE "stack-slot-coloring"
56 cl::desc(
"Suppress slot sharing during stack coloring"));
60STATISTIC(NumEliminated,
"Number of stack slots eliminated due to coloring");
61STATISTIC(NumDead,
"Number of trivially dead stack accesses eliminated");
65class StackSlotColoring {
73 std::vector<LiveInterval *> SSIntervals;
101 class ColorAssignmentInfo {
103 LiveInterval *SingleLI =
nullptr;
105 LiveIntervalUnion *LIU =
nullptr;
108 uint8_t LIUPad[
sizeof(LiveIntervalUnion)];
111 ~ColorAssignmentInfo() {
113 LIU->~LiveIntervalUnion();
118 bool overlaps(LiveInterval *LI)
const {
120 return LiveIntervalUnion::Query(*LI, *LIU).checkInterference();
121 return SingleLI ? SingleLI->overlaps(*LI) :
false;
128 LIU->unify(*LI, *LI);
129 }
else if (SingleLI) {
130 LIU =
new (LIUPad) LiveIntervalUnion(
Alloc);
131 LIU->unify(*SingleLI, *SingleLI);
132 LIU->unify(*LI, *LI);
145 StackSlotColoring(MachineFunction &MF, LiveStacks *LS,
146 MachineBlockFrequencyInfo *MBFI, SlotIndexes *Indexes)
147 : MFI(&MF.getFrameInfo()), TII(MF.getSubtarget().getInstrInfo()), LS(LS),
148 MBFI(MBFI), Indexes(Indexes) {}
149 bool run(MachineFunction &MF);
152 void InitializeSlots();
153 void ScanForSpillSlotRefs(MachineFunction &MF);
154 int ColorSlot(LiveInterval *li);
155 bool ColorSlots(MachineFunction &MF);
156 void RewriteInstruction(MachineInstr &
MI, SmallVectorImpl<int> &SlotMapping,
157 MachineFunction &MF);
158 bool RemoveDeadStores(MachineBasicBlock *
MBB);
165 StackSlotColoringLegacy() : MachineFunctionPass(ID) {}
167 void getAnalysisUsage(AnalysisUsage &AU)
const override {
172 AU.
addRequired<MachineBlockFrequencyInfoWrapperPass>();
184 bool runOnMachineFunction(MachineFunction &MF)
override;
189char StackSlotColoringLegacy::ID = 0;
194 "Stack Slot Coloring",
false,
false)
207 return LHS->weight() > RHS->weight();
219 for (MachineBasicBlock &
MBB : MF) {
220 for (MachineInstr &
MI :
MBB) {
221 for (
const MachineOperand &MO :
MI.operands()) {
224 int FI = MO.getIndex();
227 if (!
LS->hasInterval(FI))
229 LiveInterval &li =
LS->getInterval(FI);
230 if (!
MI.isDebugInstr())
234 for (MachineMemOperand *MMO :
MI.memoperands()) {
235 if (
const FixedStackPseudoSourceValue *FSV =
237 MMO->getPseudoValue())) {
238 int FI = FSV->getFrameIndex();
249void StackSlotColoring::InitializeSlots() {
256 OrigAlignments.
resize(LastFI);
258 AllColors[0].
resize(LastFI);
259 UsedColors[0].
resize(LastFI);
260 Assignments.resize(LastFI);
262 using Pair = std::iterator_traits<LiveStacks::iterator>::value_type;
266 Intervals.
reserve(
LS->getNumIntervals());
270 [](Pair *
LHS, Pair *
RHS) {
return LHS->first <
RHS->first; });
274 for (
auto *
I : Intervals) {
275 LiveInterval &li =
I->second;
281 SSIntervals.push_back(&li);
287 if (StackID >= AllColors.
size()) {
288 AllColors.
resize(StackID + 1);
289 UsedColors.
resize(StackID + 1);
291 AllColors[StackID].
resize(LastFI);
292 UsedColors[StackID].
resize(LastFI);
295 AllColors[StackID].set(FI);
305 for (
unsigned I = 0,
E = AllColors.
size();
I !=
E; ++
I)
306 NextColors[
I] = AllColors[
I].find_first();
310int StackSlotColoring::ColorSlot(LiveInterval *li) {
319 Color = UsedColors[StackID].find_first();
320 while (Color != -1) {
321 if (!Assignments[Color].overlaps(li)) {
326 Color = UsedColors[StackID].find_next(Color);
331 LLVM_DEBUG(
dbgs() <<
"cannot share FIs with different stack IDs\n");
338 assert(NextColors[StackID] != -1 &&
"No more spill slots?");
339 Color = NextColors[StackID];
340 UsedColors[StackID].set(Color);
341 NextColors[StackID] = AllColors[StackID].find_next(NextColors[StackID]);
347 Assignments[Color].add(li, LIUAlloc);
348 LLVM_DEBUG(
dbgs() <<
"Assigning fi#" << FI <<
" to fi#" << Color <<
"\n");
353 Align Alignment = OrigAlignments[FI];
356 int64_t
Size = OrigSizes[FI];
364bool StackSlotColoring::ColorSlots(MachineFunction &MF) {
366 SmallVector<int, 16> SlotMapping(NumObjs, -1);
369 BitVector UsedColors(NumObjs);
373 for (LiveInterval *li : SSIntervals) {
375 int NewSS = ColorSlot(li);
376 assert(NewSS >= 0 &&
"Stack coloring failed?");
377 SlotMapping[
SS] = NewSS;
378 RevMap[NewSS].push_back(SS);
379 SlotWeights[NewSS] += li->
weight();
380 UsedColors.set(NewSS);
385 for (LiveInterval *li : SSIntervals) {
393 for (LiveInterval *li : SSIntervals)
402 for (
unsigned SS = 0, SE = SSRefs.
size(); SS != SE; ++SS) {
403 int NewFI = SlotMapping[
SS];
404 if (NewFI == -1 || (NewFI == (
int)SS))
408 SmallVectorImpl<MachineMemOperand *> &RefMMOs = SSRefs[
SS];
409 for (MachineMemOperand *MMO : RefMMOs)
410 MMO->setValue(NewSV);
414 for (MachineBasicBlock &
MBB : MF) {
415 for (MachineInstr &
MI :
MBB)
416 RewriteInstruction(
MI, SlotMapping, MF);
417 RemoveDeadStores(&
MBB);
421 for (
int StackID = 0,
E = AllColors.
size(); StackID !=
E; ++StackID) {
422 int NextColor = NextColors[StackID];
423 while (NextColor != -1) {
424 LLVM_DEBUG(
dbgs() <<
"Removing unused stack object fi#" << NextColor <<
"\n");
426 NextColor = AllColors[StackID].find_next(NextColor);
435void StackSlotColoring::RewriteInstruction(MachineInstr &
MI,
436 SmallVectorImpl<int> &SlotMapping,
437 MachineFunction &MF) {
439 for (MachineOperand &MO :
MI.operands()) {
442 int OldFI = MO.getIndex();
445 int NewFI = SlotMapping[OldFI];
446 if (NewFI == -1 || NewFI == OldFI)
461bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock*
MBB) {
464 bool changed =
false;
466 SmallVector<MachineInstr*, 4> toErase;
472 int FirstSS, SecondSS;
473 if (
TII->isStackSlotCopy(*
I, FirstSS, SecondSS) && FirstSS == SecondSS &&
491 while ((NextMI !=
E) && NextMI->isDebugInstr()) {
495 if (NextMI ==
E)
continue;
499 if (!LoadSize || !StoreSize)
501 if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1 ||
508 if (NextMI->findRegisterUseOperandIdx(LoadReg,
nullptr,
true) !=
518 for (MachineInstr *
MI : toErase) {
521 MI->eraseFromParent();
527bool StackSlotColoring::run(MachineFunction &MF) {
529 dbgs() <<
"********** Stack Slot Coloring **********\n"
530 <<
"********** Function: " << MF.
getName() <<
'\n';
535 unsigned NumSlots =
LS->getNumIntervals();
547 ScanForSpillSlotRefs(MF);
551 for (
int &
Next : NextColors)
555 for (
auto &RefMMOs : SSRefs)
558 OrigAlignments.
clear();
567bool StackSlotColoringLegacy::runOnMachineFunction(MachineFunction &MF) {
571 LiveStacks *
LS = &getAnalysis<LiveStacksWrapperLegacy>().getLS();
572 MachineBlockFrequencyInfo *MBFI =
573 &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
574 SlotIndexes *Indexes = &getAnalysis<SlotIndexesWrapperPass>().getSI();
575 StackSlotColoring Impl(MF, LS, MBFI, Indexes);
586 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 & 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...
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.
LLVM_ABI 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)
DXILDebugInfoMap run(Module &M)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool operator()(LiveInterval *LHS, LiveInterval *RHS) const