10
10
// lifetime markers machine instructions (LIFETIME_START and LIFETIME_END),
11
11
// which represent the possible lifetime of stack slots. It attempts to
12
12
// merge disjoint stack slots and reduce the used stack space.
13
- // NOTE: This pass is not StackSlotColoring, which optimizes spill slots.
14
- //
15
- // TODO: In the future we plan to improve stack coloring in the following ways:
16
- // 1. Allow merging multiple small slots into a single larger slot at different
17
- // offsets.
18
- // 2. Merge this pass with StackSlotColoring and allow merging of allocas with
19
- // spill slots.
13
+ // NOTE: This pass is not StackSlotColoring, which optimizes only spill slots.
20
14
//
21
15
// ===----------------------------------------------------------------------===//
22
16
25
19
#include " llvm/ADT/DenseMap.h"
26
20
#include " llvm/ADT/DepthFirstIterator.h"
27
21
#include " llvm/ADT/SmallPtrSet.h"
28
- #include " llvm/ADT/SmallSet.h"
29
22
#include " llvm/ADT/SmallVector.h"
30
23
#include " llvm/ADT/Statistic.h"
31
24
#include " llvm/Analysis/ValueTracking.h"
@@ -101,9 +94,8 @@ static cl::opt<bool> UseNewStackColoring(
101
94
" new-stack-coloring" , cl::init(false ), cl::Hidden,
102
95
cl::desc(" Use a better logic to try to reduce stack usage" ));
103
96
104
- static constexpr unsigned MaxCandidatesToConsiderDefault = 5 ;
105
- static cl::opt<unsigned > MaxCandidatesToConsider (
106
- " stackcoloring-max-candidates" , cl::init(MaxCandidatesToConsiderDefault),
97
+ static cl::opt<unsigned > MaxCandidatesOpt (
98
+ " stackcoloring-max-candidates" , cl::init(0 ),
107
99
cl::Hidden,
108
100
cl::desc(
109
101
" Max number of candidates that will be evaluated, 0 means no limit" ));
@@ -658,7 +650,7 @@ LLVM_DUMP_METHOD void StackColoring::SlotInfo::dump(const StackColoring* State)
658
650
Slot = this - State->Slot2Info .data ();
659
651
dbgs () << " fi#" << Slot;
660
652
} else
661
- dbgs () << " SlotInfo" ;
653
+ dbgs () << " SlotInfo" ;
662
654
dbgs () << " :" ;
663
655
if (Offset != InvalidIdx)
664
656
dbgs () << " offset=" << Offset;
@@ -667,10 +659,8 @@ LLVM_DUMP_METHOD void StackColoring::SlotInfo::dump(const StackColoring* State)
667
659
dbgs () << " \" " << State->MFI ->getObjectAllocation (Slot)->getName () << " \" " ;
668
660
if (State->MFI ->isSpillSlotObjectIndex (Slot))
669
661
dbgs () << " spill" ;
670
- }
662
+ }
671
663
dbgs () << " size=" << Size << " align=" << Align.value () << ' \n ' ;
672
- if (IndexBasedLiveRange)
673
- dbgs () << " Index: " << *IndexBasedLiveRange << " \n " ;
674
664
dumpBV (" LIVENESS " , Liveness);
675
665
BitVector Start;
676
666
Start.resize (Liveness.size ());
@@ -975,6 +965,13 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
975
965
unsigned SpillChangeCounter = 0 ;
976
966
977
967
if (LS && LS->getNumIntervals ()) {
968
+ // Here we prepare Spill slots lifetime informations
969
+ // Live ranges in the LiveStacks seem to be slightly outdated in many small
970
+ // ways. this is not an issue for stack-slot-coloring, because its only
971
+ // operating on LiveRange form LiveStack, but it is an issue here,
972
+ // So we only rely on LiveStack, to give us live edges, and conservatively
973
+ // re-construct in-block liveness changes
974
+
978
975
for (const MachineBasicBlock &MBB : *MF) {
979
976
BlockLifetimeInfo &MBBLiveness = BlockLiveness[MBB.getNumber ()];
980
977
MBBLiveness.LiveIn .resize (NumSlots);
@@ -1017,14 +1014,6 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
1017
1014
unsigned Slot = PSV->getFrameIndex ();
1018
1015
if (!LS->hasInterval (Slot))
1019
1016
continue ;
1020
- // if (Slot == 17) {
1021
- // dbgs() << "MI: " << MI;
1022
- // dbgs() << "MBB: " << MBB.getName() << "\n";
1023
- // dbgs() << "MBB range:" << Indexes->getMBBRange(&MBB).first << "-"
1024
- // << Indexes->getMBBRange(&MBB).second << "\n";
1025
- // dbgs() << "slot range: " << LS->getInterval(Slot) << "\n";
1026
- // dbgs() << "\n";
1027
- // }
1028
1017
assert (MMO->isStore () != MMO->isLoad ());
1029
1018
if (MMO->isStore ()) {
1030
1019
if (!IsStoredTo[Slot]) {
@@ -1050,6 +1039,8 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
1050
1039
/* IsStart=*/ false , Slot});
1051
1040
}
1052
1041
1042
+ // Ensure that the changes are in the same order they will be found and
1043
+ // need to be processed in
1053
1044
std::stable_sort (MidBlockSpillChanges.begin () + SizeOnStart,
1054
1045
MidBlockSpillChanges.end (),
1055
1046
[&](SplitSlotChanges Lhs, SplitSlotChanges Rhs) -> bool {
@@ -1083,6 +1074,8 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
1083
1074
1084
1075
bool StartedSinceInc = false ;
1085
1076
auto EndRangeFor = [&](int Slot) {
1077
+ // The less index the better, so we only increase if the ranges would not
1078
+ // be accurate without
1086
1079
if (StartIdx[Slot] == CurrIdx || StartedSinceInc) {
1087
1080
CurrIdx++;
1088
1081
StartedSinceInc = false ;
@@ -1103,9 +1096,6 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
1103
1096
continue ;
1104
1097
SlotIndex ThisIndex = Indexes->getInstructionIndex (MI);
1105
1098
auto OnChange = [&](unsigned Slot, bool IsStart) {
1106
- // if (Slot == 3) {
1107
- // outs() << "HERE\n";
1108
- // }
1109
1099
if (IsStart) {
1110
1100
StartedSinceInc = true ;
1111
1101
// If a slot is already definitely in use, we don't have to emit
@@ -1211,7 +1201,6 @@ void StackColoring::remapInstructions(DenseMap<int, int>& SlotRemap, int MergedS
1211
1201
continue ;
1212
1202
int Slot = VI.getStackSlot ();
1213
1203
if (Slot >= 0 && Slot2Info[Slot].Offset != InvalidIdx) {
1214
- // FIXME: properly update the offset into MergedSlot debug
1215
1204
VI.updateStackSlot (MergedSlot);
1216
1205
}
1217
1206
if (auto It = SlotRemap.find (Slot); It != SlotRemap.end ()) {
@@ -1587,7 +1576,7 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
1587
1576
SlotInfo* LastQueryLhs = nullptr ;
1588
1577
SlotInfo* LastQueryRhs = nullptr ;
1589
1578
bool LastQueryRes = false ;
1590
- // TODO: Real caching ?
1579
+ // Maybe there should be real caching here
1591
1580
auto HasOverlapCached = [&](SlotInfo &Lhs, SlotInfo &Rhs) {
1592
1581
if (&Lhs == LastQueryLhs && LastQueryRhs == &Rhs)
1593
1582
return LastQueryRes;
@@ -1618,8 +1607,10 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
1618
1607
1619
1608
// The slots in the linked-list are always kept in ascending order, so the
1620
1609
// earliest slot has the lowest offset
1621
- // This loop handles cases where the latest slot doesn't cannot be both live
1622
- // because of the CFG, so even if there lifetime overlap, they can overlap
1610
+ // This loop handles cases where this slot and the latest slot doesn't
1611
+ // cannot be both live because of the CFG, so even if there lifetime
1612
+ // overlap, they can overlap
1613
+ // See comment about implementation higher in the file
1623
1614
while (LLVM_UNLIKELY (Last->Slot != InvalidIdx &&
1624
1615
!HasOverlapCached (Info, Slot2Info[Last->Slot ])))
1625
1616
Last = &OlderStatus[Last->Prev ];
@@ -1640,7 +1631,7 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
1640
1631
return ;
1641
1632
}
1642
1633
1643
- // Insure ordering of slots
1634
+ // Ensure ordering of slots
1644
1635
Status* Inserted = &OlderStatus.back ();
1645
1636
Inserted->Offset = Offset;
1646
1637
Inserted->Slot = &Info - Slot2Info.data ();
@@ -1653,9 +1644,10 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
1653
1644
Curr->Prev = Idx;
1654
1645
};
1655
1646
1656
- SmallVector<unsigned , MaxCandidatesToConsiderDefault> Candidates;
1657
- unsigned MaxCandidates =
1658
- MaxCandidatesToConsider == 0 ? ~0u : MaxCandidatesToConsider;
1647
+ // This is a vector but element ordering is not relevant
1648
+ SmallVector<unsigned > Candidates;
1649
+
1650
+ unsigned MaxCandidates = MaxCandidatesOpt == 0 ? ~0u : MaxCandidatesOpt;
1659
1651
for (unsigned I = 0 ; I < MaxCandidates; I++) {
1660
1652
if (SlotStack.empty ())
1661
1653
break ;
@@ -1668,7 +1660,7 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
1668
1660
unsigned BestIdx = InvalidIdx;
1669
1661
unsigned BestOffset = InvalidIdx;
1670
1662
1671
- LLVM_DEBUG (dbgs () << " top= " << WorseCaseOffset << " choosing: " );
1663
+ LLVM_DEBUG (dbgs () << " Worse is at " << WorseCaseOffset << " , choosing: " );
1672
1664
for (unsigned K = 0 ; K < Candidates.size (); K++) {
1673
1665
SlotInfo &Info = Slot2Info[Candidates[K]];
1674
1666
unsigned Offset = 0 ;
@@ -1707,7 +1699,8 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
1707
1699
if (Other.SlotPriority != Info.SlotPriority )
1708
1700
return Other.SlotPriority < Info.SlotPriority ;
1709
1701
1710
- // Both are always stored in Slot2Info, so this is deterministic
1702
+ // Both are always stored in Slot2Info, so this is equivalent to
1703
+ // FrameIndex comparaison
1711
1704
return &Other < &Info;
1712
1705
}();
1713
1706
@@ -1785,10 +1778,10 @@ bool StackColoring::run(MachineFunction &Func) {
1785
1778
VNInfoAllocator.Reset ();
1786
1779
Slot2Info.clear ();
1787
1780
1788
- unsigned NumSlots = MFI->getObjectIndexEnd ();
1781
+ if (!UseNewStackColoring)
1782
+ LS = nullptr ;
1789
1783
1790
- // if (MF->getName() == "_ZL9transformPjS_Rm")
1791
- // outs() << "HERE\n";
1784
+ unsigned NumSlots = MFI->getObjectIndexEnd ();
1792
1785
1793
1786
// If there are no stack slots then there are no markers to remove.
1794
1787
if (NumSlots < 2 || DisableColoring)
@@ -1900,22 +1893,10 @@ bool StackColoring::run(MachineFunction &Func) {
1900
1893
auto &SecondS = LiveStarts[SecondSlot];
1901
1894
assert (!First->empty () && !Second->empty () && " Found an empty range" );
1902
1895
1903
- bool OldNoOverlap = !First->isLiveAtIndexes (SecondS) &&
1904
- !Second->isLiveAtIndexes (FirstS);
1905
-
1906
- SlotInfo &FSlot = Slot2Info[FirstSlot];
1907
- SlotInfo &SSlot = Slot2Info[SecondSlot];
1908
- bool NewNoOverlap = !FSlot.hasOverlap (SSlot);
1909
-
1910
- // if (NewNoOverlap != OldNoOverlap) {
1911
- // LLVM_DEBUG(dbgs() << "OldNoOverlap=" << OldNoOverlap
1912
- // << " NewNoOverlap=" << NewNoOverlap << "\n");
1913
- // }
1914
- // assert(OldNoOverlap == NewNoOverlap);
1915
-
1916
1896
// Merge disjoint slots. This is a little bit tricky - see the
1917
1897
// Implementation Notes section for an explanation.
1918
- if (OldNoOverlap) {
1898
+ if (!First->isLiveAtIndexes (SecondS) &&
1899
+ !Second->isLiveAtIndexes (FirstS)) {
1919
1900
Changed = true ;
1920
1901
First->MergeSegmentsInAsValue (*Second, First->getValNumInfo (0 ));
1921
1902
@@ -1924,8 +1905,6 @@ bool StackColoring::run(MachineFunction &Func) {
1924
1905
auto Mid = FirstS.begin () + OldSize;
1925
1906
std::inplace_merge (FirstS.begin (), Mid, FirstS.end ());
1926
1907
1927
- // FSlot.Liveness |= SSlot.Liveness;
1928
-
1929
1908
SlotRemap[SecondSlot] = FirstSlot;
1930
1909
SortedSlots[J] = -1 ;
1931
1910
LLVM_DEBUG (dbgs () << " Merging #" << FirstSlot << " and slots #"
0 commit comments