[llvm-branch-commits] [llvm-branch] r106110 - in /llvm/branches/Apple/Troughton: ./ include/llvm/CodeGen/RegisterCoalescer.h lib/CodeGen/RegisterCoalescer.cpp lib/CodeGen/SimpleRegisterCoalescing.cpp lib/CodeGen/SimpleRegisterCoalescing.h test/CodeGen/Thumb2/2010-06-14-NEONCoalescer.ll

Jakob Stoklund Olesen stoklund at 2pi.dk
Wed Jun 16 09:52:15 PDT 2010


Author: stoklund
Date: Wed Jun 16 11:52:15 2010
New Revision: 106110

URL: http://llvm.org/viewvc/llvm-project?rev=106110&view=rev
Log:
$ svn merge -c 105997 https://llvm.org/svn/llvm-project/llvm/trunk
--- Merging r105997 into '.':
A    test/CodeGen/Thumb2/2010-06-14-NEONCoalescer.ll
U    include/llvm/CodeGen/RegisterCoalescer.h
U    lib/CodeGen/SimpleRegisterCoalescing.cpp
U    lib/CodeGen/SimpleRegisterCoalescing.h
U    lib/CodeGen/RegisterCoalescer.cpp


Added:
    llvm/branches/Apple/Troughton/test/CodeGen/Thumb2/2010-06-14-NEONCoalescer.ll
      - copied unchanged from r105997, llvm/trunk/test/CodeGen/Thumb2/2010-06-14-NEONCoalescer.ll
Modified:
    llvm/branches/Apple/Troughton/   (props changed)
    llvm/branches/Apple/Troughton/include/llvm/CodeGen/RegisterCoalescer.h
    llvm/branches/Apple/Troughton/lib/CodeGen/RegisterCoalescer.cpp
    llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.cpp
    llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.h

Propchange: llvm/branches/Apple/Troughton/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Jun 16 11:52:15 2010
@@ -1 +1 @@
-/llvm/trunk:105358,105361,105369,105372,105399,105427,105437,105439,105441,105470,105473,105481,105498,105541,105554,105557,105585-105586,105634,105653,105665,105669,105677,105745,105749,105774-105775,105836,105845,105862,105938,105959,105965,105969,105982,105990-105991,105998,106004,106021,106051
+/llvm/trunk:105358,105361,105369,105372,105399,105427,105437,105439,105441,105470,105473,105481,105498,105541,105554,105557,105585-105586,105634,105653,105665,105669,105677,105745,105749,105774-105775,105836,105845,105862,105938,105959,105965,105969,105982,105990-105991,105997-105998,106004,106021,106051

Modified: llvm/branches/Apple/Troughton/include/llvm/CodeGen/RegisterCoalescer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/include/llvm/CodeGen/RegisterCoalescer.h?rev=106110&r1=106109&r2=106110&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/include/llvm/CodeGen/RegisterCoalescer.h (original)
+++ llvm/branches/Apple/Troughton/include/llvm/CodeGen/RegisterCoalescer.h Wed Jun 16 11:52:15 2010
@@ -25,6 +25,9 @@
   class RegallocQuery;
   class AnalysisUsage;
   class MachineInstr;
+  class TargetRegisterInfo;
+  class TargetRegisterClass;
+  class TargetInstrInfo;
 
   /// An abstract interface for register coalescers.  Coalescers must
   /// implement this interface to be part of the coalescer analysis
@@ -141,6 +144,87 @@
       return true;
     }
   };
