From 6b6e32d954233ddeeae7f99e358ff85059f1176a Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 15 Sep 2011 16:41:12 +0000 Subject: [PATCH] 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 --- lib/CodeGen/InlineSpiller.cpp | 77 +++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp index c1168c92bcf..0c46aeb6aa1 100644 --- a/lib/CodeGen/InlineSpiller.cpp +++ b/lib/CodeGen/InlineSpiller.cpp @@ -120,11 +120,6 @@ private: typedef DenseMap SibValueMap; SibValueMap SibValues; - // Values live-out from basic blocks. This is the same as - // LI.getVNInfoAt(LIS.getMBBEndIdx(MBB).getPrevSlot()) - typedef DenseMap LiveOutMap; - LiveOutMap LiveOutValues; - // Dead defs generated during spilling. SmallVector 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 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; - // Known predecessor 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. - if (Inserted) - WorkList.push_back(std::make_pair(Reg, PVNI)); - propagateSiblingValue(SVI, VNI); + if (!OrigLI.containsOneValue() && + OrigLI.getVNInfoAt(VNI2->def) != OrigVNI) + continue; + 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(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. 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)