[llvm-commits] [llvm] r86725 - in /llvm/trunk: include/llvm/CodeGen/LiveVariables.h lib/CodeGen/LiveVariables.cpp lib/CodeGen/PHIElimination.cpp lib/CodeGen/PHIElimination.h

Jakob Stoklund Olesen stoklund at 2pi.dk
Tue Nov 10 14:01:05 PST 2009


Author: stoklund
Date: Tue Nov 10 16:01:05 2009
New Revision: 86725

URL: http://llvm.org/viewvc/llvm-project?rev=86725&view=rev
Log:
Teach PHIElimination to split critical edges when -split-phi-edges is enabled.

Critical edges leading to a PHI node are split when the PHI source variable is
live out from the predecessor block. This help the coalescer eliminate more
PHI joins.

Modified:
    llvm/trunk/include/llvm/CodeGen/LiveVariables.h
    llvm/trunk/lib/CodeGen/LiveVariables.cpp
    llvm/trunk/lib/CodeGen/PHIElimination.cpp
    llvm/trunk/lib/CodeGen/PHIElimination.h

Modified: llvm/trunk/include/llvm/CodeGen/LiveVariables.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveVariables.h?rev=86725&r1=86724&r2=86725&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/LiveVariables.h (original)
+++ llvm/trunk/include/llvm/CodeGen/LiveVariables.h Tue Nov 10 16:01:05 2009
@@ -103,7 +103,10 @@
       Kills.erase(I);
       return true;
     }
-    
+
+    /// findKill - Find a kill instruction in MBB. Return NULL if none is found.
+    MachineInstr *findKill(const MachineBasicBlock *MBB) const;
+
     void dump() const;
   };
 
@@ -263,6 +266,10 @@
   void HandleVirtRegDef(unsigned reg, MachineInstr *MI);
   void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB,
                         MachineInstr *MI);
+
+  /// addNewBlock - Add a new basic block A as an empty predecessor of B. All
+  /// variables that are live into B will be marked as passing live through A.
+  void addNewBlock(MachineBasicBlock *A, MachineBasicBlock *B);
 };
 
 } // End llvm namespace

Modified: llvm/trunk/lib/CodeGen/LiveVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveVariables.cpp?rev=86725&r1=86724&r2=86725&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/LiveVariables.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveVariables.cpp Tue Nov 10 16:01:05 2009
@@ -50,6 +50,14 @@
   MachineFunctionPass::getAnalysisUsage(AU);
 }
 
+MachineInstr *
+LiveVariables::VarInfo::findKill(const MachineBasicBlock *MBB) const {
+  for (unsigned i = 0, e = Kills.size(); i != e; ++i)
+    if (Kills[i]->getParent() == MBB)
+      return Kills[i];
+  return NULL;
+}
+
 void LiveVariables::VarInfo::dump() const {
   errs() << "  Alive in blocks: ";
   for (SparseBitVector<>::iterator I = AliveBlocks.begin(),
@@ -641,3 +649,35 @@
         PHIVarInfo[BBI->getOperand(i + 1).getMBB()->getNumber()]
           .push_back(BBI->getOperand(i).getReg());
 }
+
+void LiveVariables::addNewBlock(MachineBasicBlock *A, MachineBasicBlock *B) {
+  unsigned NumA = A->getNumber();
+  unsigned NumB = B->getNumber();
+
+  // Update info for all live variables
+  for (unsigned i = 0, e = VirtRegInfo.size(); i != e; ++i) {
+    VarInfo &VI = VirtRegInfo[i];
+
+    // Anything live through B is also live through A.
+    if (VI.AliveBlocks.test(NumB)) {
+      VI.AliveBlocks.set(NumA);
+      continue;
+    }
+
+    // If we're not killed in B, we are not live in
+    if (!VI.findKill(B))
+      continue;
+
+    unsigned Reg = i+TargetRegisterInfo::FirstVirtualRegister;
+
+    // Find a def outside B
+    for (MachineRegisterInfo::def_iterator di = MRI->def_begin(Reg),
+           de=MRI->def_end(); di != de; ++di) {
+      if (di->getParent() != B) {
+        // Reg was defined outside B and killed in B - it must be live in.
+        VI.AliveBlocks.set(NumA);
+        break;
+      }
+    }
+  }
+}

Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.cpp?rev=86725&r1=86724&r2=86725&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/PHIElimination.cpp (original)
+++ llvm/trunk/lib/CodeGen/PHIElimination.cpp Tue Nov 10 16:01:05 2009
@@ -27,12 +27,20 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
 #include <algorithm>
 #include <map>
 using namespace llvm;
 
 STATISTIC(NumAtomic, "Number of atomic phis lowered");
+STATISTIC(NumSplits, "Number of critical edges split on demand");
+
+static cl::opt<bool>
+SplitEdges("split-phi-edges",
+           cl::desc("Split critical edges during phi elimination"),
+           cl::init(false), cl::Hidden);
 
 char PHIElimination::ID = 0;
 static RegisterPass<PHIElimination>
@@ -41,10 +49,14 @@
 const PassInfo *const llvm::PHIEliminationID = &X;
 
 void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const {
-  AU.setPreservesCFG();
   AU.addPreserved<LiveVariables>();
-  AU.addPreservedID(MachineLoopInfoID);
-  AU.addPreservedID(MachineDominatorsID);
+  if (SplitEdges) {
+    AU.addRequired<LiveVariables>();
+  } else {
+    AU.setPreservesCFG();
+    AU.addPreservedID(MachineLoopInfoID);
+    AU.addPreservedID(MachineDominatorsID);
+  }
   MachineFunctionPass::getAnalysisUsage(AU);
 }
 
@@ -84,6 +96,9 @@
   if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
     return false;   // Quick exit for basic blocks without PHIs.
 
+  if (SplitEdges)
+    SplitPHIEdges(MF, MBB);
+
   // Get an iterator to the first instruction after the last PHI node (this may
   // also be the end of the basic block).
   MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin());
