PR 770 - permit coallescing of registers in subset register classes.
authorEvan Cheng <evan.cheng@apple.com>
Tue, 9 May 2006 06:37:48 +0000 (06:37 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 9 May 2006 06:37:48 +0000 (06:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28197 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 0ae4b5ad0f25762bd9d40f807d6651f2eedb89a6..f01608c176ccd2b8537a1905b88ebe21bd1bc2aa 100644 (file)
@@ -167,9 +167,11 @@ namespace llvm {
                                    unsigned SrcReg, unsigned DestReg,
                                    bool isLiveIn = false);
 
-    /// Return true if the two specified registers belong to different
-    /// register classes.  The registers may be either phys or virt regs.
-    bool differingRegisterClasses(unsigned RegA, unsigned RegB) const;
+    /// Return true if the two specified registers belong to the same or
+    /// compatible register classes.  The registers may be either phys or
+    /// virt regs.
+    bool compatibleRegisterClasses(unsigned RegA, unsigned RegB,
+                                   bool &Swap) const;
 
     bool AdjustIfAllOverlappingRangesAreCopiesFrom(LiveInterval &IntA,
                                                    LiveInterval &IntB,
index 17144f55822d5421246c12aaccc4b3ee88f2ca3b..946d80de6b4c074d47b11bcaf4d6210fb130f4dc 100644 (file)
@@ -705,9 +705,12 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
           MRegisterInfo::isPhysicalRegister(DestReg))
         continue;
 
-      // If they are not of the same register class, we cannot join them.
-      if (differingRegisterClasses(SrcReg, DestReg))
+      // If they are not of compatible register classes, we cannot join them.
+      bool Swap = false;
+      if (!compatibleRegisterClasses(SrcReg, DestReg, Swap)) {
+        DEBUG(std::cerr << "Register classes aren't compatible!\n");
         continue;
+      }
 
       LiveInterval &SrcInt = getInterval(SrcReg);
       LiveInterval &DestInt = getInterval(DestReg);
@@ -741,7 +744,7 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
         DestInt.join(SrcInt, MIDefIdx);
         DEBUG(std::cerr << "Joined.  Result = " << DestInt << "\n");
 
-        if (!MRegisterInfo::isPhysicalRegister(SrcReg)) {
+        if (!Swap && !MRegisterInfo::isPhysicalRegister(SrcReg)) {
           r2iMap_.erase(SrcReg);
           r2rMap_[SrcReg] = DestReg;
         } else {
@@ -803,24 +806,33 @@ void LiveIntervals::joinIntervals() {
              std::cerr << "  reg " << i << " -> reg " << r2rMap_[i] << "\n");
 }
 
-/// Return true if the two specified registers belong to different register
-/// classes.  The registers may be either phys or virt regs.
-bool LiveIntervals::differingRegisterClasses(unsigned RegA,
-                                             unsigned RegB) const {
+/// Return true if the two specified registers belong to same or compatible
+/// register classes. The registers may be either phys or virt regs.
+bool LiveIntervals::compatibleRegisterClasses(unsigned RegA, unsigned RegB,
+                                                 bool &Swap) const {
 
   // Get the register classes for the first reg.
   if (MRegisterInfo::isPhysicalRegister(RegA)) {
     assert(MRegisterInfo::isVirtualRegister(RegB) &&
            "Shouldn't consider two physregs!");
-    return !mf_->getSSARegMap()->getRegClass(RegB)->contains(RegA);
+    return mf_->getSSARegMap()->getRegClass(RegB)->contains(RegA);
   }
 
   // Compare against the regclass for the second reg.
-  const TargetRegisterClass *RegClass = mf_->getSSARegMap()->getRegClass(RegA);
-  if (MRegisterInfo::isVirtualRegister(RegB))
-    return RegClass != mf_->getSSARegMap()->getRegClass(RegB);
-  else
-    return !RegClass->contains(RegB);
+  const TargetRegisterClass *RegClassA = mf_->getSSARegMap()->getRegClass(RegA);
+  if (MRegisterInfo::isVirtualRegister(RegB)) {
+    const TargetRegisterClass *RegClassB=mf_->getSSARegMap()->getRegClass(RegB);
+    if (RegClassA == RegClassB)
+      return true;
+    else {
+      if (RegClassB->hasSubRegClass(RegClassA)) {
+        Swap = true;
+        return true;
+      }
+      return RegClassA->hasSubRegClass(RegClassB);
+    }
+  } else
+    return RegClassA->contains(RegB);
 }
 
 bool LiveIntervals::overlapsAliases(const LiveInterval *LHS,