Part 1.
- Change register allocation hint to a pair of unsigned integers. The hint type is zero (which means prefer the register specified as second part of the pair) or entirely target dependent.
- Allow targets to specify alternative register allocation orders based on allocation hint.

Part 2.
- Use the register allocation hint system to implement more aggressive load / store multiple formation.
- Aggressively form LDRD / STRD. These are formed *before* register allocation. It has to be done this way to shorten live interval of base and offset registers. e.g.
v1025 = LDR v1024, 0
v1026 = LDR v1024, 0
=>
v1025,v1026 = LDRD v1024, 0

If this transformation isn't done before allocation, v1024 will overlap v1025 which means it more difficult to allocate a register pair.

- Even with the register allocation hint, it may not be possible to get the desired allocation. In that case, the post-allocation load / store multiple pass must fix the ldrd / strd instructions. They can either become ldm / stm instructions or back to a pair of ldr / str instructions.

This is work in progress, not yet enabled.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73381 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
index 97926dd..4d3ce3a 100644
--- a/lib/CodeGen/LiveInterval.cpp
+++ b/lib/CodeGen/LiveInterval.cpp
@@ -507,12 +507,11 @@
   // Update regalloc hint if currently there isn't one.
   if (TargetRegisterInfo::isVirtualRegister(reg) &&
       TargetRegisterInfo::isVirtualRegister(Other.reg)) {
-    std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> Hint =
-      MRI->getRegAllocationHint(reg);
-    if (Hint.first == MachineRegisterInfo::RA_None) {
-      std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> OtherHint =
+    std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(reg);
+    if (Hint.first == 0 && Hint.second == 0) {
+      std::pair<unsigned, unsigned> OtherHint =
         MRI->getRegAllocationHint(Other.reg);
-      if (OtherHint.first != MachineRegisterInfo::RA_None)
+      if (OtherHint.first || OtherHint.second)
         MRI->setRegAllocationHint(reg, OtherHint.first, OtherHint.second);
     }
   }
@@ -772,8 +771,7 @@
                         BumpPtrAllocator &VNInfoAllocator) {
   ranges.clear();
   valnos.clear();
-  std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> Hint =
-    MRI->getRegAllocationHint(RHS.reg);
+  std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(RHS.reg);
   MRI->setRegAllocationHint(reg, Hint.first, Hint.second);
 
   weight = RHS.weight;
diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp
index 9649c4c..544d83a 100644
--- a/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/lib/CodeGen/MachineRegisterInfo.cpp
@@ -65,7 +65,7 @@
   // Add a reg, but keep track of whether the vector reallocated or not.
   void *ArrayBase = VRegInfo.empty() ? 0 : &VRegInfo[0];
   VRegInfo.push_back(std::make_pair(RegClass, (MachineOperand*)0));
-  RegAllocHints.push_back(std::make_pair(RA_None, 0));
+  RegAllocHints.push_back(std::make_pair(0, 0));
 
   if (!((&VRegInfo[0] == ArrayBase || VRegInfo.size() == 1)))
     // The vector reallocated, handle this now.
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index 3c445e7..ec956c2 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -281,7 +281,8 @@
     /// getFreePhysReg - return a free physical register for this virtual
     /// register interval if we have one, otherwise return 0.
     unsigned getFreePhysReg(LiveInterval* cur);
-    unsigned getFreePhysReg(const TargetRegisterClass *RC,
+    unsigned getFreePhysReg(LiveInterval* cur,
+                            const TargetRegisterClass *RC,
                             unsigned MaxInactiveCount,
                             SmallVector<unsigned, 256> &inactiveCounts,
                             bool SkipDGRegs);
@@ -936,8 +937,7 @@
           if (DstSubReg)
             Reg = tri_->getMatchingSuperReg(Reg, DstSubReg, RC);
           if (Reg && allocatableRegs_[Reg] && RC->contains(Reg))
-            mri_->setRegAllocationHint(cur->reg,
-                                       MachineRegisterInfo::RA_Preference, Reg);
+            mri_->setRegAllocationHint(cur->reg, 0, Reg);
         }
       }
     }
@@ -1046,8 +1046,7 @@
     if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) {
       // "Downgrade" physReg to try to keep physReg from being allocated until
       // the next reload from the same SS is allocated. 
-      mri_->setRegAllocationHint(NextReloadLI->reg,
-                                 MachineRegisterInfo::RA_Preference, physReg);
+      mri_->setRegAllocationHint(NextReloadLI->reg, 0, physReg);
       DowngradeRegister(cur, physReg);
     }
     return;
