24 #define DEBUG_TYPE "stackcoloring"
72 cl::desc(
"Do not optimize lifetime zones that "
75 STATISTIC(NumMarkerSeen,
"Number of lifetime markers found.");
76 STATISTIC(StackSpaceSaved,
"Number of bytes saved due to merging slots.");
77 STATISTIC(StackSlotMerged,
"Number of stack slot merged.");
78 STATISTIC(EscapedAllocas,
"Number of allocas that escaped the lifetime region");
94 struct BlockLifetimeInfo {
107 LivenessMap BlockLiveness;
127 struct SlotSizeSorter {
130 bool operator()(
int LHS,
int RHS) {
132 if (LHS == -1)
return false;
133 if (RHS == -1)
return true;
135 return MFI->getObjectSize(LHS) > MFI->getObjectSize(RHS);
153 bool removeAllMarkers();
158 unsigned collectMarkers(
unsigned NumSlot);
164 void calculateLocalLiveness();
167 void calculateLiveIntervals(
unsigned NumSlots);
179 void removeInvalidSlotRanges();
191 "stack-coloring",
"Merge disjoint stack slots",
false,
false)
197 void StackColoring::getAnalysisUsage(
AnalysisUsage &AU)
const {
207 DEBUG(
dbgs()<<
"Inspecting block #"<<BasicBlocks.lookup(*FI)<<
208 " ["<<FI->getName()<<
"]\n");
210 LivenessMap::const_iterator BI = BlockLiveness.find(*FI);
211 assert(BI != BlockLiveness.end() &&
"Block not found");
212 const BlockLifetimeInfo &BlockInfo = BI->second;
215 for (
unsigned i=0; i < BlockInfo.Begin.size(); ++i)
216 DEBUG(
dbgs()<<BlockInfo.Begin.test(i)<<
" ");
220 for (
unsigned i=0; i < BlockInfo.End.size(); ++i)
221 DEBUG(
dbgs()<<BlockInfo.End.test(i)<<
" ");
226 for (
unsigned i=0; i < BlockInfo.LiveIn.size(); ++i)
227 DEBUG(
dbgs()<<BlockInfo.LiveIn.test(i)<<
" ");
231 for (
unsigned i=0; i < BlockInfo.LiveOut.size(); ++i)
232 DEBUG(
dbgs()<<BlockInfo.LiveOut.test(i)<<
" ");
237 unsigned StackColoring::collectMarkers(
unsigned NumSlot) {
238 unsigned MarkersFound = 0;
247 BasicBlocks[*FI] = BasicBlockNumbering.size();
248 BasicBlockNumbering.push_back(*FI);
251 BlockLifetimeInfo &BlockInfo = BlockLiveness[*FI];
253 BlockInfo.Begin.resize(NumSlot);
254 BlockInfo.End.resize(NumSlot);
263 Markers.push_back(BI);
271 const AllocaInst *Allocation = MFI->getObjectAllocation(Slot);
273 DEBUG(
dbgs()<<
"Found a lifetime marker for slot #"<<Slot<<
274 " with allocation: "<< Allocation->
getName()<<
"\n");
278 BlockInfo.Begin.set(Slot);
280 if (BlockInfo.Begin.test(Slot)) {
284 BlockInfo.Begin.reset(Slot);
286 BlockInfo.End.set(Slot);
293 NumMarkerSeen += MarkersFound;
297 void StackColoring::calculateLocalLiveness() {
304 BasicBlockNumbering.end());
305 unsigned NumSSMIters = 0;
314 PI = BasicBlockNumbering.begin(), PE = BasicBlockNumbering.end();
318 if (!BBSet.count(BB))
continue;
321 LivenessMap::iterator BI = BlockLiveness.find(BB);
322 assert(BI != BlockLiveness.end() &&
"Block not found");
323 BlockLifetimeInfo &BlockInfo = BI->second;
330 PE = BB->
pred_end(); PI != PE; ++PI) {
331 LivenessMap::const_iterator
I = BlockLiveness.find(*PI);
332 assert(I != BlockLiveness.end() &&
"Predecessor not found");
333 LocalLiveIn |= I->second.LiveOut;
335 LocalLiveIn |= BlockInfo.End;
336 LocalLiveIn.
reset(BlockInfo.Begin);
340 SE = BB->
succ_end(); SI != SE; ++SI) {
341 LivenessMap::const_iterator I = BlockLiveness.find(*SI);
342 assert(I != BlockLiveness.end() &&
"Successor not found");
343 LocalLiveOut |= I->second.LiveIn;
345 LocalLiveOut |= BlockInfo.Begin;
346 LocalLiveOut.
reset(BlockInfo.End);
348 LocalLiveIn |= LocalLiveOut;
349 LocalLiveOut |= LocalLiveIn;
353 LocalLiveOut.
reset(BlockInfo.End);
354 LocalLiveIn.
reset(BlockInfo.Begin);
364 LocalEndBegin &= BlockInfo.Begin;
365 LocalLiveIn |= LocalEndBegin;
366 LocalLiveOut |= LocalEndBegin;
368 if (LocalLiveIn.
test(BlockInfo.LiveIn)) {
370 BlockInfo.LiveIn |= LocalLiveIn;
373 PE = BB->
pred_end(); PI != PE; ++PI)
377 if (LocalLiveOut.
test(BlockInfo.LiveOut)) {
379 BlockInfo.LiveOut |= LocalLiveOut;
382 SE = BB->
succ_end(); SI != SE; ++SI)
391 void StackColoring::calculateLiveIntervals(
unsigned NumSlots) {
398 MBB != MBBe; ++MBB) {
402 Finishes.
resize(NumSlots);
406 e = Markers.end(); it != e; ++it) {
413 "Invalid Lifetime marker");
418 assert(Slot >= 0 &&
"Invalid slot");
420 SlotIndex ThisIndex = Indexes->getInstructionIndex(MI);
423 if (!Starts[Slot].isValid() || Starts[Slot] > ThisIndex)
424 Starts[Slot] = ThisIndex;
426 if (!Finishes[Slot].isValid() || Finishes[Slot] < ThisIndex)
427 Finishes[Slot] = ThisIndex;
432 BlockLifetimeInfo &MBBLiveness = BlockLiveness[MBB];
433 for (
int pos = MBBLiveness.LiveIn.find_first(); pos != -1;
434 pos = MBBLiveness.LiveIn.find_next(pos)) {
435 Starts[pos] = Indexes->getMBBStartIdx(MBB);
437 for (
int pos = MBBLiveness.LiveOut.find_first(); pos != -1;
438 pos = MBBLiveness.LiveOut.find_next(pos)) {
439 Finishes[pos] = Indexes->getMBBEndIdx(MBB);
442 for (
unsigned i = 0; i < NumSlots; ++i) {
443 assert(Starts[i].isValid() == Finishes[i].isValid() &&
"Unmatched range");
444 if (!Starts[i].isValid())
447 assert(Starts[i] && Finishes[i] &&
"Invalid interval");
448 VNInfo *ValNum = Intervals[i]->getValNumInfo(0);
453 Intervals[i]->addSegment(LiveInterval::Segment(S, F, ValNum));
457 SlotIndex NewStart = Indexes->getMBBStartIdx(MBB);
458 SlotIndex NewFin = Indexes->getMBBEndIdx(MBB);
459 Intervals[i]->addSegment(LiveInterval::Segment(NewStart, F, ValNum));
460 Intervals[i]->addSegment(LiveInterval::Segment(S, NewFin, ValNum));
466 bool StackColoring::removeAllMarkers() {
468 for (
unsigned i = 0; i < Markers.size(); ++i) {
469 Markers[i]->eraseFromParent();
474 DEBUG(
dbgs()<<
"Removed "<<Count<<
" markers.\n");
479 unsigned FixedInstr = 0;
480 unsigned FixedMemOp = 0;
481 unsigned FixedDbg = 0;
487 VE = VMap.
end(); VI != VE; ++VI) {
488 const MDNode *Var = VI->first;
490 std::pair<unsigned, DebugLoc> &VP = VI->second;
491 if (SlotRemap.
count(VP.first)) {
493 VP.first = SlotRemap[VP.first];
501 e = SlotRemap.
end(); it != e; ++it) {
502 const AllocaInst *From = MFI->getObjectAllocation(it->first);
503 const AllocaInst *To = MFI->getObjectAllocation(it->second);
504 assert(To && From &&
"Invalid allocation object");
511 for (BB = MF->begin(), BBE = MF->end(); BB != BBE; ++BB)
512 for (I = BB->begin(), IE = BB->end(); I !=
IE; ++
I) {
521 E = I->memoperands_end(); MM != E; ++MM) {
537 if (!V || !isa<AllocaInst>(V)) {
544 if (!Allocas.
count(AI))
552 for (
unsigned i = 0 ; i < I->getNumOperands(); ++i) {
564 if (!SlotRemap.
count(FromSlot))
575 bool TouchesMemory = I->mayLoad() || I->mayStore();
579 SlotIndex Index = Indexes->getInstructionIndex(I);
581 assert(Interval->
find(Index) != Interval->
end() &&
582 "Found instruction usage outside of live range.");
587 int ToSlot = SlotRemap[FromSlot];
593 DEBUG(
dbgs()<<
"Fixed "<<FixedMemOp<<
" machine memory operands.\n");
594 DEBUG(
dbgs()<<
"Fixed "<<FixedDbg<<
" debug locations.\n");
595 DEBUG(
dbgs()<<
"Fixed "<<FixedInstr<<
" machine instructions.\n");
598 void StackColoring::removeInvalidSlotRanges() {
601 for (BB = MF->begin(), BBE = MF->end(); BB != BBE; ++BB)
602 for (I = BB->begin(), IE = BB->end(); I !=
IE; ++
I) {
614 if (!I->mayLoad() && !I->mayStore())
618 for (
unsigned i = 0 ; i < I->getNumOperands(); ++i) {
629 if (Intervals[Slot]->empty())
635 SlotIndex Index = Indexes->getInstructionIndex(I);
636 if (Interval->
find(Index) == Interval->
end()) {
637 Intervals[Slot]->clear();
638 DEBUG(
dbgs()<<
"Invalidating range #"<<Slot<<
"\n");
648 for (
unsigned i=0; i < NumSlots; ++i) {
650 if (SlotRemap.
count(i)) {
651 int Target = SlotRemap[i];
653 while (SlotRemap.
count(Target)) {
654 Target = SlotRemap[Target];
655 SlotRemap[i] = Target;
662 DEBUG(
dbgs() <<
"********** Stack Coloring **********\n"
663 <<
"********** Function: "
666 MFI = MF->getFrameInfo();
667 Indexes = &getAnalysis<SlotIndexes>();
668 BlockLiveness.clear();
670 BasicBlockNumbering.clear();
673 VNInfoAllocator.Reset();
675 unsigned NumSlots = MFI->getObjectIndexEnd();
684 Intervals.reserve(NumSlots);
686 unsigned NumMarkers = collectMarkers(NumSlots);
688 unsigned TotalSize = 0;
689 DEBUG(
dbgs()<<
"Found "<<NumMarkers<<
" markers and "<<NumSlots<<
" slots\n");
692 for (
int i=0; i < MFI->getObjectIndexEnd(); ++i) {
693 DEBUG(
dbgs()<<
"Slot #"<<i<<
" - "<<MFI->getObjectSize(i)<<
" bytes.\n");
694 TotalSize += MFI->getObjectSize(i);
697 DEBUG(
dbgs()<<
"Total Stack size: "<<TotalSize<<
" bytes\n\n");
702 DEBUG(
dbgs()<<
"Will not try to merge slots.\n");
703 return removeAllMarkers();
706 for (
unsigned i=0; i < NumSlots; ++i) {
708 Intervals.push_back(LI);
709 LI->
getNextValue(Indexes->getZeroIndex(), VNInfoAllocator);
714 calculateLocalLiveness();
717 calculateLiveIntervals(NumSlots);
722 removeInvalidSlotRanges();
726 unsigned RemovedSlots = 0;
727 unsigned ReducedSize = 0;
730 for (
unsigned I = 0; I < NumSlots; ++
I) {
731 if (Intervals[SortedSlots[I]]->empty())
743 std::stable_sort(SortedSlots.
begin(), SortedSlots.
end(),
744 SlotSizeSorter(MFI));
749 for (
unsigned I = 0; I < NumSlots; ++
I) {
750 if (SortedSlots[I] == -1)
753 for (
unsigned J=I+1; J < NumSlots; ++J) {
754 if (SortedSlots[J] == -1)
757 int FirstSlot = SortedSlots[
I];
758 int SecondSlot = SortedSlots[J];
761 assert (!First->
empty() && !Second->
empty() &&
"Found an empty range");
767 SlotRemap[SecondSlot] = FirstSlot;
769 DEBUG(
dbgs()<<
"Merging #"<<FirstSlot<<
" and slots #"<<
770 SecondSlot<<
" together.\n");
771 unsigned MaxAlignment = std::max(MFI->getObjectAlignment(FirstSlot),
772 MFI->getObjectAlignment(SecondSlot));
774 assert(MFI->getObjectSize(FirstSlot) >=
775 MFI->getObjectSize(SecondSlot) &&
776 "Merging a small object into a larger one");
779 ReducedSize += MFI->getObjectSize(SecondSlot);
780 MFI->setObjectAlignment(FirstSlot, MaxAlignment);
781 MFI->RemoveStackObject(SecondSlot);
788 StackSpaceSaved += ReducedSize;
789 StackSlotMerged += RemovedSlots;
790 DEBUG(
dbgs()<<
"Merge "<<RemovedSlots<<
" slots. Saved "<<
791 ReducedSize<<
" bytes\n");
795 expungeSlotMap(SlotRemap, NumSlots);
796 remapInstructions(SlotRemap);
799 for (
unsigned I = 0; I < NumSlots; ++
I) {
803 return removeAllMarkers();
SuperClass::iterator iterator
void push_back(const T &Elt)
static PassRegistry * getPassRegistry()
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
MDNode - a tuple of other values.
const Function * getFunction() const
stack Merge disjoint stack false
LoopInfoBase< BlockT, LoopT > * LI
StringRef getName() const
Value * GetUnderlyingObject(Value *V, const DataLayout *TD=0, unsigned MaxLookup=6)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Abstract Stack Frame Information.
ID
LLVM Calling Convention Representation.
void MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo)
static cl::opt< bool > ProtectFromEscapedAllocas("protect-from-escaped-allocas", cl::init(false), cl::Hidden, cl::desc("Do not optimize lifetime zones that ""are broken"))
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
const MachineBasicBlock * getParent() const
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
VariableDbgInfoMapTy & getVariableDbgInfo()
df_iterator< T > df_end(const T &G)
const MachineOperand & getOperand(unsigned i) const
virtual bool isConstant(const MachineFrameInfo *) const
bool overlaps(const LiveRange &other) const
bool count(const KeyT &Val) const
count - Return true if the specified key is in the map.
succ_iterator succ_begin()
pred_iterator pred_begin()
std::vector< MachineBasicBlock * >::const_iterator const_pred_iterator
iterator find(SlotIndex Pos)
void setValue(const Value *NewSV)
bool test(unsigned Idx) const
STATISTIC(NumMarkerSeen,"Number of lifetime markers found.")
void initializeStackColoringPass(PassRegistry &)
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
df_iterator< T > df_begin(const T &G)
const Value * getValue() const
VNInfo * getValNumInfo(unsigned ValNo)
bundle_iterator< const MachineInstr, const_instr_iterator > const_iterator
INITIALIZE_PASS_BEGIN(StackColoring,"stack-coloring","Merge disjoint stack slots", false, false) INITIALIZE_PASS_END(StackColoring
std::string getName(ID id, ArrayRef< Type * > Tys=None)
virtual void getAnalysisUsage(AnalysisUsage &AU) const
stack Merge disjoint stack slots
VNInfo * getNextValue(SlotIndex def, VNInfo::Allocator &VNInfoAllocator)
std::vector< MachineBasicBlock * >::const_iterator const_succ_iterator
static cl::opt< bool > DisableColoring("no-stack-coloring", cl::init(false), cl::Hidden, cl::desc("Disable stack coloring"))
LLVM Value Representation.
BasicBlockListType::iterator iterator
SlotIndex - An opaque wrapper around machine indexes.