+
+
+  /// CoalescerPair - A helper class for register coalescers. When deciding if
+  /// two registers can be coalesced, CoalescerPair can determine if a copy
+  /// instruction would become an identity copy after coalescing.
+  class CoalescerPair {
+    const TargetInstrInfo &tii_;
+    const TargetRegisterInfo &tri_;
+
+    /// dstReg_ - The register that will be left after coalescing. It can be a
+    /// virtual or physical register.
+    unsigned dstReg_;
+
+    /// srcReg_ - the virtual register that will be coalesced into dstReg.
+    unsigned srcReg_;
+
+    /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the
+    /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a
+    /// virtual register.
+    unsigned subIdx_;
+
+    /// partial_ - True when the original copy was a partial subregister copy.
+    bool partial_;
+
+    /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy
+    /// instruction.
+    bool flipped_;
+
+    /// newRC_ - The register class of the coalesced register, or NULL if dstReg_
+    /// is a physreg.
+    const TargetRegisterClass *newRC_;
+
+    /// compose - Compose subreg indices a and b, either may be 0.
+    unsigned compose(unsigned, unsigned) const;
+
+    /// isMoveInstr - Return true if MI is a move or subreg instruction.
+    bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst,
+                     unsigned &SrcSub, unsigned &DstSub) const;
+
+  public:
+    CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri)
+      : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0),
+        partial_(false), flipped_(false), newRC_(0) {}
+
+    /// setRegisters - set registers to match the copy instruction MI. Return
+    /// false if MI is not a coalescable copy instruction.
+    bool setRegisters(const MachineInstr*);
+
+    /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible
+    /// because dstReg_ is a physical register, or subIdx_ is set.
+    bool flip();
+
+    /// isCoalescable - Return true if MI is a copy instruction that will become
+    /// an identity copy after coalescing.
+    bool isCoalescable(const MachineInstr*) const;
+
+    /// isPhys - Return true if DstReg is a physical register.
+    bool isPhys() const { return !newRC_; }
+
+    /// isPartial - Return true if the original copy instruction did not copy the
+    /// full register, but was a subreg operation.
+    bool isPartial() const { return partial_; }
+
+    /// isFlipped - Return true when getSrcReg is the register being defined by
+    /// the original copy instruction.
+    bool isFlipped() const { return flipped_; }
+
+    /// getDstReg - Return the register (virtual or physical) that will remain
+    /// after coalescing.
+    unsigned getDstReg() const { return dstReg_; }
+
+    /// getSrcReg - Return the virtual register that will be coalesced away.
+    unsigned getSrcReg() const { return srcReg_; }
+
+    /// getSubIdx - Return the subregister index in DstReg that SrcReg will be
+    /// coalesced into, or 0.
+    unsigned getSubIdx() const { return subIdx_; }
+
+    /// getNewRC - Return the register class of the coalesced register.
+    const TargetRegisterClass *getNewRC() const { return newRC_; }
+  };
 }
 
 // Because of the way .a files work, we must force the SimpleRC

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/RegisterCoalescer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/RegisterCoalescer.cpp?rev=106110&r1=106109&r2=106110&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/RegisterCoalescer.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/RegisterCoalescer.cpp Wed Jun 16 11:52:15 2010
@@ -16,6 +16,8 @@
 #include "llvm/CodeGen/RegisterCoalescer.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
 #include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Pass.h"
 
@@ -33,6 +35,151 @@
 //
 RegisterCoalescer::~RegisterCoalescer() {}
 
