mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-14 09:38:40 +00:00
Trace through sibling PHIs in bulk.
When traceSiblingValue() encounters a PHI-def value created by live range splitting, don't look at all the predecessor blocks. That can be very expensive in a complicated CFG. Instead, consider that all the non-PHI defs jointly dominate all the PHI-defs. Tracing directly to all the non-PHI defs is much faster that zipping around in the CFG when there are many PHIs with many predecessors. This significantly improves compile time for indirectbr interpreters. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139797 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b6e9a83349
commit
6b6e32d954
@ -120,11 +120,6 @@ private:
|
|||||||
typedef DenseMap<VNInfo*, SibValueInfo> SibValueMap;
|
typedef DenseMap<VNInfo*, SibValueInfo> SibValueMap;
|
||||||
SibValueMap SibValues;
|
SibValueMap SibValues;
|
||||||
|
|
||||||
// Values live-out from basic blocks. This is the same as
|
|
||||||
// LI.getVNInfoAt(LIS.getMBBEndIdx(MBB).getPrevSlot())
|
|
||||||
typedef DenseMap<MachineBasicBlock*, VNInfo*> LiveOutMap;
|
|
||||||
LiveOutMap LiveOutValues;
|
|
||||||
|
|
||||||
// Dead defs generated during spilling.
|
// Dead defs generated during spilling.
|
||||||
SmallVector<MachineInstr*, 8> DeadDefs;
|
SmallVector<MachineInstr*, 8> DeadDefs;
|
||||||
|
|
||||||
@ -500,6 +495,7 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
|
|||||||
|
|
||||||
// Trace through PHI-defs created by live range splitting.
|
// Trace through PHI-defs created by live range splitting.
|
||||||
if (VNI->isPHIDef()) {
|
if (VNI->isPHIDef()) {
|
||||||
|
// Stop at original PHIs. We don't know the value at the predecessors.
|
||||||
if (VNI->def == OrigVNI->def) {
|
if (VNI->def == OrigVNI->def) {
|
||||||
DEBUG(dbgs() << "orig phi value\n");
|
DEBUG(dbgs() << "orig phi value\n");
|
||||||
SVI->second.DefByOrigPHI = true;
|
SVI->second.DefByOrigPHI = true;
|
||||||
@ -507,28 +503,60 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
|
|||||||
propagateSiblingValue(SVI);
|
propagateSiblingValue(SVI);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Get values live-out of predecessors.
|
|
||||||
|
// This is a PHI inserted by live range splitting. We could trace the
|
||||||
|
// live-out value from predecessor blocks, but that search can be very
|
||||||
|
// expensive if there are many predecessors and many more PHIs as
|
||||||
|
// generated by tail-dup when it sees an indirectbr. Instead, look at
|
||||||
|
// all the non-PHI defs that have the same value as OrigVNI. They must
|
||||||
|
// jointly dominate VNI->def. This is not optimal since VNI may actually
|
||||||
|
// be jointly dominated by a smaller subset of defs, so there is a change
|
||||||
|
// we will miss a AllDefsAreReloads optimization.
|
||||||
|
|
||||||
|
// Separate all values dominated by OrigVNI into PHIs and non-PHIs.
|
||||||
|
SmallVector<VNInfo*, 8> PHIs, NonPHIs;
|
||||||
LiveInterval &LI = LIS.getInterval(Reg);
|
LiveInterval &LI = LIS.getInterval(Reg);
|
||||||
MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def);
|
LiveInterval &OrigLI = LIS.getInterval(Original);
|
||||||
DEBUG(dbgs() << "split phi value, check " << MBB->pred_size()
|
|
||||||
<< " preds\n");
|
for (LiveInterval::vni_iterator VI = LI.vni_begin(), VE = LI.vni_end();
|
||||||
for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
|
VI != VE; ++VI) {
|
||||||
PE = MBB->pred_end(); PI != PE; ++PI) {
|
VNInfo *VNI2 = *VI;
|
||||||
// Use a cache of block live-out values. This is faster than using
|
if (VNI2->isUnused())
|
||||||
// getVNInfoAt on complex intervals.
|
|
||||||
VNInfo *&PVNI = LiveOutValues[*PI];
|
|
||||||
if (!PVNI)
|
|
||||||
PVNI = LI.getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot());
|
|
||||||
if (!PVNI)
|
|
||||||
continue;
|
continue;
|
||||||
// Known predecessor value? Try an insertion.
|
if (!OrigLI.containsOneValue() &&
|
||||||
tie(SVI, Inserted) =
|
OrigLI.getVNInfoAt(VNI2->def) != OrigVNI)
|
||||||
SibValues.insert(std::make_pair(PVNI, SibValueInfo(Reg, PVNI)));
|
continue;
|
||||||
// This is the first time we see PVNI, add it to the worklist.
|
if (VNI2->isPHIDef() && VNI2->def != OrigVNI->def)
|
||||||
if (Inserted)
|
PHIs.push_back(VNI2);
|
||||||
WorkList.push_back(std::make_pair(Reg, PVNI));
|
else
|
||||||
propagateSiblingValue(SVI, VNI);
|
NonPHIs.push_back(VNI2);
|
||||||
}
|
}
|
||||||
|
DEBUG(dbgs() << "split phi value, checking " << PHIs.size()
|
||||||
|
<< " phi-defs, and " << NonPHIs.size()
|
||||||
|
<< " non-phi/orig defs\n");
|
||||||
|
|
||||||
|
// Create entries for all the PHIs. Don't add them to the worklist, we
|
||||||
|
// are processing all of them in one go here.
|
||||||
|
for (unsigned i = 0, e = PHIs.size(); i != e; ++i)
|
||||||
|
SibValues.insert(std::make_pair(PHIs[i], SibValueInfo(Reg, PHIs[i])));
|
||||||
|
|
||||||
|
// Add every PHI as a dependent of all the non-PHIs.
|
||||||
|
for (unsigned i = 0, e = NonPHIs.size(); i != e; ++i) {
|
||||||
|
VNInfo *NonPHI = NonPHIs[i];
|
||||||
|
// Known value? Try an insertion.
|
||||||
|
tie(SVI, Inserted) =
|
||||||
|
SibValues.insert(std::make_pair(NonPHI, SibValueInfo(Reg, NonPHI)));
|
||||||
|
// Add all the PHIs as dependents of NonPHI.
|
||||||
|
for (unsigned pi = 0, pe = PHIs.size(); pi != pe; ++pi)
|
||||||
|
SVI->second.Deps.push_back(PHIs[pi]);
|
||||||
|
// This is the first time we see NonPHI, add it to the worklist.
|
||||||
|
if (Inserted)
|
||||||
|
WorkList.push_back(std::make_pair(Reg, NonPHI));
|
||||||
|
else
|
||||||
|
// Propagate to all inserted PHIs, not just VNI.
|
||||||
|
propagateSiblingValue(SVI);
|
||||||
|
}
|
||||||
|
|
||||||
// Next work list item.
|
// Next work list item.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -587,7 +615,6 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
|
|||||||
/// Keep track of values that may be rematerializable.
|
/// Keep track of values that may be rematerializable.
|
||||||
void InlineSpiller::analyzeSiblingValues() {
|
void InlineSpiller::analyzeSiblingValues() {
|
||||||
SibValues.clear();
|
SibValues.clear();
|
||||||
LiveOutValues.clear();
|
|
||||||
|
|
||||||
// No siblings at all?
|
// No siblings at all?
|
||||||
if (Edit->getReg() == Original)
|
if (Edit->getReg() == Original)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user