@@ -1293,7 +1292,7 @@
       // It interval has a preference, it must be defined by a copy. Clear the
       // preference now since the source interval allocation may have been
       // undone as well.
-      mri_->setRegAllocationHint(i->reg, MachineRegisterInfo::RA_None, 0);
+      mri_->setRegAllocationHint(i->reg, 0, 0);
     else {
       UpgradeRegister(ii->second);
     }
@@ -1349,15 +1348,17 @@
   }
 }
 
-unsigned RALinScan::getFreePhysReg(const TargetRegisterClass *RC,
+unsigned RALinScan::getFreePhysReg(LiveInterval* cur,
+                                   const TargetRegisterClass *RC,
                                    unsigned MaxInactiveCount,
                                    SmallVector<unsigned, 256> &inactiveCounts,
                                    bool SkipDGRegs) {
   unsigned FreeReg = 0;
   unsigned FreeRegInactiveCount = 0;
 
-  TargetRegisterClass::iterator I = RC->allocation_order_begin(*mf_);
-  TargetRegisterClass::iterator E = RC->allocation_order_end(*mf_);
+  TargetRegisterClass::iterator I, E;
+  tie(I, E) = tri_->getAllocationOrder(RC,
+                                    mri_->getRegAllocationHint(cur->reg), *mf_);
   assert(I != E && "No allocatable register in this register class!");
 
   // Scan for the first available register.
@@ -1380,7 +1381,7 @@
   // return this register.
   if (FreeReg == 0 || FreeRegInactiveCount == MaxInactiveCount)
     return FreeReg;
-  
+ 
   // Continue scanning the registers, looking for the one with the highest
   // inactive count.  Alkis found that this reduced register pressure very
   // slightly on X86 (in rev 1.94 of this file), though this should probably be
@@ -1440,12 +1441,12 @@
   }
 
   if (!DowngradedRegs.empty()) {
-    unsigned FreeReg = getFreePhysReg(RC, MaxInactiveCount, inactiveCounts,
+    unsigned FreeReg = getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts,
                                       true);
     if (FreeReg)
       return FreeReg;
   }
-  return getFreePhysReg(RC, MaxInactiveCount, inactiveCounts, false);
+  return getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, false);
 }
 
 FunctionPass* llvm::createLinearScanRegisterAllocator() {
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index 95e5aca..7d9170a 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -1272,26 +1272,8 @@
                                       const TargetRegisterInfo *TRI) {
   if (TargetRegisterInfo::isPhysicalRegister(Reg))
     return 0;
-
-  std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> Hint =
-    MRI->getRegAllocationHint(Reg);
-  switch (Hint.first) {
-  default: assert(0);
-  case MachineRegisterInfo::RA_None:
-    return 0;
-  case MachineRegisterInfo::RA_Preference:
-    return Hint.second;
-  case MachineRegisterInfo::RA_PairEven:
-    if (TargetRegisterInfo::isPhysicalRegister(Hint.second))
-      return TRI->getRegisterPairOdd(MF, Hint.second);
-    return Hint.second;
-  case MachineRegisterInfo::RA_PairOdd:
-    if (TargetRegisterInfo::isPhysicalRegister(Hint.second))
-      return TRI->getRegisterPairEven(MF, Hint.second);
-    return Hint.second;
-  }
-  // Shouldn't reach here.
-  return 0;
+  std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
+  return TRI->ResolveRegAllocHint(Hint.first, Hint.second, MF);
 }
 
 /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
