3030#include " llvm/ADT/Statistic.h"
3131#include " llvm/Analysis/ValueTracking.h"
3232#include " llvm/CodeGen/LiveInterval.h"
33+ #include " llvm/CodeGen/LiveStacks.h"
3334#include " llvm/CodeGen/MachineBasicBlock.h"
3435#include " llvm/CodeGen/MachineFrameInfo.h"
3536#include " llvm/CodeGen/MachineFunction.h"
@@ -399,6 +400,8 @@ class StackColoring {
399400 MachineFrameInfo *MFI = nullptr ;
400401 MachineFunction *MF = nullptr ;
401402
403+ LiveStacks* LS = nullptr ;
404+
402405 struct SlotInfo {
403406 // All places in the current function where this Slot is live
404407 BitVector Liveness;
@@ -484,7 +487,7 @@ class StackColoring {
484487 unsigned NumIterations;
485488
486489public:
487- StackColoring (SlotIndexes *Indexes) : Indexes(Indexes) {}
490+ StackColoring (SlotIndexes *Indexes, LiveStacks* LS ) : LS(LS), Indexes(Indexes) {}
488491 bool run (MachineFunction &Func);
489492
490493private:
@@ -573,6 +576,7 @@ INITIALIZE_PASS_END(StackColoringLegacy, DEBUG_TYPE,
573576
574577void StackColoringLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
575578 AU.addRequired <SlotIndexesWrapperPass>();
579+ AU.addUsedIfAvailable <LiveStacksWrapperLegacy>();
576580 MachineFunctionPass::getAnalysisUsage (AU);
577581}
578582
@@ -744,6 +748,9 @@ unsigned StackColoring::collectMarkers(unsigned NumSlot) {
744748 ConservativeSlots.clear ();
745749 ConservativeSlots.resize (NumSlot);
746750
751+ if (LS)
752+ MarkersFound += LS->getNumIntervals () * 2 ;
753+
747754 // number of start and end lifetime ops for each slot
748755 SmallVector<int , 8 > NumStartLifetimes (NumSlot, 0 );
749756 SmallVector<int , 8 > NumEndLifetimes (NumSlot, 0 );
@@ -955,6 +962,113 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
955962 int CurrIdx = 0 ;
956963
957964 DefinitelyInUse.resize (NumSlots);
965+ struct SplitSlotChanges {
966+ const MachineInstr* AtMI;
967+ unsigned BlockIdx : 31 ;
968+ unsigned IsStart : 1 ;
969+ unsigned Slot;
970+ };
971+ SmallVector<SplitSlotChanges> MidBlockSpillChanges;
972+ unsigned SpillChangeCounter = 0 ;
973+
974+ if (LS && LS->getNumIntervals ()) {
975+ for (const MachineBasicBlock &MBB : *MF) {
976+ BlockLifetimeInfo &MBBLiveness = BlockLiveness[MBB.getNumber ()];
977+ MBBLiveness.LiveIn .resize (NumSlots);
978+ MBBLiveness.LiveOut .resize (NumSlots);
979+ }
980+ for (const MachineBasicBlock &MBB : *MF) {
981+ unsigned Base = LS->getStartIdx ();
982+ BlockLifetimeInfo &MBBLiveness = BlockLiveness[MBB.getNumber ()];
983+ for (unsigned I = 0 ; I < LS->getNumIntervals (); I++) {
984+ unsigned Slot = Base + I;
985+ if (LS->getInterval (Slot).liveAt (Indexes->getMBBStartIdx (&MBB))) {
986+ MBBLiveness.LiveIn [Slot] = true ;
987+ // Checking if the end of the block is in the live-range is not
988+ // reliable
989+ for (MachineBasicBlock *Pred : MBB.predecessors ())
990+ BlockLiveness[Pred->getNumber ()].LiveOut [Slot] = true ;
991+ }
992+ }
993+ }
994+ for (const MachineBasicBlock &MBB : *MF) {
995+ unsigned SizeOnStart = MidBlockSpillChanges.size ();
996+ BlockLifetimeInfo &MBBLiveness = BlockLiveness[MBB.getNumber ()];
997+ BitVector IsStoredTo;
998+ IsStoredTo.resize (NumSlots, false );
999+ struct MIBlockIdx {
1000+ const MachineInstr* MI;
1001+ unsigned BlockIdx;
1002+ };
1003+ unsigned BlockIdx = 0 ;
1004+ SmallVector<MIBlockIdx> LastUse;
1005+ LastUse.resize (NumSlots, {nullptr , 0 });
1006+ for (const MachineInstr &MI : MBB) {
1007+ if (MI.isDebugInstr ())
1008+ continue ;
1009+ for (MachineMemOperand* MMO : MI.memoperands ()) {
1010+ auto *PSV = dyn_cast_if_present<FixedStackPseudoSourceValue>(
1011+ MMO->getPseudoValue ());
1012+ if (!PSV)
1013+ continue ;
1014+ unsigned Slot = PSV->getFrameIndex ();
1015+ if (!LS->hasInterval (Slot))
1016+ continue ;
1017+ // if (Slot == 17) {
1018+ // dbgs() << "MI: " << MI;
1019+ // dbgs() << "MBB: " << MBB.getName() << "\n";
1020+ // dbgs() << "MBB range:" << Indexes->getMBBRange(&MBB).first << "-"
1021+ // << Indexes->getMBBRange(&MBB).second << "\n";
1022+ // dbgs() << "slot range: " << LS->getInterval(Slot) << "\n";
1023+ // dbgs() << "\n";
1024+ // }
1025+ assert (MMO->isStore () != MMO->isLoad ());
1026+ if (MMO->isStore ()) {
1027+ if (!IsStoredTo[Slot]) {
1028+ MidBlockSpillChanges.push_back (
1029+ {&MI, BlockIdx, /* IsStart=*/ true , Slot});
1030+ IsStoredTo[Slot] = true ;
1031+ }
1032+ } else
1033+ LastUse[Slot] = {&MI, BlockIdx};
1034+ }
1035+ BlockIdx++;
1036+ }
1037+
1038+ BitVector Liveness = MBBLiveness.LiveIn ;
1039+ Liveness |= IsStoredTo;
1040+ Liveness &= MBBLiveness.LiveOut .flip ();
1041+ for (unsigned Slot : Liveness.set_bits ()) {
1042+ if (!LS->hasInterval (Slot))
1043+ continue ;
1044+ if (LastUse[Slot].MI )
1045+ MidBlockSpillChanges.push_back ({LastUse[Slot].MI ,
1046+ LastUse[Slot].BlockIdx ,
1047+ /* IsStart=*/ false , Slot});
1048+ }
1049+
1050+ std::stable_sort (MidBlockSpillChanges.begin () + SizeOnStart,
1051+ MidBlockSpillChanges.end (),
1052+ [&](SplitSlotChanges Lhs, SplitSlotChanges Rhs) -> bool {
1053+ if (Lhs.BlockIdx == Rhs.BlockIdx )
1054+ assert (Lhs.Slot != Rhs.Slot );
1055+ if (Lhs.BlockIdx != Rhs.BlockIdx )
1056+ return Lhs.BlockIdx < Rhs.BlockIdx ;
1057+ // Avoid overlap of lifetime when the same instruction
1058+ // starts some spill lifetime and ends others.
1059+ return Rhs.IsStart ;
1060+ });
1061+ }
1062+ }
1063+ LLVM_DEBUG ({
1064+ for (SplitSlotChanges C : MidBlockSpillChanges) {
1065+ dbgs () << " Idx=" << C.BlockIdx << " Slot=" << C.Slot
1066+ << " IsStart=" << C.IsStart << " MI=" << *C.AtMI ;
1067+ }
1068+ });
1069+
1070+ // To avoid needing bounds checks
1071+ MidBlockSpillChanges.push_back ({nullptr , 0 , false , InvalidIdx});
9581072
9591073 // For each block, find which slots are active within this block
9601074 // and update the live intervals.
@@ -986,10 +1100,15 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
9861100 for (const MachineInstr &MI : MBB) {
9871101 SmallVector<int , 4 > slots;
9881102 bool IsStart = false ;
989- if (!isLifetimeStartOrEnd (MI, slots, IsStart))
1103+ bool AnyChange = isLifetimeStartOrEnd (MI, slots, IsStart);
1104+ AnyChange |= MidBlockSpillChanges[SpillChangeCounter].AtMI == &MI;
1105+ if (!AnyChange)
9901106 continue ;
9911107 SlotIndex ThisIndex = Indexes->getInstructionIndex (MI);
992- for (auto Slot : slots) {
1108+ auto OnChange = [&](unsigned Slot, bool IsStart) {
1109+ // if (Slot == 3) {
1110+ // outs() << "HERE\n";
1111+ // }
9931112 if (IsStart) {
9941113 StartedSinceInc = true ;
9951114 // If a slot is already definitely in use, we don't have to emit
@@ -1016,6 +1135,14 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
10161135 if (StartIdx[Slot] != -1 )
10171136 EndRangeFor (Slot);
10181137 }
1138+ };
1139+ for (auto Slot : slots)
1140+ OnChange (Slot, IsStart);
1141+ for (; SpillChangeCounter < MidBlockSpillChanges.size () &&
1142+ MidBlockSpillChanges[SpillChangeCounter].AtMI == &MI;
1143+ SpillChangeCounter++) {
1144+ SplitSlotChanges Change = MidBlockSpillChanges[SpillChangeCounter];
1145+ OnChange (Change.Slot , Change.IsStart );
10191146 }
10201147 }
10211148
@@ -1035,6 +1162,9 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
10351162 Intervals[i]->addSegment (LiveInterval::Segment (Starts[i], EndIdx, VNI));
10361163 }
10371164 }
1165+ // Make sure we reached the end
1166+ assert (!MidBlockSpillChanges[SpillChangeCounter].AtMI );
1167+
10381168 LivenessSize = CurrIdx;
10391169 for (SlotInfo &Info : Slot2Info) {
10401170 Info.Liveness .resize (CurrIdx);
@@ -1043,6 +1173,7 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
10431173 // SlotInfo::hasOverlap, which should have better cache locality
10441174 std::sort (Info.StartLiveness .begin (), Info.StartLiveness .end ());
10451175#ifndef NDEBUG
1176+ assert (Info.Liveness .any () == !Info.StartLiveness .empty ());
10461177 for (int Start : Info.StartLiveness )
10471178 assert (Info.Liveness [Start]);
10481179#endif
@@ -1380,13 +1511,19 @@ bool StackColoringLegacy::runOnMachineFunction(MachineFunction &MF) {
13801511 if (skipFunction (MF.getFunction ()))
13811512 return false ;
13821513
1383- StackColoring SC (&getAnalysis<SlotIndexesWrapperPass>().getSI ());
1514+ LiveStacks* LS = nullptr ;
1515+ LiveStacksWrapperLegacy* LSWL = getAnalysisIfAvailable<LiveStacksWrapperLegacy>();
1516+ if (LSWL)
1517+ LS = &LSWL->getLS ();
1518+
1519+ StackColoring SC (&getAnalysis<SlotIndexesWrapperPass>().getSI (), LS);
13841520 return SC.run (MF);
13851521}
13861522
13871523PreservedAnalyses StackColoringPass::run (MachineFunction &MF,
13881524 MachineFunctionAnalysisManager &MFAM) {
1389- StackColoring SC (&MFAM.getResult <SlotIndexesAnalysis>(MF));
1525+ StackColoring SC (&MFAM.getResult <SlotIndexesAnalysis>(MF),
1526+ MFAM.getCachedResult <LiveStacksAnalysis>(MF));
13901527 if (SC.run (MF))
13911528 return PreservedAnalyses::none ();
13921529 return PreservedAnalyses::all ();
@@ -1400,6 +1537,8 @@ unsigned StackColoring::doMerging(unsigned NumSlots) {
14001537 int64_t OrigPesSize = 0 ;
14011538 for (unsigned Slot = 0 ; Slot < NumSlots; Slot++) {
14021539 SlotInfo& Info = Slot2Info[Slot];
1540+ if (Info.StartLiveness .empty ())
1541+ assert (!LS || !LS->hasInterval (Slot));
14031542 if (!Info.StartLiveness .empty () &&
14041543 DebugCounter::shouldExecute (ProcessSlot)) {
14051544 FinalAlign = std::max (FinalAlign, Info.Align );
@@ -1596,6 +1735,9 @@ bool StackColoring::run(MachineFunction &Func) {
15961735
15971736 unsigned NumSlots = MFI->getObjectIndexEnd ();
15981737
1738+ // if (MF->getName() == "_ZL9transformPjS_Rm")
1739+ // outs() << "HERE\n";
1740+
15991741 // If there are no stack slots then there are no markers to remove.
16001742 if (NumSlots < 2 || DisableColoring)
16011743 return removeAllMarkers ();
0 commit comments