Use MachineInstr::readsWritesVirtualRegister to determine if a register is read.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 21 May 2010 16:42:30 +0000 (16:42 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 21 May 2010 16:42:30 +0000 (16:42 +0000)
This correctly handles partial redefines and undef uses.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@104322 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachineInstr.h
lib/CodeGen/LiveIntervalAnalysis.cpp
lib/CodeGen/MachineInstr.cpp

index 5e62f0bcfb8f6d4699498195b925a338d6a14bc0..cd72344dc71ebbd68ed967b3a1bce862b0e0ec6f 100644 (file)
@@ -28,6 +28,7 @@
 
 namespace llvm {
 
+template <typename T> class SmallVectorImpl;
 class AliasAnalysis;
 class TargetInstrDesc;
 class TargetInstrInfo;
@@ -239,7 +240,16 @@ public:
   /// readsVirtualRegister - Return true if the MachineInstr reads the specified
   /// virtual register. Take into account that a partial define is a
   /// read-modify-write operation.
-  bool readsVirtualRegister(unsigned Reg) const;
+  bool readsVirtualRegister(unsigned Reg) const {
+    return readsWritesVirtualRegister(Reg).first;
+  }
+
+  /// readsWritesVirtualRegister - Return a pair of bools (reads, writes)
+  /// indicating if this instruction reads or writes Reg. This also considers
+  /// partial defines.
+  /// If Ops is not null, all operand indices for Reg are added.
+  std::pair<bool,bool> readsWritesVirtualRegister(unsigned Reg,
+                                      SmallVectorImpl<unsigned> *Ops = 0) const;
 
   /// killsRegister - Return true if the MachineInstr kills the specified
   /// register. If TargetRegisterInfo is passed, then it also checks if there is
index c07802ee26b359cb3b9365300360111c96280797..5b1c36932d21b0d3168087da3dc2d6dc22aed452 100644 (file)
@@ -1098,7 +1098,6 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
     if (!mop.isReg())
       continue;
     unsigned Reg = mop.getReg();
-    unsigned RegI = Reg;
     if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg))
       continue;
     if (Reg != li.reg)
@@ -1140,26 +1139,8 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
     //
     // Keep track of whether we replace a use and/or def so that we can
     // create the spill interval with the appropriate range. 
-
-    HasUse = mop.isUse();
-    HasDef = mop.isDef();
     SmallVector<unsigned, 2> Ops;
-    Ops.push_back(i);
-    for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) {
-      const MachineOperand &MOj = MI->getOperand(j);
-      if (!MOj.isReg())
-        continue;
-      unsigned RegJ = MOj.getReg();
-      if (RegJ == 0 || TargetRegisterInfo::isPhysicalRegister(RegJ))
-        continue;
-      if (RegJ == RegI) {
-        Ops.push_back(j);
-        if (!MOj.isUndef()) {
-          HasUse |= MOj.isUse();
-          HasDef |= MOj.isDef();
-        }
-      }
-    }
+    tie(HasUse, HasDef) = MI->readsWritesVirtualRegister(Reg, &Ops);
 
     // Create a new virtual register for the spill interval.
     // Create the new register now so we can map the fold instruction
