From 8e4eaabdb82c99ffe72b2a4ed5322f3a22944606 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Tue, 31 Mar 2015 19:57:53 +0000 Subject: [PATCH] RegAllocGreedy: Allow target to specify register class ordering. 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 | 6 ++++++ include/llvm/Target/TargetRegisterInfo.h | 3 +++ lib/CodeGen/RegAllocGreedy.cpp | 7 ++++--- utils/TableGen/CodeGenRegisters.cpp | 4 ++++ utils/TableGen/CodeGenRegisters.h | 1 + utils/TableGen/RegisterInfoEmitter.cpp | 1 + 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index f854225fe88..d7356293a0f 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -207,6 +207,12 @@ class RegisterClass 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 diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 41840529965..7752203b98b 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -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; diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index f30b6d80369..26f42c93323 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -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. diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 68c27167610..7179611f012 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -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. diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 00e2957edc6..dc441436537 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -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. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 17bee6e7666..4704232f78c 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -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())