Skip to content

Commit 09de6f3

Browse files
committed
Start rebuild lifetimes for spill slots
1 parent fb19fd0 commit 09de6f3

File tree

2 files changed

+150
-8
lines changed

2 files changed

+150
-8
lines changed

llvm/lib/CodeGen/StackColoring.cpp

Lines changed: 147 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
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

486489
public:
487-
StackColoring(SlotIndexes *Indexes) : Indexes(Indexes) {}
490+
StackColoring(SlotIndexes *Indexes, LiveStacks* LS) : LS(LS), Indexes(Indexes) {}
488491
bool run(MachineFunction &Func);
489492

490493
private:
@@ -573,6 +576,7 @@ INITIALIZE_PASS_END(StackColoringLegacy, DEBUG_TYPE,
573576

574577
void 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

13871523
PreservedAnalyses 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();

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,13 +1498,13 @@ void TargetPassConfig::addOptimizedRegAlloc() {
14981498
addPass(&MachineSchedulerID);
14991499

15001500
if (addRegAssignAndRewriteOptimized()) {
1501-
// Perform stack slot coloring and post-ra machine LICM.
1502-
addPass(&StackSlotColoringID);
1503-
15041501
if (MergedStackColoring) {
15051502
// This pass merges large allocas. StackSlotColoring is a different pass
15061503
// which merges spill slots.
15071504
addPass(&StackColoringLegacyID);
1505+
} else {
1506+
// Perform stack slot coloring and post-ra machine LICM.
1507+
addPass(&StackSlotColoringID);
15081508
}
15091509

15101510
// Allow targets to expand pseudo instructions depending on the choice of

0 commit comments

Comments
 (0)