summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/RegisterCoalescer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/RegisterCoalescer.cpp')
-rw-r--r--llvm/lib/CodeGen/RegisterCoalescer.cpp283
1 files changed, 228 insertions, 55 deletions
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 7fdc85a6e444..751f79e66b73 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -133,6 +133,20 @@ namespace {
AliasAnalysis *AA = nullptr;
RegisterClassInfo RegClassInfo;
+ /// Position and VReg of a PHI instruction during coalescing.
+ struct PHIValPos {
+ SlotIndex SI; ///< Slot where this PHI occurs.
+ Register Reg; ///< VReg the PHI occurs in.
+ unsigned SubReg; ///< Qualifying subregister for Reg.
+ };
+
+ /// Map from debug instruction number to PHI position during coalescing.
+ DenseMap<unsigned, PHIValPos> PHIValToPos;
+ /// Index of, for each VReg, which debug instruction numbers and
+ /// corresponding PHIs are sensitive to coalescing. Each VReg may have
+ /// multiple PHI defs, at different positions.
+ DenseMap<Register, SmallVector<unsigned, 2>> RegToPHIIdx;
+
/// Debug variable location tracking -- for each VReg, maintain an
/// ordered-by-slot-index set of DBG_VALUEs, to help quick
/// identification of whether coalescing may change location validity.
@@ -187,6 +201,11 @@ namespace {
/// Recursively eliminate dead defs in DeadDefs.
void eliminateDeadDefs();
+ /// allUsesAvailableAt - Return true if all registers used by OrigMI at
+ /// OrigIdx are also available with the same value at UseIdx.
+ bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx,
+ SlotIndex UseIdx);
+
/// LiveRangeEdit callback for eliminateDeadDefs().
void LRE_WillEraseInstruction(MachineInstr *MI) override;
@@ -590,6 +609,14 @@ void RegisterCoalescer::eliminateDeadDefs() {
nullptr, this).eliminateDeadDefs(DeadDefs);
}
+bool RegisterCoalescer::allUsesAvailableAt(const MachineInstr *OrigMI,
+ SlotIndex OrigIdx,
+ SlotIndex UseIdx) {
+ SmallVector<Register, 8> NewRegs;
+ return LiveRangeEdit(nullptr, NewRegs, *MF, *LIS, nullptr, this)
+ .allUsesAvailableAt(OrigMI, OrigIdx, UseIdx);
+}
+
void RegisterCoalescer::LRE_WillEraseInstruction(MachineInstr *MI) {
// MI may be in WorkList. Make sure we don't visit it.
ErasedInstrs.insert(MI);
@@ -914,7 +941,7 @@ RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
if (UseMO.isUndef())
continue;
MachineInstr *UseMI = UseMO.getParent();
- if (UseMI->isDebugValue()) {
+ if (UseMI->isDebugInstr()) {
// FIXME These don't have an instruction index. Not clear we have enough
// info to decide whether to do this replacement or not. For now do it.
UseMO.setReg(NewReg);
@@ -1329,6 +1356,9 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
}
}
+ if (!allUsesAvailableAt(DefMI, ValNo->def, CopyIdx))
+ return false;
+
DebugLoc DL = CopyMI->getDebugLoc();
MachineBasicBlock *MBB = CopyMI->getParent();
MachineBasicBlock::iterator MII =
@@ -1543,9 +1573,11 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
// If the virtual SrcReg is completely eliminated, update all DBG_VALUEs
// to describe DstReg instead.
if (MRI->use_nodbg_empty(SrcReg)) {
- for (MachineOperand &UseMO : MRI->use_operands(SrcReg)) {
+ for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SrcReg);
+ UI != MRI->use_end();) {
+ MachineOperand &UseMO = *UI++;
MachineInstr *UseMI = UseMO.getParent();
- if (UseMI->isDebugValue()) {
+ if (UseMI->isDebugInstr()) {
if (Register::isPhysicalRegister(DstReg))
UseMO.substPhysReg(DstReg, *TRI);
else
@@ -1726,7 +1758,7 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
if (SubReg == 0 || MO.isUndef())
continue;
MachineInstr &MI = *MO.getParent();
- if (MI.isDebugValue())
+ if (MI.isDebugInstr())
continue;
SlotIndex UseIdx = LIS->getInstructionIndex(MI).getRegSlot(true);
addUndefFlag(*DstInt, UseIdx, MO, SubReg);
@@ -1753,7 +1785,7 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
// If SrcReg wasn't read, it may still be the case that DstReg is live-in
// because SrcReg is a sub-register.
- if (DstInt && !Reads && SubIdx && !UseMI->isDebugValue())
+ if (DstInt && !Reads && SubIdx && !UseMI->isDebugInstr())
Reads = DstInt->liveAt(LIS->getInstructionIndex(*UseMI));
// Replace SrcReg with DstReg in all UseMI operands.
@@ -1768,24 +1800,27 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
// A subreg use of a partially undef (super) register may be a complete
// undef use now and then has to be marked that way.
- if (SubIdx != 0 && MO.isUse() && MRI->shouldTrackSubRegLiveness(DstReg)) {
- if (!DstInt->hasSubRanges()) {
- BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
- LaneBitmask FullMask = MRI->getMaxLaneMaskForVReg(DstInt->reg());
- LaneBitmask UsedLanes = TRI->getSubRegIndexLaneMask(SubIdx);
- LaneBitmask UnusedLanes = FullMask & ~UsedLanes;
- DstInt->createSubRangeFrom(Allocator, UsedLanes, *DstInt);
- // The unused lanes are just empty live-ranges at this point.
- // It is the caller responsibility to set the proper
- // dead segments if there is an actual dead def of the
- // unused lanes. This may happen with rematerialization.
- DstInt->createSubRange(Allocator, UnusedLanes);
+ if (MO.isUse() && !DstIsPhys) {
+ unsigned SubUseIdx = TRI->composeSubRegIndices(SubIdx, MO.getSubReg());
+ if (SubUseIdx != 0 && MRI->shouldTrackSubRegLiveness(DstReg)) {
+ if (!DstInt->hasSubRanges()) {
+ BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
+ LaneBitmask FullMask = MRI->getMaxLaneMaskForVReg(DstInt->reg());
+ LaneBitmask UsedLanes = TRI->getSubRegIndexLaneMask(SubIdx);
+ LaneBitmask UnusedLanes = FullMask & ~UsedLanes;
+ DstInt->createSubRangeFrom(Allocator, UsedLanes, *DstInt);
+ // The unused lanes are just empty live-ranges at this point.
+ // It is the caller responsibility to set the proper
+ // dead segments if there is an actual dead def of the
+ // unused lanes. This may happen with rematerialization.
+ DstInt->createSubRange(Allocator, UnusedLanes);
+ }
+ SlotIndex MIIdx = UseMI->isDebugInstr()
+ ? LIS->getSlotIndexes()->getIndexBefore(*UseMI)
+ : LIS->getInstructionIndex(*UseMI);
+ SlotIndex UseIdx = MIIdx.getRegSlot(true);
+ addUndefFlag(*DstInt, UseIdx, MO, SubUseIdx);
}
- SlotIndex MIIdx = UseMI->isDebugValue()
- ? LIS->getSlotIndexes()->getIndexBefore(*UseMI)
- : LIS->getInstructionIndex(*UseMI);
- SlotIndex UseIdx = MIIdx.getRegSlot(true);
- addUndefFlag(*DstInt, UseIdx, MO, SubIdx);
}
if (DstIsPhys)
@@ -1796,7 +1831,7 @@ void RegisterCoalescer::updateRegDefsUses(Register SrcReg, Register DstReg,
LLVM_DEBUG({
dbgs() << "\t\tupdated: ";
- if (!UseMI->isDebugValue())
+ if (!UseMI->isDebugInstr())
dbgs() << LIS->getInstructionIndex(*UseMI) << "\t";
dbgs() << *UseMI;
});
@@ -2837,9 +2872,39 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) {
if ((TRI->getSubRegIndexLaneMask(Other.SubIdx) & ~V.WriteLanes).none())
return CR_Impossible;
- // We need to verify that no instructions are reading the clobbered lanes. To
- // save compile time, we'll only check that locally. Don't allow the tainted
- // value to escape the basic block.
+ if (TrackSubRegLiveness) {
+ auto &OtherLI = LIS->getInterval(Other.Reg);
+ // If OtherVNI does not have subranges, it means all the lanes of OtherVNI
+ // share the same live range, so we just need to check whether they have
+ // any conflict bit in their LaneMask.
+ if (!OtherLI.hasSubRanges()) {
+ LaneBitmask OtherMask = TRI->getSubRegIndexLaneMask(Other.SubIdx);
+ return (OtherMask & V.WriteLanes).none() ? CR_Replace : CR_Impossible;
+ }
+
+ // If we are clobbering some active lanes of OtherVNI at VNI->def, it is
+ // impossible to resolve the conflict. Otherwise, we can just replace
+ // OtherVNI because of no real conflict.
+ for (LiveInterval::SubRange &OtherSR : OtherLI.subranges()) {
+ LaneBitmask OtherMask =
+ TRI->composeSubRegIndexLaneMask(Other.SubIdx, OtherSR.LaneMask);
+ if ((OtherMask & V.WriteLanes).none())
+ continue;
+
+ auto OtherSRQ = OtherSR.Query(VNI->def);
+ if (OtherSRQ.valueIn() && OtherSRQ.endPoint() > VNI->def) {
+ // VNI is clobbering some lanes of OtherVNI, they have real conflict.
+ return CR_Impossible;
+ }
+ }
+
+ // VNI is NOT clobbering any lane of OtherVNI, just replace OtherVNI.
+ return CR_Replace;
+ }
+
+ // We need to verify that no instructions are reading the clobbered lanes.
+ // To save compile time, we'll only check that locally. Don't allow the
+ // tainted value to escape the basic block.
MachineBasicBlock *MBB = Indexes->getMBBFromIndex(VNI->def);
if (OtherLRQ.endPoint() >= Indexes->getMBBEndIdx(MBB))
return CR_Impossible;
@@ -2959,7 +3024,7 @@ taintExtent(unsigned ValNo, LaneBitmask TaintedLanes, JoinVals &Other,
bool JoinVals::usesLanes(const MachineInstr &MI, Register Reg, unsigned SubIdx,
LaneBitmask Lanes) const {
- if (MI.isDebugInstr())
+ if (MI.isDebugOrPseudoInstr())
return false;
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg() || MO.isDef() || MO.getReg() != Reg)
@@ -3006,8 +3071,10 @@ bool JoinVals::resolveConflicts(JoinVals &Other) {
MachineBasicBlock::iterator MI = MBB->begin();
if (!VNI->isPHIDef()) {
MI = Indexes->getInstructionFromIndex(VNI->def);
- // No need to check the instruction defining VNI for reads.
- ++MI;
+ if (!VNI->def.isEarlyClobber()) {
+ // No need to check the instruction defining VNI for reads.
+ ++MI;
+ }
}
assert(!SlotIndex::isSameInstr(VNI->def, TaintExtent.front().first) &&
"Interference ends on VNI->def. Should have been handled earlier");
@@ -3114,6 +3181,13 @@ void JoinVals::pruneValues(JoinVals &Other,
}
}
+// Check if the segment consists of a copied live-through value (i.e. the copy
+// in the block only extended the liveness, of an undef value which we may need
+// to handle).
+static bool isLiveThrough(const LiveQueryResult Q) {
+ return Q.valueIn() && Q.valueIn()->isPHIDef() && Q.valueIn() == Q.valueOut();
+}
+
/// Consider the following situation when coalescing the copy between
/// %31 and %45 at 800. (The vertical lines represent live range segments.)
///
@@ -3196,11 +3270,21 @@ void JoinVals::pruneSubRegValues(LiveInterval &LI, LaneBitmask &ShrinkMask) {
// with V.OtherVNI.
LIS->extendToIndices(S, EndPoints);
}
+
+ // We may need to eliminate the subrange if the copy introduced a live
+ // out undef value.
+ if (ValueOut->isPHIDef())
+ ShrinkMask |= S.LaneMask;
continue;
}
+
// If a subrange ends at the copy, then a value was copied but only
// partially used later. Shrink the subregister range appropriately.
- if (Q.valueIn() != nullptr && Q.valueOut() == nullptr) {
+ //
+ // Ultimately this calls shrinkToUses, so assuming ShrinkMask is
+ // conservatively correct.
+ if ((Q.valueIn() != nullptr && Q.valueOut() == nullptr) ||
+ (V.Resolution == CR_Erase && isLiveThrough(Q))) {
LLVM_DEBUG(dbgs() << "\t\tDead uses at sublane "
<< PrintLaneMask(S.LaneMask) << " at " << Def
<< "\n");
@@ -3526,6 +3610,64 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
// Scan and mark undef any DBG_VALUEs that would refer to a different value.
checkMergingChangesDbgValues(CP, LHS, LHSVals, RHS, RHSVals);
+ // If the RHS covers any PHI locations that were tracked for debug-info, we
+ // must update tracking information to reflect the join.
+ auto RegIt = RegToPHIIdx.find(CP.getSrcReg());
+ if (RegIt != RegToPHIIdx.end()) {
+ // Iterate over all the debug instruction numbers assigned this register.
+ for (unsigned InstID : RegIt->second) {
+ auto PHIIt = PHIValToPos.find(InstID);
+ assert(PHIIt != PHIValToPos.end());
+ const SlotIndex &SI = PHIIt->second.SI;
+
+ // Does the RHS cover the position of this PHI?
+ auto LII = RHS.find(SI);
+ if (LII == RHS.end() || LII->start > SI)
+ continue;
+
+ // Accept two kinds of subregister movement:
+ // * When we merge from one register class into a larger register:
+ // %1:gr16 = some-inst
+ // ->
+ // %2:gr32.sub_16bit = some-inst
+ // * When the PHI is already in a subregister, and the larger class
+ // is coalesced:
+ // %2:gr32.sub_16bit = some-inst
+ // %3:gr32 = COPY %2
+ // ->
+ // %3:gr32.sub_16bit = some-inst
+ // Test for subregister move:
+ if (CP.getSrcIdx() != 0 || CP.getDstIdx() != 0)
+ // If we're moving between different subregisters, ignore this join.
+ // The PHI will not get a location, dropping variable locations.
+ if (PHIIt->second.SubReg && PHIIt->second.SubReg != CP.getSrcIdx())
+ continue;
+
+ // Update our tracking of where the PHI is.
+ PHIIt->second.Reg = CP.getDstReg();
+
+ // If we merge into a sub-register of a larger class (test above),
+ // update SubReg.
+ if (CP.getSrcIdx() != 0)
+ PHIIt->second.SubReg = CP.getSrcIdx();
+ }
+
+ // Rebuild the register index in RegToPHIIdx to account for PHIs tracking
+ // different VRegs now. Copy old collection of debug instruction numbers and
+ // erase the old one:
+ auto InstrNums = RegIt->second;
+ RegToPHIIdx.erase(RegIt);
+
+ // There might already be PHIs being tracked in the destination VReg. Insert
+ // into an existing tracking collection, or insert a new one.
+ RegIt = RegToPHIIdx.find(CP.getDstReg());
+ if (RegIt != RegToPHIIdx.end())
+ RegIt->second.insert(RegIt->second.end(), InstrNums.begin(),
+ InstrNums.end());
+ else
+ RegToPHIIdx.insert({CP.getDstReg(), InstrNums});
+ }
+
// Join RHS into LHS.
LHS.join(RHS, LHSVals.getAssignments(), RHSVals.getAssignments(), NewVNInfo);
@@ -3565,8 +3707,12 @@ void RegisterCoalescer::buildVRegToDbgValueMap(MachineFunction &MF)
// After collecting a block of DBG_VALUEs into ToInsert, enter them into the
// vreg => DbgValueLoc map.
auto CloseNewDVRange = [this, &ToInsert](SlotIndex Slot) {
- for (auto *X : ToInsert)
- DbgVRegToValues[X->getDebugOperand(0).getReg()].push_back({Slot, X});
+ for (auto *X : ToInsert) {
+ for (auto Op : X->debug_operands()) {
+ if (Op.isReg() && Op.getReg().isVirtual())
+ DbgVRegToValues[Op.getReg()].push_back({Slot, X});
+ }
+ }
ToInsert.clear();
};
@@ -3578,10 +3724,12 @@ void RegisterCoalescer::buildVRegToDbgValueMap(MachineFunction &MF)
SlotIndex CurrentSlot = Slots.getMBBStartIdx(&MBB);
for (auto &MI : MBB) {
- if (MI.isDebugValue() && MI.getDebugOperand(0).isReg() &&
- MI.getDebugOperand(0).getReg().isVirtual()) {
- ToInsert.push_back(&MI);
- } else if (!MI.isDebugInstr()) {
+ if (MI.isDebugValue()) {
+ if (any_of(MI.debug_operands(), [](const MachineOperand &MO) {
+ return MO.isReg() && MO.getReg().isVirtual();
+ }))
+ ToInsert.push_back(&MI);
+ } else if (!MI.isDebugOrPseudoInstr()) {
CurrentSlot = Slots.getInstructionIndex(MI);
CloseNewDVRange(CurrentSlot);
}
@@ -3677,12 +3825,14 @@ void RegisterCoalescer::checkMergingChangesDbgValuesImpl(Register Reg,
if (DbgValueSetIt->first < SegmentIt->end) {
// "Other" is live and there is a DBG_VALUE of Reg: test if we should
// set it undef.
- if (DbgValueSetIt->first >= SegmentIt->start &&
- DbgValueSetIt->second->getDebugOperand(0).getReg() != 0 &&
- ShouldUndef(DbgValueSetIt->first)) {
- // Mark undef, erase record of this DBG_VALUE to avoid revisiting.
- DbgValueSetIt->second->setDebugValueUndef();
- continue;
+ if (DbgValueSetIt->first >= SegmentIt->start) {
+ bool HasReg = DbgValueSetIt->second->hasDebugOperandForReg(Reg);
+ bool ShouldUndefReg = ShouldUndef(DbgValueSetIt->first);
+ if (HasReg && ShouldUndefReg) {
+ // Mark undef, erase record of this DBG_VALUE to avoid revisiting.
+ DbgValueSetIt->second->setDebugValueUndef();
+ continue;
+ }
}
++DbgValueSetIt;
} else {
@@ -3857,21 +4007,20 @@ RegisterCoalescer::copyCoalesceInMBB(MachineBasicBlock *MBB) {
// are not inherently easier to resolve, but slightly preferable until we
// have local live range splitting. In particular this is required by
// cmp+jmp macro fusion.
- for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end();
- MII != E; ++MII) {
- if (!MII->isCopyLike())
+ for (MachineInstr &MI : *MBB) {
+ if (!MI.isCopyLike())
continue;
- bool ApplyTerminalRule = applyTerminalRule(*MII);
- if (isLocalCopy(&(*MII), LIS)) {
+ bool ApplyTerminalRule = applyTerminalRule(MI);
+ if (isLocalCopy(&MI, LIS)) {
if (ApplyTerminalRule)
- LocalTerminals.push_back(&(*MII));
+ LocalTerminals.push_back(&MI);
else
- LocalWorkList.push_back(&(*MII));
+ LocalWorkList.push_back(&MI);
} else {
if (ApplyTerminalRule)
- GlobalTerminals.push_back(&(*MII));
+ GlobalTerminals.push_back(&MI);
else
- WorkList.push_back(&(*MII));
+ WorkList.push_back(&MI);
}
}
// Append the copies evicted by the terminal rule at the end of the list.
@@ -3915,10 +4064,9 @@ void RegisterCoalescer::joinAllIntervals() {
std::vector<MBBPriorityInfo> MBBs;
MBBs.reserve(MF->size());
- for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) {
- MachineBasicBlock *MBB = &*I;
- MBBs.push_back(MBBPriorityInfo(MBB, Loops->getLoopDepth(MBB),
- JoinSplitEdges && isSplitEdge(MBB)));
+ for (MachineBasicBlock &MBB : *MF) {
+ MBBs.push_back(MBBPriorityInfo(&MBB, Loops->getLoopDepth(&MBB),
+ JoinSplitEdges && isSplitEdge(&MBB)));
}
array_pod_sort(MBBs.begin(), MBBs.end(), compareMBBPriority);
@@ -3981,6 +4129,19 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {
else
JoinGlobalCopies = (EnableGlobalCopies == cl::BOU_TRUE);
+ // If there are PHIs tracked by debug-info, they will need updating during
+ // coalescing. Build an index of those PHIs to ease updating.
+ SlotIndexes *Slots = LIS->getSlotIndexes();
+ for (const auto &DebugPHI : MF->DebugPHIPositions) {
+ MachineBasicBlock *MBB = DebugPHI.second.MBB;
+ Register Reg = DebugPHI.second.Reg;
+ unsigned SubReg = DebugPHI.second.SubReg;
+ SlotIndex SI = Slots->getMBBStartIdx(MBB);
+ PHIValPos P = {SI, Reg, SubReg};
+ PHIValToPos.insert(std::make_pair(DebugPHI.first, P));
+ RegToPHIIdx[Reg].push_back(DebugPHI.first);
+ }
+
// The MachineScheduler does not currently require JoinSplitEdges. This will
// either be enabled unconditionally or replaced by a more general live range
// splitting optimization.
@@ -4036,6 +4197,18 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {
}
}
+ // After coalescing, update any PHIs that are being tracked by debug-info
+ // with their new VReg locations.
+ for (auto &p : MF->DebugPHIPositions) {
+ auto it = PHIValToPos.find(p.first);
+ assert(it != PHIValToPos.end());
+ p.second.Reg = it->second.Reg;
+ p.second.SubReg = it->second.SubReg;
+ }
+
+ PHIValToPos.clear();
+ RegToPHIIdx.clear();
+
LLVM_DEBUG(dump());
if (VerifyCoalescing)
MF->verify(this, "After register coalescing");