RegAllocGreedy: Allow target to specify register class ordering.
authorMatthias Braun <matze@braunis.de>
Tue, 31 Mar 2015 19:57:53 +0000 (19:57 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 31 Mar 2015 19:57:53 +0000 (19:57 +0000)
Specify an allocation order with a register class. This is used by register
allocators with a greedy heuristic. This is usefull as it is sometimes
beneficial to color more constrained classes first.

Differential Revision: http://reviews.llvm.org/D8626

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

include/llvm/Target/Target.td
include/llvm/Target/TargetRegisterInfo.h
lib/CodeGen/RegAllocGreedy.cpp
utils/TableGen/CodeGenRegisters.cpp
utils/TableGen/CodeGenRegisters.h
utils/TableGen/RegisterInfoEmitter.cpp

index f854225fe88644b9c17083c570a311d576bc7103..d7356293a0f18d1e30f51211f0b2882caf07b75a 100644 (file)
@@ -207,6 +207,12 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
   // The function should return 0 to select the default order defined by
   // MemberList, 1 to select the first AltOrders entry and so on.
   code AltOrderSelect = [{}];
+
+  // Specify allocation priority for register allocators using a greedy
+  // heuristic. Classes with high priority are assigned first. It is sometimes
+  // beneficial to assign registers to highly constrained classes first.
+  // The priority has to be in the range [0,63].
+  int AllocationPriority = 0;
 }
 
 // The memberList in a RegisterClass is a dag of set operations. TableGen
index 418405299659c49937697b310b9dba85c4847df8..7752203b98b868d3baeb0afd1766e8b290d78eaf 100644 (file)
@@ -46,6 +46,9 @@ public:
   const uint32_t *SubClassMask;
   const uint16_t *SuperRegIndices;
   const unsigned LaneMask;
+  /// Classes with high priority should be assigned first by register allocators
+  /// with a greedy heuristic. The priority is a value in the range [0,63].
+  const uint8_t AllocationPriority;
   /// Whether the class supports two (or more) disjunct subregister indices.
   const bool HasDisjunctSubRegs;
   const sc_iterator SuperClasses;
index f30b6d803697ccfe46d3ffad084340d206aca417..26f42c93323ad1190dbb0a15e46f78a8acb10a5e 100644 (file)
@@ -538,8 +538,9 @@ void RAGreedy::enqueue(PQueue &CurQueue, LiveInterval *LI) {
     // Giant live ranges fall back to the global assignment heuristic, which
     // prevents excessive spilling in pathological cases.
     bool ReverseLocal = TRI->reverseLocalAssignment();
+    const TargetRegisterClass &RC = *MRI->getRegClass(Reg);
     bool ForceGlobal = !ReverseLocal &&
-      (Size / SlotIndex::InstrDist) > (2 * MRI->getRegClass(Reg)->getNumRegs());
+      (Size / SlotIndex::InstrDist) > (2 * RC.getNumRegs());
 
     if (ExtraRegInfo[Reg].Stage == RS_Assign && !ForceGlobal && !LI->empty() &&
         LIS->intervalIsInOneMBB(*LI)) {
@@ -554,8 +555,8 @@ void RAGreedy::enqueue(PQueue &CurQueue, LiveInterval *LI) {
         // large blocks on targets with many physical registers.
         Prio = Indexes->getZeroIndex().getInstrDistance(LI->endIndex());
       }
-    }
-    else {
+      Prio |= RC.AllocationPriority << 24;
+    else {
       // Allocate global and split ranges in long->short order. Long ranges that
       // don't fit should be spilled (or split) ASAP so they don't create
       // interference.  Mark a bit to prioritize global above local ranges.
index 68c27167610d0d2d6de8c2d97cc5147c5cc8bee4..7179611f01274dfbb3b2e9fc34a471fb70be6167 100644 (file)
@@ -711,6 +711,10 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
   CopyCost = R->getValueAsInt("CopyCost");
   Allocatable = R->getValueAsBit("isAllocatable");
   AltOrderSelect = R->getValueAsString("AltOrderSelect");
+  int AllocationPriority = R->getValueAsInt("AllocationPriority");
+  if (AllocationPriority < 0 || AllocationPriority > 63)
+    PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,63]");
+  this->AllocationPriority = AllocationPriority;
 }
 
 // Create an inferred register class that was missing from the .td files.
index 00e2957edc6ae4f4df1453dcfae39cfa5fa6e5ec..dc441436537db399cfb1d4f1d3a5501106f86277 100644 (file)
@@ -306,6 +306,7 @@ namespace llvm {
     int CopyCost;
     bool Allocatable;
     std::string AltOrderSelect;
+    uint8_t AllocationPriority;
     /// Contains the combination of the lane masks of all subregisters.
     unsigned LaneMask;
     /// True if there are at least 2 subregisters which do not interfere.
index 17bee6e76664005b2d6a5735a2585f8a514c9ebb..4704232f78cfa165ae6e2cd3037b1ae45e70ae8b 100644 (file)
@@ -1287,6 +1287,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
          << "SubClassMask,\n    SuperRegIdxSeqs + "
          << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n    "
          << format("0x%08x,\n    ", RC.LaneMask)
+         << (unsigned)RC.AllocationPriority << ",\n    "
          << (RC.HasDisjunctSubRegs?"true":"false")
          << ", /* HasDisjunctSubRegs */\n    ";
       if (RC.getSuperClasses().empty())