@@ -277,7 +292,8 @@
 
     // Okay, if we now know that the value is not live out of the block, we can
     // add a kill marker in this block saying that it kills the incoming value!
-    if (!ValueIsUsed && !isLiveOut(SrcReg, opBlock, *LV)) {
+    // When SplitEdges is enabled, the value is never live out.
+    if (!ValueIsUsed && (SplitEdges || !isLiveOut(SrcReg, opBlock, *LV))) {
       // In our final twist, we have to decide which instruction kills the
       // register.  In most cases this is the copy, however, the first
       // terminator instruction at the end of the block may also use the value.
@@ -329,6 +345,22 @@
                                      BBI->getOperand(i).getReg())];
 }
 
+void llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF,
+                                         MachineBasicBlock &MBB) {
+  LiveVariables &LV = getAnalysis<LiveVariables>();
+  for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end();
+       BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) {
+    for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) {
+      unsigned Reg = BBI->getOperand(i).getReg();
+      MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB();
+      // We break edges when registers are live out from the predecessor block
+      // (not considering PHI nodes).
+      if (isLiveOut(Reg, *PreMBB, LV))
+        SplitCriticalEdge(PreMBB, &MBB);
+    }
+  }
+}
+
 bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB,
                                      LiveVariables &LV) {
   LiveVariables::VarInfo &InRegVI = LV.getVarInfo(Reg);
@@ -376,3 +408,43 @@
   }
   return false;
 }
+
+MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A,
+                                                     MachineBasicBlock *B) {
+  assert(A && B && "Missing MBB end point");
+  ++NumSplits;
+
+  MachineFunction *MF = A->getParent();
+  MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(B->getBasicBlock());
+  MF->push_back(NMBB);
+  const unsigned NewNum = NMBB->getNumber();
+  DEBUG(errs() << "PHIElimination splitting critical edge:"
+        " BB#" << A->getNumber()
+        << " -- BB#" << NewNum
+        << " -- BB#" << B->getNumber() << '\n');
+
+  A->ReplaceUsesOfBlockWith(B, NMBB);
+  NMBB->addSuccessor(B);
+
+  // Insert unconditional "jump B" instruction in NMBB.
+  SmallVector<MachineOperand, 4> Cond;
+  MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, B, NULL, Cond);
+
+  LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>();
+  if (LV)
+    LV->addNewBlock(NMBB, B);
+
+  // Fix PHI nodes in B so they refer to NMBB instead of A
+  for (MachineBasicBlock::iterator i = B->begin(), e = B->end();
+       i != e && i->getOpcode() == TargetInstrInfo::PHI; ++i)
+    for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2)
+      if (i->getOperand(ni+1).getMBB() == A) {
+        i->getOperand(ni+1).setMBB(NMBB);
+        // Mark PHI sources as passing live through NMBB
+        if (LV)
+          LV->getVarInfo(i->getOperand(ni).getReg()).AliveBlocks.set(NewNum);
+      }
+  return NMBB;
+}
+
+

Modified: llvm/trunk/lib/CodeGen/PHIElimination.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.h?rev=86725&r1=86724&r2=86725&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/PHIElimination.h (original)
+++ llvm/trunk/lib/CodeGen/PHIElimination.h Tue Nov 10 16:01:05 2009
@@ -89,12 +89,21 @@
     ///
     void analyzePHINodes(const MachineFunction& Fn);
 
+    /// Split critical edges where necessary for good coalescer performance.
+    void SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB);
+
     /// isLiveOut - Determine if Reg is live out from MBB, when not
     /// considering PHI nodes. This means that Reg is either killed by
     /// a successor block or passed through one.
     bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB,
                    LiveVariables &LV);
 
+    /// SplitCriticalEdge - Split a critical edge from A to B by
+    /// inserting a new MBB. Update branches in A and PHI instructions
+    /// in B. Return the new block.
+    MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *A,
+                                         MachineBasicBlock *B);
+
     // FindCopyInsertPoint - Find a safe place in MBB to insert a copy from
     // SrcReg.  This needs to be after any def or uses of SrcReg, but before
     // any subsequent point where control flow might jump out of the basic





More information about the llvm-commits mailing list