Trace through sibling PHIs in bulk.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Thu, 15 Sep 2011 16:41:12 +0000 (16:41 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Thu, 15 Sep 2011 16:41:12 +0000 (16:41 +0000)
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

index c1168c92bcf2614b0ae1009d391326026efc83b4..0c46aeb6aa1c8f15646bf776c08eae555f209252 100644 (file)
@@ -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)