Add new shorter predicates for testing machine operands for various types:
[oota-llvm.git] / lib / CodeGen / StrongPHIElimination.cpp
index ee62a6b30c9a7c2672641636de24e9b23f7ce8dc..d7360840e25ac0074b674adb7ba85f5b5f62e660 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Owen Anderson and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -21,7 +21,6 @@
 
 #define DEBUG_TYPE "strongphielim"
 #include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/BreakCriticalMachineEdge.h"
 #include "llvm/CodeGen/LiveVariables.h"
 #include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -29,6 +28,7 @@
 #include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Compiler.h"
 using namespace llvm;
@@ -40,7 +40,10 @@ namespace {
     StrongPHIElimination() : MachineFunctionPass((intptr_t)&ID) {}
 
     DenseMap<MachineBasicBlock*,
-             SmallVector<std::pair<unsigned, unsigned>, 2> > Waiting;
+             std::map<unsigned, unsigned> > Waiting;
+    
+    std::map<unsigned, std::vector<unsigned> > Stacks;
+    std::set<unsigned> UsedByAnother;
 
     bool runOnMachineFunction(MachineFunction &Fn);
     
@@ -57,7 +60,7 @@ namespace {
       preorder.clear();
       maxpreorder.clear();
       
-      waiting.clear();
+      Waiting.clear();
     }
 
   private:
@@ -90,8 +93,6 @@ namespace {
     DenseMap<MachineBasicBlock*, unsigned> preorder;
     DenseMap<MachineBasicBlock*, unsigned> maxpreorder;
     
-    DenseMap<MachineBasicBlock*, std::vector<MachineInstr*> > waiting;
-    
     
     void computeDFS(MachineFunction& MF);
     void processBlock(MachineBasicBlock* MBB);
@@ -101,8 +102,8 @@ namespace {
                          std::set<unsigned>& PHIUnion,
                          std::vector<StrongPHIElimination::DomForestNode*>& DF,
                          std::vector<std::pair<unsigned, unsigned> >& locals);
-    void breakCriticalEdges(MachineFunction &Fn);
-    
+    void ScheduleCopies(MachineBasicBlock* MBB, std::set<unsigned>& pushed);
+    void InsertCopies(MachineBasicBlock* MBB);
   };
 
   char StrongPHIElimination::ID = 0;
@@ -258,6 +259,101 @@ bool isLiveOut(LiveVariables::VarInfo& V, MachineBasicBlock* MBB) {
   return false;
 }
 
+/// isKillInst - helper method that determines, from a VarInfo, if an 
+/// instruction kills a given register
+bool isKillInst(LiveVariables::VarInfo& V, MachineInstr* MI) {
+  return std::find(V.Kills.begin(), V.Kills.end(), MI) != V.Kills.end();
+}
+
+/// interferes - checks for local interferences by scanning a block.  The only
+/// trick parameter is 'mode' which tells it the relationship of the two
+/// registers. 0 - defined in the same block, 1 - first properly dominates
+/// second, 2 - second properly dominates first 
+bool interferes(LiveVariables::VarInfo& First, LiveVariables::VarInfo& Second,
+                MachineBasicBlock* scan, unsigned mode) {
+  MachineInstr* def = 0;
+  MachineInstr* kill = 0;
+  
+  bool interference = false;
+  
+  // Wallk the block, checking for interferences
+  for (MachineBasicBlock::iterator MBI = scan->begin(), MBE = scan->end();
+       MBI != MBE; ++MBI) {
+    MachineInstr* curr = MBI;
+    
+    // Same defining block...
+    if (mode == 0) {
+      if (curr == First.DefInst) {
+        // If we find our first DefInst, save it
+        if (!def) {
+          def = curr;
+        // If there's already an unkilled DefInst, then 
+        // this is an interference
+        } else if (!kill) {
+          interference = true;
+          break;
+        // If there's a DefInst followed by a KillInst, then
+        // they can't interfere
+        } else {
+          interference = false;
+          break;
+        }
+      // Symmetric with the above
+      } else if (curr == Second.DefInst ) {
+        if (!def) {
+          def = curr;
+        } else if (!kill) {
+          interference = true;
+          break;
+        } else {
+          interference = false;
+          break;
+        }
+      // Store KillInsts if they match up with the DefInst
+      } else if (isKillInst(First, curr)) {
+        if (def == First.DefInst) {
+          kill = curr;
+        } else if (isKillInst(Second, curr)) {
+          if (def == Second.DefInst) {
+            kill = curr;
+          }
+        }
+      }
+    // First properly dominates second...
+    } else if (mode == 1) {
+      if (curr == Second.DefInst) {
+        // DefInst of second without kill of first is an interference
+        if (!kill) {
+          interference = true;
+          break;
+        // DefInst after a kill is a non-interference
+        } else {
+          interference = false;
+          break;
+        }
+      // Save KillInsts of First
+      } else if (isKillInst(First, curr)) {
+        kill = curr;
+      }
+    // Symmetric with the above
+    } else if (mode == 2) {
+      if (curr == First.DefInst) {
+        if (!kill) {
+          interference = true;
+          break;
+        } else {
+          interference = false;
+          break;
+        }
+      } else if (isKillInst(Second, curr)) {
+        kill = curr;
+      }
+    }
+  }
+  
+  return interference;
+}
+
 /// processBlock - Eliminate PHIs in the given block
 void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) {
   LiveVariables& LV = getAnalysis<LiveVariables>();
@@ -289,8 +385,9 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) {
           UnionedBlocks.count(SrcInfo.DefInst->getParent())) {
         
         // add a copy from a_i to p in Waiting[From[a_i]]
-        MachineBasicBlock* From = P->getOperand(i).getMachineBasicBlock();
-        Waiting[From].push_back(std::make_pair(SrcReg, DestReg));
+        MachineBasicBlock* From = P->getOperand(i).getMBB();
+        Waiting[From].insert(std::make_pair(SrcReg, DestReg));
+        UsedByAnother.insert(SrcReg);
       } else {
         PHIUnion.insert(SrcReg);
         UnionedBlocks.insert(SrcInfo.DefInst->getParent());
@@ -304,7 +401,51 @@ void StrongPHIElimination::processBlock(MachineBasicBlock* MBB) {
     std::vector<std::pair<unsigned, unsigned> > localInterferences;
     processPHIUnion(P, PHIUnion, DF, localInterferences);
     
-    // FIXME: Check for local interferences
+    // Check for local interferences
+    for (std::vector<std::pair<unsigned, unsigned> >::iterator I =
+        localInterferences.begin(), E = localInterferences.end(); I != E; ++I) {
+      std::pair<unsigned, unsigned> p = *I;
+      
+      LiveVariables::VarInfo& FirstInfo = LV.getVarInfo(p.first);
+      LiveVariables::VarInfo& SecondInfo = LV.getVarInfo(p.second);
+      
+      MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
+      
+      // Determine the block we need to scan and the relationship between
+      // the two registers
+      MachineBasicBlock* scan = 0;
+      unsigned mode = 0;
+      if (FirstInfo.DefInst->getParent() == SecondInfo.DefInst->getParent()) {
+        scan = FirstInfo.DefInst->getParent();
+        mode = 0; // Same block
+      } else if (MDT.dominates(FirstInfo.DefInst->getParent(),
+                             SecondInfo.DefInst->getParent())) {
+        scan = SecondInfo.DefInst->getParent();
+        mode = 1; // First dominates second
+      } else {
+        scan = FirstInfo.DefInst->getParent();
+        mode = 2; // Second dominates first
+      }
+      
+      // If there's an interference, we need to insert  copies
+      if (interferes(FirstInfo, SecondInfo, scan, mode)) {
+        // Insert copies for First
+        for (int i = P->getNumOperands() - 1; i >= 2; i-=2) {
+          if (P->getOperand(i-1).getReg() == p.first) {
+            unsigned SrcReg = p.first;
+            MachineBasicBlock* From = P->getOperand(i).getMBB();
+            
+            Waiting[From].insert(std::make_pair(SrcReg,
+                                                P->getOperand(0).getReg()));
+            UsedByAnother.insert(SrcReg);
+            
+            PHIUnion.erase(SrcReg);
+          }
+        }
+      }
+    }
+    
+    // FIXME: Cache renaming information
     
     ProcessedNames.insert(PHIUnion.begin(), PHIUnion.end());
     ++P;
@@ -346,7 +487,9 @@ void StrongPHIElimination::processPHIUnion(MachineInstr* Inst,
             unsigned SrcReg = DFNode->getReg();
             MachineBasicBlock* From = Inst->getOperand(i).getMBB();
             
-            Waiting[From].push_back(std::make_pair(SrcReg, DestReg));
+            Waiting[From].insert(std::make_pair(SrcReg, DestReg));
+            UsedByAnother.insert(SrcReg);
+            
             PHIUnion.erase(SrcReg);
           }
         }
@@ -366,48 +509,126 @@ void StrongPHIElimination::processPHIUnion(MachineInstr* Inst,
   }
 }
 
