Add the long awaited memory operand folding support for linear scan


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12058 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index e517cb3..1238a2c 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/lib/CodeGen/VirtRegMap.cpp
@@ -19,6 +19,7 @@
 #include "VirtRegMap.h"
 #include "llvm/Function.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "Support/Statistic.h"
@@ -49,6 +50,24 @@
     return frameIndex;
 }
 
+void VirtRegMap::virtFolded(unsigned virtReg,
+                            MachineInstr* oldMI,
+                            MachineInstr* newMI)
+{
+    // move previous memory references folded to new instruction
+    MI2VirtMap::iterator i, e;
+    std::vector<MI2VirtMap::mapped_type> regs;
+    for (tie(i, e) = mi2vMap_.equal_range(oldMI); i != e; ) {
+        regs.push_back(i->second);
+        mi2vMap_.erase(i++);
+    }
+    for (unsigned i = 0, e = regs.size(); i != e; ++i)
+        mi2vMap_.insert(std::make_pair(newMI, i));
+
+    // add new memory reference
+    mi2vMap_.insert(std::make_pair(newMI, virtReg));
+}
+
 std::ostream& llvm::operator<<(std::ostream& os, const VirtRegMap& vrm)
 {
     const MRegisterInfo* mri = vrm.mf_->getTarget().getRegisterInfo();
@@ -129,9 +148,9 @@
                                          vrm_.getStackSlot(virtReg),
                                          mri_.getRegClass(physReg));
                 ++numStores;
-                DEBUG(std::cerr << "\t\tadded: ";
+                DEBUG(std::cerr << "added: ";
                       prior(nextLastRef)->print(std::cerr, tm_);
-                      std::cerr << "\t\tafter: ";
+                      std::cerr << "after: ";
                       lastDef->print(std::cerr, tm_));
                 lastDef_[virtReg] = 0;
             }
@@ -161,10 +180,8 @@
                                               vrm_.getStackSlot(virtReg),
                                               mri_.getRegClass(physReg));
                     ++numLoads;
-                    DEBUG(std::cerr << "\t\tadded: ";
-                          prior(mii)->print(std::cerr,tm_);
-                          std::cerr << "\t\tbefore: ";
-                          mii->print(std::cerr, tm_));
+                    DEBUG(std::cerr << "added: ";
+                          prior(mii)->print(std::cerr,tm_));
                     lastDef_[virtReg] = mii;
                 }
             }
@@ -186,6 +203,16 @@
         void eliminateVirtRegsInMbb(MachineBasicBlock& mbb) {
             for (MachineBasicBlock::iterator mii = mbb.begin(),
                      mie = mbb.end(); mii != mie; ++mii) {
+
+                // if we have references to memory operands make sure
+                // we clear all physical registers that may contain
+                // the value of the spilled virtual register
+                VirtRegMap::MI2VirtMap::const_iterator i, e;
+                for (tie(i, e) = vrm_.getFoldedVirts(mii); i != e; ++i) {
+                    unsigned physReg = vrm_.getPhys(i->second);
+                    if (physReg) vacateJustPhysReg(mbb, mii, physReg);
+                }
+
                 // rewrite all used operands
                 for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
                     MachineOperand& op = mii->getOperand(i);