+unsigned CoalescerPair::compose(unsigned a, unsigned b) const {
+  if (!a) return b;
+  if (!b) return a;
+  return tri_.composeSubRegIndices(a, b);
+}
+
+bool CoalescerPair::isMoveInstr(const MachineInstr *MI,
+                                unsigned &Src, unsigned &Dst,
+                                unsigned &SrcSub, unsigned &DstSub) const {
+  if (MI->isExtractSubreg()) {
+    Dst = MI->getOperand(0).getReg();
+    DstSub = MI->getOperand(0).getSubReg();
+    Src = MI->getOperand(1).getReg();
+    SrcSub = compose(MI->getOperand(1).getSubReg(), MI->getOperand(2).getImm());
+  } else if (MI->isInsertSubreg() || MI->isSubregToReg()) {
+    Dst = MI->getOperand(0).getReg();
+    DstSub = compose(MI->getOperand(0).getSubReg(), MI->getOperand(3).getImm());
+    Src = MI->getOperand(2).getReg();
+    SrcSub = MI->getOperand(2).getSubReg();
+  } else if (!tii_.isMoveInstr(*MI, Src, Dst, SrcSub, DstSub)) {
+    return false;
+  }
+  return true;
+}
+
+bool CoalescerPair::setRegisters(const MachineInstr *MI) {
+  srcReg_ = dstReg_ = subIdx_ = 0;
+  newRC_ = 0;
+  flipped_ = false;
+
+  unsigned Src, Dst, SrcSub, DstSub;
+  if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub))
+    return false;
+  partial_ = SrcSub || DstSub;
+
+  // If one register is a physreg, it must be Dst.
+  if (TargetRegisterInfo::isPhysicalRegister(Src)) {
+    if (TargetRegisterInfo::isPhysicalRegister(Dst))
+      return false;
+    std::swap(Src, Dst);
+    std::swap(SrcSub, DstSub);
+    flipped_ = true;
+  }
+
+  const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
+
+  if (TargetRegisterInfo::isPhysicalRegister(Dst)) {
+    // Eliminate DstSub on a physreg.
+    if (DstSub) {
+      Dst = tri_.getSubReg(Dst, DstSub);
+      if (!Dst) return false;
+      DstSub = 0;
+    }
+
+    // Eliminate SrcSub by picking a corresponding Dst superregister.
+    if (SrcSub) {
+      Dst = tri_.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src));
+      if (!Dst) return false;
+      SrcSub = 0;
+    } else if (!MRI.getRegClass(Src)->contains(Dst)) {
+      return false;
+    }
+  } else {
+    // Both registers are virtual.
+
+    // Identical sub to sub.
+    if (SrcSub == DstSub)
+      SrcSub = DstSub = 0;
+    else if (SrcSub && DstSub)
+      return false; // FIXME: Qreg:ssub_3 + Dreg:ssub_1 => QReg:dsub_1 + Dreg.
+
+    // There can be no SrcSub.
+    if (SrcSub) {
+      std::swap(Src, Dst);
+      DstSub = SrcSub;
+      SrcSub = 0;
+      assert(!flipped_ && "Unexpected flip");
+      flipped_ = true;
+    }
+
+    // Find the new register class.
+    const TargetRegisterClass *SrcRC = MRI.getRegClass(Src);
+    const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
+    if (DstSub)
+      newRC_ = tri_.getMatchingSuperRegClass(DstRC, SrcRC, DstSub);
+    else
+      newRC_ = getCommonSubClass(DstRC, SrcRC);
+    if (!newRC_)
+      return false;
+  }
+  // Check our invariants
+  assert(TargetRegisterInfo::isVirtualRegister(Src) && "Src must be virtual");
+  assert(!(TargetRegisterInfo::isPhysicalRegister(Dst) && DstSub) &&
+         "Cannot have a physical SubIdx");
+  srcReg_ = Src;
+  dstReg_ = Dst;
+  subIdx_ = DstSub;
+  return true;
+}
+
+bool CoalescerPair::flip() {
+  if (subIdx_ || TargetRegisterInfo::isPhysicalRegister(dstReg_))
+    return false;
+  std::swap(srcReg_, dstReg_);
+  flipped_ = !flipped_;
+  return true;
+}
+
+bool CoalescerPair::isCoalescable(const MachineInstr *MI) const {
+  if (!MI)
+    return false;
+  unsigned Src, Dst, SrcSub, DstSub;
+  if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub))
+    return false;
+
+  // Find the virtual register that is srcReg_.
+  if (Dst == srcReg_) {
+    std::swap(Src, Dst);
+    std::swap(SrcSub, DstSub);
+  } else if (Src != srcReg_) {
+    return false;
+  }
+
+  // Now check that Dst matches dstReg_.
+  if (TargetRegisterInfo::isPhysicalRegister(dstReg_)) {
+    if (!TargetRegisterInfo::isPhysicalRegister(Dst))
+      return false;
+    assert(!subIdx_ && "Inconsistent CoalescerPair state.");
+    // DstSub could be set for a physreg from INSERT_SUBREG.
+    if (DstSub)
+      Dst = tri_.getSubReg(Dst, DstSub);
+    // Full copy of Src.
+    if (!SrcSub)
+      return dstReg_ == Dst;
+    // This is a partial register copy. Check that the parts match.
+    return tri_.getSubReg(dstReg_, SrcSub) == Dst;
+  } else {
+    // dstReg_ is virtual.
+    if (dstReg_ != Dst)
+      return false;
+    // Registers match, do the subregisters line up?
+    return compose(subIdx_, SrcSub) == DstSub;
+  }
+}
+
 // Because of the way .a files work, we must force the SimpleRC
 // implementation to be pulled in if the RegisterCoalescer classes are
 // pulled in.  Otherwise we run the risk of RegisterCoalescer being

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=106110&r1=106109&r2=106110&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.cpp (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.cpp Wed Jun 16 11:52:15 2010
@@ -1395,6 +1395,12 @@
     return false;  // Not coalescable.
   }
 
