Index: llvm/trunk/include/llvm/Target/Target.td =================================================================== --- llvm/trunk/include/llvm/Target/Target.td +++ llvm/trunk/include/llvm/Target/Target.td @@ -207,6 +207,12 @@ // 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: llvm/trunk/include/llvm/Target/TargetRegisterInfo.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetRegisterInfo.h +++ llvm/trunk/include/llvm/Target/TargetRegisterInfo.h @@ -46,6 +46,9 @@ 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: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp =================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp @@ -538,8 +538,9 @@ // 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 @@ // 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: llvm/trunk/utils/TableGen/CodeGenRegisters.h =================================================================== --- llvm/trunk/utils/TableGen/CodeGenRegisters.h +++ llvm/trunk/utils/TableGen/CodeGenRegisters.h @@ -306,6 +306,7 @@ 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: llvm/trunk/utils/TableGen/CodeGenRegisters.cpp =================================================================== --- llvm/trunk/utils/TableGen/CodeGenRegisters.cpp +++ llvm/trunk/utils/TableGen/CodeGenRegisters.cpp @@ -711,6 +711,10 @@ 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: llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp +++ llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp @@ -1287,6 +1287,7 @@ << "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())