summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2011-09-15 16:41:12 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2011-09-15 16:41:12 +0000
commit6b6e32d954233ddeeae7f99e358ff85059f1176a (patch)
treeba65d0d3d5fa70118eed8618be9a4f4ce256f7d9
parentb6e9a83349474d348b401f02c58f4a1754181127 (diff)
downloadllvm-6b6e32d954233ddeeae7f99e358ff85059f1176a.tar.gz
llvm-6b6e32d954233ddeeae7f99e358ff85059f1176a.tar.bz2
llvm-6b6e32d954233ddeeae7f99e358ff85059f1176a.tar.xz
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
-rw-r--r--lib/CodeGen/InlineSpiller.cpp73
1 files changed, 50 insertions, 23 deletions
diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp
index c1168c92bc..0c46aeb6aa 100644
--- a/lib/CodeGen/InlineSpiller.cpp
+++ b/lib/CodeGen/InlineSpiller.cpp
@@ -120,11 +120,6 @@ private:
typedef DenseMap<VNInfo*, SibValueInfo> SibValueMap;
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.
SmallVector<MachineInstr*, 8> DeadDefs;
@@ -500,6 +495,7 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
// Trace through PHI-defs created by live range splitting.
if (VNI->isPHIDef()) {
+ // Stop at original PHIs. We don't know the value at the predecessors.
if (VNI->def == OrigVNI->def) {
DEBUG(dbgs() << "orig phi value\n");
SVI->second.DefByOrigPHI = true;
@@ -507,28 +503,60 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
propagateSiblingValue(SVI);
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);
- MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def);
- DEBUG(dbgs() << "split phi value, check " << MBB->pred_size()
- << " preds\n");
- for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
- PE = MBB->pred_end(); PI != PE; ++PI) {
- // Use a cache of block live-out values. This is faster than using
- // getVNInfoAt on complex intervals.
- VNInfo *&PVNI = LiveOutValues[*PI];
- if (!PVNI)
- PVNI = LI.getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot());
- if (!PVNI)
+ LiveInterval &OrigLI = LIS.getInterval(Original);
+
+ for (LiveInterval::vni_iterator VI = LI.vni_begin(), VE = LI.vni_end();
+ VI != VE; ++VI) {
+ VNInfo *VNI2 = *VI;
+ if (VNI2->isUnused())
+ continue;
+ if (!OrigLI.containsOneValue() &&
+ OrigLI.getVNInfoAt(VNI2->def) != OrigVNI)
continue;
- // Known predecessor value? Try an insertion.
+ if (VNI2->isPHIDef() && VNI2->def != OrigVNI->def)
+ PHIs.push_back(VNI2);
+ else
+ 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(PVNI, SibValueInfo(Reg, PVNI)));
- // This is the first time we see PVNI, add it to the worklist.
+ 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, PVNI));
- propagateSiblingValue(SVI, VNI);
+ WorkList.push_back(std::make_pair(Reg, NonPHI));
+ else
+ // Propagate to all inserted PHIs, not just VNI.
+ propagateSiblingValue(SVI);
}
+
// Next work list item.
continue;
}
@@ -587,7 +615,6 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI,
/// Keep track of values that may be rematerializable.
void InlineSpiller::analyzeSiblingValues() {
SibValues.clear();
- LiveOutValues.clear();
// No siblings at all?
if (Edit->getReg() == Original)