1//===- StackSlotColoring.cpp - Stack slot coloring pass. ------------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 9// This file implements the stack slot coloring pass. 11//===----------------------------------------------------------------------===// 48#define DEBUG_TYPE "stack-slot-coloring" 53cl::desc(
"Suppress slot sharing during stack coloring"));
57STATISTIC(NumEliminated,
"Number of stack slots eliminated due to coloring");
58STATISTIC(NumDead,
"Number of trivially dead stack accesses eliminated");
69// SSIntervals - Spill slot intervals. 70 std::vector<LiveInterval*> SSIntervals;
72// SSRefs - Keep a list of MachineMemOperands for each spill slot. 73// MachineMemOperands can be shared between instructions, so we need 74// to be careful that renames like [FI0, FI1] -> [FI1, FI2] do not 75// become FI0 -> FI1 -> FI2. 78// OrigAlignments - Alignments of stack objects before coloring. 81// OrigSizes - Sizes of stack objects before coloring. 84// AllColors - If index is set, it's a spill slot, i.e. color. 85// FIXME: This assumes PEI locate spill slot with smaller indices 86// closest to stack pointer / frame pointer. Therefore, smaller 87// index == better color. This is per stack ID. 90// NextColor - Next "color" that's not yet used. This is per stack ID. 93// UsedColors - "Colors" that have been assigned. This is per stack ID 96// Join all intervals sharing one color into a single LiveIntervalUnion to 97// speedup range overlap test. 98classColorAssignmentInfo {
99// Single liverange (used to avoid creation of LiveIntervalUnion). 101// LiveIntervalUnion to perform overlap test. 103// LiveIntervalUnion has a parameter in its constructor so doing this 108 ~ColorAssignmentInfo() {
110 LIU->~LiveIntervalUnion();
// Dirty magic again. 113// Return true if LiveInterval overlaps with any 114// intervals that have already been assigned to this color. 118return SingleLI ? SingleLI->
overlaps(*LI) :
false;
121// Add new LiveInterval to this color. 125 LIU->
unify(*LI, *LI);
128 LIU->
unify(*SingleLI, *SingleLI);
129 LIU->
unify(*LI, *LI);
138// Assignments - Color to intervals mapping. 142staticcharID;
// Pass identification 157// In some Target's pipeline, register allocation (RA) might be 158// split into multiple phases based on register class. So, this pass 159// may be invoked multiple times requiring it to save these analyses to be 170void InitializeSlots();
179}
// end anonymous namespace 181char StackSlotColoring::ID = 0;
186"Stack Slot Coloring",
false,
false)
195// IntervalSorter - Comparison predicate that sort live intervals by 199returnLHS->weight() >
RHS->weight();
203}
// end anonymous namespace 205/// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot 206/// references and update spill slot weights. 210// FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands. 216int FI = MO.getIndex();
219if (!
LS->hasInterval(FI))
222if (!
MI.isDebugInstr())
228 dyn_cast_or_null<FixedStackPseudoSourceValue>(
229 MMO->getPseudoValue())) {
230int FI = FSV->getFrameIndex();
239/// InitializeSlots - Process all spill stack slot liveintervals and add them 240/// to a sorted (by weight) list. 241void StackSlotColoring::InitializeSlots() {
244// There is always at least one stack ID. 248 OrigAlignments.
resize(LastFI);
250 AllColors[0].
resize(LastFI);
251 UsedColors[0].
resize(LastFI);
252 Assignments.
resize(LastFI);
254usingPair = std::iterator_traits<LiveStacks::iterator>::value_type;
258 Intervals.
reserve(
LS->getNumIntervals());
262 [](Pair *LHS, Pair *RHS) {
returnLHS->first <
RHS->first; });
264// Gather all spill slots into a list. 266for (
auto *
I : Intervals) {
273 SSIntervals.push_back(&li);
279 AllColors.
resize(StackID + 1);
280 UsedColors.
resize(StackID + 1);
281 AllColors[StackID].
resize(LastFI);
282 UsedColors[StackID].
resize(LastFI);
285 AllColors[StackID].set(FI);
289// Sort them by weight. 295for (
unsignedI = 0, E = AllColors.
size();
I != E; ++
I)
296 NextColors[
I] = AllColors[
I].find_first();
299/// ColorSlot - Assign a "color" (stack slot) to the specified stack slot. 308// Check if it's possible to reuse any of the used colors. 309 Color = UsedColors[StackID].find_first();
311if (!Assignments[Color].overlaps(li)) {
316 Color = UsedColors[StackID].find_next(Color);
321LLVM_DEBUG(
dbgs() <<
"cannot share FIs with different stack IDs\n");
325// Assign it to the first available color (assumed to be the best) if it's 326// not possible to share a used color with other objects. 328assert(NextColors[StackID] != -1 &&
"No more spill slots?");
329 Color = NextColors[StackID];
330 UsedColors[StackID].set(Color);
331 NextColors[StackID] = AllColors[StackID].find_next(NextColors[StackID]);
336// Record the assignment. 337 Assignments[Color].add(li, LIUAlloc);
338LLVM_DEBUG(
dbgs() <<
"Assigning fi#" << FI <<
" to fi#" << Color <<
"\n");
340// Change size and alignment of the allocated slot. If there are multiple 341// objects sharing the same slot, then make sure the size and alignment 342// are large enough for all. 343Align Alignment = OrigAlignments[FI];
346 int64_t
Size = OrigSizes[FI];
352/// Colorslots - Color all spill stack slots and rewrite all frameindex machine 353/// operands in the function. 365int NewSS = ColorSlot(li);
366assert(NewSS >= 0 &&
"Stack coloring failed?");
368 RevMap[NewSS].push_back(SS);
369 SlotWeights[NewSS] += li->
weight();
370 UsedColors.set(NewSS);
371 Changed |= (
SS != NewSS);
379// Sort them by new weight. 391// Rewrite all MachineMemOperands. 392for (
unsigned SS = 0, SE = SSRefs.
size(); SS != SE; ++SS) {
394if (NewFI == -1 || (NewFI == (
int)SS))
400 MMO->setValue(NewSV);
403// Rewrite all MO_FrameIndex operands. Look for dead stores. 407 RemoveDeadStores(&
MBB);
410// Delete unused stack slots. 411for (
int StackID = 0, E = AllColors.
size(); StackID != E; ++StackID) {
412int NextColor = NextColors[StackID];
413while (NextColor != -1) {
414LLVM_DEBUG(
dbgs() <<
"Removing unused stack object fi#" << NextColor <<
"\n");
416 NextColor = AllColors[StackID].find_next(NextColor);
423/// RewriteInstruction - Rewrite specified instruction by replacing references 424/// to old frame index with new one. 428// Update the operands. 432int OldFI = MO.getIndex();
436if (NewFI == -1 || NewFI == OldFI)
443// The MachineMemOperands have already been updated. 446/// RemoveDeadStores - Scan through a basic block and look for loads followed 447/// by stores. If they're both using the same stack slot, then the store is 448/// definitely dead. This could obviously be much more aggressive (consider 449/// pairs with instructions between them), but such extensions might have a 450/// considerable compile time impact. 452// FIXME: This could be much more aggressive, but we need to investigate 453// the compile time impact of doing so. 462int FirstSS, SecondSS;
463if (
TII->isStackSlotCopy(*
I, FirstSS, SecondSS) && FirstSS == SecondSS &&
476unsigned LoadSize = 0;
477unsigned StoreSize = 0;
480// Skip the ...pseudo debugging... instructions between a load and store. 481while ((NextMI != E) && NextMI->isDebugInstr()) {
485if (NextMI == E)
continue;
488if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1 ||
495if (NextMI->findRegisterUseOperandIdx(LoadReg,
/*TRI=*/nullptr,
true) !=
508MI->eraseFromParent();
516dbgs() <<
"********** Stack Slot Coloring **********\n" 517 <<
"********** Function: " << MF.
getName() <<
'\n';
525LS = &getAnalysis<LiveStacksWrapperLegacy>().getLS();
526 MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
527 Indexes = &getAnalysis<SlotIndexesWrapperPass>().getSI();
531unsigned NumSlots =
LS->getNumIntervals();
536// If there are calls to setjmp or sigsetjmp, don't perform stack slot 537// coloring. The stack could be modified before the longjmp is executed, 538// resulting in the wrong value being used afterwards. 542// Gather spill slot references 543 ScanForSpillSlotRefs(MF);
545 Changed = ColorSlots(MF);
547for (
int &Next : NextColors)
551for (
auto &RefMMOs : SSRefs)
554 OrigAlignments.
clear();
This file implements the BitVector class.
const HexagonInstrInfo * TII
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
Represent the analysis usage information of a pass.
AnalysisUsage & addPreservedID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
A specialized PseudoSourceValue for holding FixedStack values, which must include a frame index.
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...
Query interferences between a single live virtual register and a live interval union.
Union of live intervals that are strong candidates for coalescing into a single register (either phys...
void unify(const LiveInterval &VirtReg, const LiveRange &Range)
LiveSegments::Allocator Allocator
LiveInterval - This class represents the liveness of a register, or stack slot.
void incrementWeight(float Inc)
void setWeight(float Value)
static 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.
bool overlaps(const LiveRange &other) const
overlaps - Return true if the intersection of the two live ranges is not empty.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
PseudoSourceValueManager & getPSVManager() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
A description of a memory reference used in the backend.
MachineOperand class - Representation of each machine instruction operand.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const PseudoSourceValue * getFixedStack(int FI)
Return a pseudo source value referencing a fixed stack frame entry, e.g., a spill slot.
Special value supplied for machine level alias analysis.
Wrapper class representing virtual and physical registers.
static int stackSlot2Index(Register Reg)
Compute the frame index from a register value representing a stack slot.
void removeMachineInstrFromMaps(MachineInstr &MI, bool AllowBundled=false)
Removes machine instruction (bundle) MI from the mapping.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
void initializeStackSlotColoringPass(PassRegistry &)
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
char & StackSlotColoringID
StackSlotColoring - This pass performs stack slot coloring.
bool operator()(LiveInterval *LHS, LiveInterval *RHS) const
This struct is a compact representation of a valid (non-zero power of two) alignment.
This struct contains the mappings from the slot numbers to unnamed metadata nodes,...