@@ -1312,10 +1293,7 @@ namespace {
   struct RewriteInfo {
     SlotIndex Index;
     MachineInstr *MI;
-    bool HasUse;
-    bool HasDef;
-    RewriteInfo(SlotIndex i, MachineInstr *mi, bool u, bool d)
-      : Index(i), MI(mi), HasUse(u), HasDef(d) {}
+    RewriteInfo(SlotIndex i, MachineInstr *mi) : Index(i), MI(mi) {}
   };
 
   struct RewriteInfoCompare {
@@ -1394,7 +1372,7 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
       // easily see a situation where both registers are reloaded before
       // the INSERT_SUBREG and both target registers that would overlap.
       continue;
-    RewriteMIs.push_back(RewriteInfo(index, MI, O.isUse(), O.isDef()));
+    RewriteMIs.push_back(RewriteInfo(index, MI));
   }
   std::sort(RewriteMIs.begin(), RewriteMIs.end(), RewriteInfoCompare());
 
@@ -1404,18 +1382,11 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
     RewriteInfo &rwi = RewriteMIs[i];
     ++i;
     SlotIndex index = rwi.Index;
-    bool MIHasUse = rwi.HasUse;
-    bool MIHasDef = rwi.HasDef;
     MachineInstr *MI = rwi.MI;
     // If MI def and/or use the same register multiple times, then there
     // are multiple entries.
-    unsigned NumUses = MIHasUse;
     while (i != e && RewriteMIs[i].MI == MI) {
       assert(RewriteMIs[i].Index == index);
-      bool isUse = RewriteMIs[i].HasUse;
-      if (isUse) ++NumUses;
-      MIHasUse |= isUse;
-      MIHasDef |= RewriteMIs[i].HasDef;
       ++i;
     }
     MachineBasicBlock *MBB = MI->getParent();
@@ -1440,7 +1411,8 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
         //     = use
         // It's better to start a new interval to avoid artifically
         // extend the new interval.
-        if (MIHasDef && !MIHasUse) {
+        if (MI->readsWritesVirtualRegister(li.reg) ==
+            std::make_pair(false,true)) {
           MBBVRegsMap.erase(MBB->getNumber());
           ThisVReg = 0;
         }
@@ -1674,19 +1646,9 @@ addIntervalsForSpillsFast(const LiveInterval &li,
     MachineInstr* MI = &*RI;
     
     SmallVector<unsigned, 2> Indices;
-    bool HasUse = false;
-    bool HasDef = false;
-    
-    for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
-      MachineOperand& mop = MI->getOperand(i);
-      if (!mop.isReg() || mop.getReg() != li.reg) continue;
-      
-      HasUse |= MI->getOperand(i).isUse();
-      HasDef |= MI->getOperand(i).isDef();
-      
-      Indices.push_back(i);
-    }
-    
+    bool HasUse, HasDef;
+    tie(HasUse, HasDef) = MI->readsWritesVirtualRegister(li.reg, &Indices);
+
     if (!tryFoldMemoryOperand(MI, vrm, NULL, getInstructionIndex(MI),
                               Indices, true, slot, li.reg)) {
       unsigned NewVReg = mri_->createVirtualRegister(rc);
index 595fddda6f602bfb9a3175b81b46fbb94cd04528..319059b4bbfcf3e88c129c68e3a42bb48c1ae2e0 100644 (file)
@@ -782,27 +782,31 @@ int MachineInstr::findRegisterUseOperandIdx(unsigned Reg, bool isKill,
   return -1;
 }
 
-/// readsVirtualRegister - Return true if the MachineInstr reads the specified
-/// virtual register. Take into account that a partial define is a
-/// read-modify-write operation.
-bool MachineInstr::readsVirtualRegister(unsigned Reg) const {
-  bool PartDef = false; // Partial redefine
-  bool FullDef = false; // Full define
+/// readsWritesVirtualRegister - Return a pair of bools (reads, writes)
+/// indicating if this instruction reads or writes Reg. This also considers
+/// partial defines.
+std::pair<bool,bool>
+MachineInstr::readsWritesVirtualRegister(unsigned Reg,
+                                         SmallVectorImpl<unsigned> *Ops) const {
+  bool PartDef = false; // Partial redefine.
+  bool FullDef = false; // Full define.
+  bool Use = false;
 
   for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = getOperand(i);
     if (!MO.isReg() || MO.getReg() != Reg)
       continue;
+    if (Ops)
+      Ops->push_back(i);
     if (MO.isUse())
-      return true;
-    if (MO.getSubReg())
+      Use |= !MO.isUndef();
+    else if (MO.getSubReg())
       PartDef = true;
     else
       FullDef = true;
   }
-  // A partial register definition causes a read unless the full register is
-  // also defined.
-  return PartDef && !FullDef;
+  // A partial redefine uses Reg unless there is also a full define.
+  return std::make_pair(Use || (PartDef && !FullDef), PartDef || FullDef);
 }
 
 /// findRegisterDefOperandIdx() - Returns the operand index that is a def of