Work in progress. Finding some cse now.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97635 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp
index 6f80741..023ace2 100644
--- a/lib/CodeGen/MachineCSE.cpp
+++ b/lib/CodeGen/MachineCSE.cpp
@@ -17,6 +17,8 @@
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/ADT/ScopedHashTable.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Debug.h"
@@ -41,6 +43,8 @@
         switch (MO.getType()) {
         default: break;
         case MachineOperand::MO_Register:
+          if (MO.isDef() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
+            continue;  // Skip virtual register defs.
           Key |= MO.getReg();
           break;
         case MachineOperand::MO_Immediate:
@@ -76,18 +80,24 @@
 
     static bool isEqual(const MachineInstr* const &LHS,
                         const MachineInstr* const &RHS) {
-      return LHS->isIdenticalTo(RHS);
+      if (RHS == getEmptyKey() || RHS == getTombstoneKey() ||
+          LHS == getEmptyKey() || LHS == getTombstoneKey())
+        return LHS == RHS;
+      return LHS->isIdenticalTo(RHS, MachineInstr::IgnoreVRegDefs);
     }
   };
 } // end llvm namespace
 
 namespace {
   class MachineCSE : public MachineFunctionPass {
-    ScopedHashTable<MachineInstr*, unsigned> VNT;
+    const TargetInstrInfo *TII;
+    MachineRegisterInfo  *MRI;
     MachineDominatorTree *DT;
+    ScopedHashTable<MachineInstr*, unsigned> VNT;
+    unsigned CurrVN;
   public:
     static char ID; // Pass identification
-    MachineCSE() : MachineFunctionPass(&ID) {}
+    MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {}
 
     virtual bool runOnMachineFunction(MachineFunction &MF);
     
@@ -99,6 +109,7 @@
     }
 
   private:
+    bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB);
     bool ProcessBlock(MachineDomTreeNode *Node);
   };
 } // end anonymous namespace
@@ -109,16 +120,89 @@
 
 FunctionPass *llvm::createMachineCSEPass() { return new MachineCSE(); }
 
-bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
-  ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
-  MachineBasicBlock *MBB = Node->getBlock();
-  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
-       ++I) {
+bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI,
+                                          MachineBasicBlock *MBB) {
+  bool Changed = false;
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    MachineOperand &MO = MI->getOperand(i);
+    if (MO.isReg() && MO.isUse()) {
+      unsigned Reg = MO.getReg();
+      if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg))
+        continue;
+      MachineInstr *DefMI = MRI->getVRegDef(Reg);
+      if (DefMI->getParent() == MBB) {
+        unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
+        if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
+            TargetRegisterInfo::isVirtualRegister(SrcReg) &&
+            !SrcSubIdx && !DstSubIdx) {
+          MO.setReg(SrcReg);
+          Changed = true;
+        }
+      }
+    }
+  }
+
+  return Changed;
+}
+
+static bool hasLivePhysRegDefUse(MachineInstr *MI) {
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    MachineOperand &MO = MI->getOperand(i);
+    if (!MO.isReg())
+      continue;
+    unsigned Reg = MO.getReg();
+    if (!Reg)
+      continue;
+    if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
+        !(MO.isDef() && MO.isDead()))
+      return true;
   }
   return false;
 }
 
+bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) {
+  bool Changed = false;
+
+  ScopedHashTableScope<MachineInstr*, unsigned> VNTS(VNT);
+  MachineBasicBlock *MBB = Node->getBlock();
+  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
+       ++I) {
+    MachineInstr *MI = &*I;
+    bool SawStore = false;
+    if (!MI->isSafeToMove(TII, 0, SawStore))
+      continue;
+    // Ignore copies or instructions that read / write physical registers
+    // (except for dead defs of physical registers).
+    unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
+    if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx))
+      continue;
+    if (hasLivePhysRegDefUse(MI))
+      continue;
+
+    bool FoundCSE = VNT.count(MI);
+    if (!FoundCSE) {
+      // Look for trivial copy coalescing opportunities.
+      if (PerformTrivialCoalescing(MI, MBB))
+        FoundCSE = VNT.count(MI);
+    }
+
+    if (FoundCSE)
+      DEBUG(dbgs() << "Found a common subexpression: " << *MI);
+    else
+      VNT.insert(MI, ++CurrVN);
+  }
+
+  // Recursively call ProcessBlock with childred.
+  const std::vector<MachineDomTreeNode*> &Children = Node->getChildren();
+  for (unsigned i = 0, e = Children.size(); i != e; ++i)
+    Changed |= ProcessBlock(Children[i]);
+
+  return Changed;
+}
+
 bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
+  TII = MF.getTarget().getInstrInfo();
+  MRI = &MF.getRegInfo();
   DT = &getAnalysis<MachineDominatorTree>();
   return ProcessBlock(DT->getRootNode());
 }