+  CoalescerPair CP(*tii_, *tri_);
+  if (!CP.setRegisters(CopyMI)) {
+    DEBUG(dbgs() << "\tNot coalescable.\n");
+    return false;
+  }
+
   bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg);
   bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg);
 
@@ -1722,7 +1728,7 @@
       DEBUG(dbgs() << "\tNot profitable!\n");
       return false;
     }
-  } else if (!JoinIntervals(DstInt, SrcInt, Swapped)) {
+  } else if (!JoinIntervals(DstInt, SrcInt, Swapped, CP)) {
     // Coalescing failed.
 
     // If definition of source is defined by trivial computation, try
@@ -1919,33 +1925,13 @@
   return std::find(V.begin(), V.end(), Val) != V.end();
 }
 
-static bool isValNoDefMove(const MachineInstr *MI, unsigned DR, unsigned SR,
-                           const TargetInstrInfo *TII,
-                           const TargetRegisterInfo *TRI) {
-  unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
-  if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx))
-    ;
-  else if (MI->isExtractSubreg()) {
-    DstReg = MI->getOperand(0).getReg();
-    SrcReg = MI->getOperand(1).getReg();
-  } else if (MI->isSubregToReg() ||
-             MI->isInsertSubreg()) {
-    DstReg = MI->getOperand(0).getReg();
-    SrcReg = MI->getOperand(2).getReg();
-  } else
-    return false;
-  return (SrcReg == SR || TRI->isSuperRegister(SR, SrcReg)) &&
-         (DstReg == DR || TRI->isSuperRegister(DR, DstReg));
-}
-
 /// RangeIsDefinedByCopyFromReg - Return true if the specified live range of
 /// the specified live interval is defined by a copy from the specified
 /// register.