@@ -1595,8 +1577,7 @@
       if (PhysJoinTweak) {
         if (SrcIsPhys) {
           if (!isWinToJoinVRWithSrcPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) {
-            mri_->setRegAllocationHint(DstInt.reg,
-                                    MachineRegisterInfo::RA_Preference, SrcReg);
+            mri_->setRegAllocationHint(DstInt.reg, 0, SrcReg);
             ++numAborts;
             DOUT << "\tMay tie down a physical register, abort!\n";
             Again = true;  // May be possible to coalesce later.
@@ -1604,8 +1585,7 @@
           }
         } else {
           if (!isWinToJoinVRWithDstPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) {
-            mri_->setRegAllocationHint(SrcInt.reg,
-                                    MachineRegisterInfo::RA_Preference, DstReg);
+            mri_->setRegAllocationHint(SrcInt.reg, 0, DstReg);
             ++numAborts;
             DOUT << "\tMay tie down a physical register, abort!\n";
             Again = true;  // May be possible to coalesce later.
@@ -1629,8 +1609,7 @@
         if (Length > Threshold &&
             (((float)std::distance(mri_->use_begin(JoinVReg),
                                    mri_->use_end()) / Length) < Ratio)) {
-          mri_->setRegAllocationHint(JoinVInt.reg,
-                                  MachineRegisterInfo::RA_Preference, JoinPReg);
+          mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg);
           ++numAborts;
           DOUT << "\tMay tie down a physical register, abort!\n";
           Again = true;  // May be possible to coalesce later.
@@ -1815,8 +1794,7 @@
       TargetRegisterInfo::isVirtualRegister(ResDstInt->reg)) {
     const TargetRegisterClass *RC = mri_->getRegClass(ResDstInt->reg);
     if (!RC->contains(Preference))
-      mri_->setRegAllocationHint(ResDstInt->reg,
-                                 MachineRegisterInfo::RA_None, 0);
+      mri_->setRegAllocationHint(ResDstInt->reg, 0, 0);
   }
 
   DOUT << "\n\t\tJoined.  Result = "; ResDstInt->print(DOUT, tri_);
@@ -2067,12 +2045,9 @@
   // Update regalloc hint if both are virtual registers.
   if (TargetRegisterInfo::isVirtualRegister(LHS.reg) && 
       TargetRegisterInfo::isVirtualRegister(RHS.reg)) {
-    std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> RHSPref =
-      mri_->getRegAllocationHint(RHS.reg);
-    std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> LHSPref =
-      mri_->getRegAllocationHint(LHS.reg);
-    if (RHSPref.first != MachineRegisterInfo::RA_None &&
-        LHSPref.first == MachineRegisterInfo::RA_None)
+    std::pair<unsigned, unsigned> RHSPref = mri_->getRegAllocationHint(RHS.reg);
+    std::pair<unsigned, unsigned> LHSPref = mri_->getRegAllocationHint(LHS.reg);
+    if (RHSPref != LHSPref)
       mri_->setRegAllocationHint(LHS.reg, RHSPref.first, RHSPref.second);
   }
 
@@ -2846,8 +2821,8 @@
       }
 
       // Slightly prefer live interval that has been assigned a preferred reg.
-      if (mri_->getRegAllocationHint(LI.reg).first !=
-          MachineRegisterInfo::RA_None)
+      std::pair<unsigned, unsigned> Hint = mri_->getRegAllocationHint(LI.reg);
+      if (Hint.first || Hint.second)
         LI.weight *= 1.01F;
 
       // Divide the weight of the interval by its size.  This encourages 
diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index 87d75dd..4d3417f 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/lib/CodeGen/VirtRegMap.cpp
@@ -100,36 +100,15 @@
 }
 
 unsigned VirtRegMap::getRegAllocPref(unsigned virtReg) {
-  std::pair<MachineRegisterInfo::RegAllocHintType, unsigned> Hint =
-    MRI->getRegAllocationHint(virtReg);
-  switch (Hint.first) {
-  default: assert(0);
-  case MachineRegisterInfo::RA_None:
-    return 0;
-  case MachineRegisterInfo::RA_Preference:
-    if (TargetRegisterInfo::isPhysicalRegister(Hint.second))
-      return Hint.second;
-    if (hasPhys(Hint.second))
-      return getPhys(Hint.second);
-  case MachineRegisterInfo::RA_PairEven: {
-    unsigned physReg = Hint.second;
-    if (TargetRegisterInfo::isPhysicalRegister(physReg))
-      return TRI->getRegisterPairEven(*MF, physReg);
-    else if (hasPhys(physReg))
-      return TRI->getRegisterPairEven(*MF, getPhys(physReg));
-    return 0;
-  }
-  case MachineRegisterInfo::RA_PairOdd: {
-    unsigned physReg = Hint.second;
-    if (TargetRegisterInfo::isPhysicalRegister(physReg))
-      return TRI->getRegisterPairOdd(*MF, physReg);
-    else if (hasPhys(physReg))
-      return TRI->getRegisterPairOdd(*MF, getPhys(physReg));
-    return 0;
-  }
-  }
-  // Shouldn't reach here.
-  return 0;
+  std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(virtReg);
+  unsigned physReg = Hint.second;
+  if (physReg &&
+      TargetRegisterInfo::isVirtualRegister(physReg) && hasPhys(physReg))
+    physReg = getPhys(physReg);
+  if (Hint.first == 0)
+    return (physReg && TargetRegisterInfo::isPhysicalRegister(physReg))
+      ? physReg : 0;
+  return TRI->ResolveRegAllocHint(Hint.first, physReg, *MF);
 }
 
 int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) {