-/// breakCriticalEdges - Break critical edges coming into blocks with PHI
-/// nodes, preserving dominator and livevariable info.
-void StrongPHIElimination::breakCriticalEdges(MachineFunction &Fn) {
-  typedef std::pair<MachineBasicBlock*, MachineBasicBlock*> MBB_pair;
+/// ScheduleCopies - Insert copies into predecessor blocks, scheduling
+/// them properly so as to avoid the 'lost copy' and the 'virtual swap'
+/// problems.
+///
+/// Based on "Practical Improvements to the Construction and Destruction
+/// of Static Single Assignment Form" by Briggs, et al.
+void StrongPHIElimination::ScheduleCopies(MachineBasicBlock* MBB,
+                                          std::set<unsigned>& pushed) {
+  std::map<unsigned, unsigned>& copy_set= Waiting[MBB];
+  
+  std::map<unsigned, unsigned> worklist;
+  std::map<unsigned, unsigned> map;
+  
+  // Setup worklist of initial copies
+  for (std::map<unsigned, unsigned>::iterator I = copy_set.begin(),
+       E = copy_set.end(); I != E; ) {
+    map.insert(std::make_pair(I->first, I->first));
+    map.insert(std::make_pair(I->second, I->second));
+         
+    if (!UsedByAnother.count(I->first)) {
+      worklist.insert(*I);
+      
+      // Avoid iterator invalidation
+      unsigned first = I->first;
+      ++I;
+      copy_set.erase(first);
+    } else {
+      ++I;
+    }
+  }
   
-  MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
   LiveVariables& LV = getAnalysis<LiveVariables>();
   
-  // Find critical edges
-  std::vector<MBB_pair> criticals;
-  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
-    if (!I->empty() &&
-        I->begin()->getOpcode() == TargetInstrInfo::PHI &&
-        I->pred_size() > 1)
-      for (MachineBasicBlock::pred_iterator PI = I->pred_begin(),
-           PE = I->pred_end(); PI != PE; ++PI)
-        if ((*PI)->succ_size() > 1)
-          criticals.push_back(std::make_pair(*PI, I));
-  
-  for (std::vector<MBB_pair>::iterator I = criticals.begin(),
-       E = criticals.end(); I != E; ++I) {
-    // Split the edge
-    MachineBasicBlock* new_bb = SplitCriticalMachineEdge(I->first, I->second);
-    
-    // Update dominators
-    MDT.splitBlock(I->first);
+  // Iterate over the worklist, inserting copies
+  while (!worklist.empty() || !copy_set.empty()) {
+    while (!worklist.empty()) {
+      std::pair<unsigned, unsigned> curr = *worklist.begin();
+      worklist.erase(curr.first);
+      
+      if (isLiveOut(LV.getVarInfo(curr.second), MBB)) {
+        // Insert copy from curr.second to a temporary
+        // Push temporary on Stacks
+        // Insert temporary in pushed
+      }
+      
+      // Insert copy from map[curr.first] to curr.second
+      map[curr.first] = curr.second;
+      
+      // If curr.first is a destination in copy_set...
+      for (std::map<unsigned, unsigned>::iterator I = copy_set.begin(),
+           E = copy_set.end(); I != E; )
+        if (curr.first == I->second) {
+          std::pair<unsigned, unsigned> temp = *I;
+          
+          // Avoid iterator invalidation
+          ++I;
+          copy_set.erase(temp.first);
+          worklist.insert(temp);
+          
+          break;
+        } else {
+          ++I;
+        }
+    }
     
-    // Update livevariables
-    for (unsigned var = 1024; var < Fn.getSSARegMap()->getLastVirtReg(); ++var)
-      if (isLiveOut(LV.getVarInfo(var), I->first))
-        LV.getVarInfo(var).AliveBlocks.set(new_bb->getNumber());
+    if (!copy_set.empty()) {
+      std::pair<unsigned, unsigned> curr = *copy_set.begin();
+      copy_set.erase(curr.first);
+      
+      // Insert a copy from dest to a new temporary t at the end of b
+      // map[curr.second] = t;
+      
+      worklist.insert(curr);
+    }
   }
 }
 
+/// InsertCopies - insert copies into MBB and all of its successors
+void StrongPHIElimination::InsertCopies(MachineBasicBlock* MBB) {
+  std::set<unsigned> pushed;
+  
+  // Rewrite register uses from Stacks
+  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end();
+      I != E; ++I)
+    for (unsigned i = 0; i < I->getNumOperands(); ++i)
+      if (I->getOperand(i).isRegister() &&
+          Stacks[I->getOperand(i).getReg()].size()) {
+        I->getOperand(i).setReg(Stacks[I->getOperand(i).getReg()].back());
+      }
+  
+  // Schedule the copies for this block
+  ScheduleCopies(MBB, pushed);
+  
+  // Recur to our successors
+  for (GraphTraits<MachineBasicBlock*>::ChildIteratorType I = 
+       GraphTraits<MachineBasicBlock*>::child_begin(MBB), E =
+       GraphTraits<MachineBasicBlock*>::child_end(MBB); I != E; ++I)
+    InsertCopies(*I);
+  
+  // As we exit this block, pop the names we pushed while processing it
+  for (std::set<unsigned>::iterator I = pushed.begin(), 
+       E = pushed.end(); I != E; ++I)
+    Stacks[*I].pop_back();
+}
+
 bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) {
-  breakCriticalEdges(Fn);
+  // Compute DFS numbers of each block
   computeDFS(Fn);
   
+  // Determine which phi node operands need copies
   for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
     if (!I->empty() &&
         I->begin()->getOpcode() == TargetInstrInfo::PHI)
       processBlock(I);
   
+  // Insert copies
+  // FIXME: This process should probably preserve LiveVariables
+  InsertCopies(Fn.begin());
+  
+  // FIXME: Perform renaming
+  
   return false;
 }