-bool SimpleRegisterCoalescing::RangeIsDefinedByCopyFromReg(LiveInterval &li,
-                                                           LiveRange *LR,
-                                                           unsigned Reg) {
-  unsigned SrcReg = li_->getVNInfoSourceReg(LR->valno);
-  if (SrcReg == Reg)
+bool SimpleRegisterCoalescing::RangeIsDefinedByCopy(LiveInterval &li,
+                                                    LiveRange *LR,
+                                                    CoalescerPair &CP) {
+  if (CP.isCoalescable(LR->valno->getCopy()))
     return true;
   // FIXME: Do isPHIDef and isDefAccurate both need to be tested?
   if ((LR->valno->isPHIDef() || !LR->valno->isDefAccurate()) &&
@@ -1954,7 +1940,7 @@
     // It's a sub-register live interval, we may not have precise information.
     // Re-compute it.
     MachineInstr *DefMI = li_->getInstructionFromIndex(LR->start);
-    if (DefMI && isValNoDefMove(DefMI, li.reg, Reg, tii_, tri_)) {
+    if (CP.isCoalescable(DefMI)) {
       // Cache computed info.
       LR->valno->def = LR->start;
       LR->valno->setCopy(DefMI);
@@ -1986,7 +1972,8 @@
 /// value number and that the RHS is not defined by a copy from this
 /// interval.  This returns false if the intervals are not joinable, or it
 /// joins them and returns true.
-bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){
+bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS,
+                                          CoalescerPair &CP) {
   assert(RHS.containsOneValue());
 
   // Some number (potentially more than one) value numbers in the current
@@ -2028,7 +2015,7 @@
         if (LHSIt->valno->hasRedefByEC())
           return false;
         // Copy from the RHS?
-        if (!RangeIsDefinedByCopyFromReg(LHS, LHSIt, RHS.reg))
+        if (!RangeIsDefinedByCopy(LHS, LHSIt, CP))
           return false;    // Nope, bail out.
 
         if (ValueLiveAt(LHSIt, LHS.end(), RHSIt->valno->def))
@@ -2072,7 +2059,7 @@
             return false;
           // Otherwise, if this is a copy from the RHS, mark it as being merged
           // in.
-          if (RangeIsDefinedByCopyFromReg(LHS, LHSIt, RHS.reg)) {
+          if (RangeIsDefinedByCopy(LHS, LHSIt, CP)) {
             if (ValueLiveAt(LHSIt, LHS.end(), RHSIt->valno->def))
               // Here is an interesting situation:
               // BB1:
@@ -2171,7 +2158,7 @@
 /// below to update aliases.
 bool
 SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
-                                        bool &Swapped) {
+                                        bool &Swapped, CoalescerPair &CP) {
   // Compute the final value assignment, assuming that the live ranges can be
   // coalesced.
   SmallVector<int, 16> LHSValNoAssignments;
@@ -2252,7 +2239,7 @@
       // faster checks to see if the live ranges are coalescable.  This joiner
       // can't swap the LHS/RHS intervals though.
       if (!TargetRegisterInfo::isPhysicalRegister(RHS.reg)) {
-        return SimpleJoin(LHS, RHS);
+        return SimpleJoin(LHS, RHS, CP);
       } else {
         RHSValNoInfo = RHSValNoInfo0;
       }
@@ -2318,7 +2305,7 @@
 
       // DstReg is known to be a register in the LHS interval.  If the src is
       // from the RHS interval, we can use its value #.
-      if (li_->getVNInfoSourceReg(VNI) != RHS.reg)
+      if (!CP.isCoalescable(VNI->getCopy()))
         continue;
 
       // Figure out the value # from the RHS.
@@ -2338,7 +2325,7 @@
 
       // DstReg is known to be a register in the RHS interval.  If the src is
       // from the LHS interval, we can use its value #.
-      if (li_->getVNInfoSourceReg(VNI) != LHS.reg)
+      if (!CP.isCoalescable(VNI->getCopy()))
         continue;
 
       // Figure out the value # from the LHS.

Modified: llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.h?rev=106110&r1=106109&r2=106110&view=diff
==============================================================================
--- llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.h (original)
+++ llvm/branches/Apple/Troughton/lib/CodeGen/SimpleRegisterCoalescing.h Wed Jun 16 11:52:15 2010
@@ -111,14 +111,15 @@
     /// physreg, this method always canonicalizes DestInt to be it.  The output
     /// "SrcInt" will not have been modified, so we can use this information
     /// below to update aliases.
-    bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS, bool &Swapped);
+    bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS, bool &Swapped,
+                       CoalescerPair &CP);
     
     /// SimpleJoin - Attempt to join the specified interval into this one. The
     /// caller of this method must guarantee that the RHS only contains a single
     /// value number and that the RHS is not defined by a copy from this
     /// interval.  This returns false if the intervals are not joinable, or it
     /// joins them and returns true.
-    bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS);
+    bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS, CoalescerPair &CP);
     
     /// Return true if the two specified registers belong to different register
     /// classes.  The registers may be either phys or virt regs.
@@ -210,11 +211,10 @@
     bool ValueLiveAt(LiveInterval::iterator LRItr, LiveInterval::iterator LREnd, 
                      SlotIndex defPoint) const;                                  
 
-    /// RangeIsDefinedByCopyFromReg - Return true if the specified live range of
-    /// the specified live interval is defined by a copy from the specified
-    /// register.
-    bool RangeIsDefinedByCopyFromReg(LiveInterval &li, LiveRange *LR,
-                                     unsigned Reg);
+    /// RangeIsDefinedByCopy - Return true if the specified live range of the
+    /// specified live interval is defined by a coalescable copy.
+    bool RangeIsDefinedByCopy(LiveInterval &li, LiveRange *LR,
+                              CoalescerPair &CP);
 
     /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and
     /// update the subregister number if it is not zero. If DstReg is a





More information about the llvm-branch-commits mailing list