1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
//===- RegisterClassInfo.cpp - Dynamic Register Class Info ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the RegisterClassInfo class which provides dynamic
// information about target register classes. Callee-saved vs. caller-saved and
// reserved registers depend on calling conventions and other dynamic
// information, so some things cannot be determined statically.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
using namespace llvm;
#define DEBUG_TYPE "regalloc"
static cl::opt<unsigned>
StressRA("stress-regalloc", cl::Hidden, cl::init(0), cl::value_desc("N"),
cl::desc("Limit all regclasses to N registers"));
RegisterClassInfo::RegisterClassInfo() = default;
void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf) {
bool Update = false;
MF = &mf;
auto &STI = MF->getSubtarget();
// Allocate new array the first time we see a new target.
if (STI.getRegisterInfo() != TRI) {
TRI = STI.getRegisterInfo();
RegClass.reset(new RCInfo[TRI->getNumRegClasses()]);
Update = true;
}
// Does this MF have different CSRs?
assert(TRI && "no register info set");
// Get the callee saved registers.
const MCPhysReg *CSR = MF->getRegInfo().getCalleeSavedRegs();
if (Update || CSR != CalleeSavedRegs) {
// Build a CSRAlias map. Every CSR alias saves the last
// overlapping CSR.
CalleeSavedAliases.assign(TRI->getNumRegs(), 0);
for (const MCPhysReg *I = CSR; *I; ++I)
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI)
CalleeSavedAliases[*AI] = *I;
Update = true;
}
CalleeSavedRegs = CSR;
// Even if CSR list is same, we could have had a different allocation order
// if ignoreCSRForAllocationOrder is evaluated differently.
BitVector CSRHintsForAllocOrder(TRI->getNumRegs());
for (const MCPhysReg *I = CSR; *I; ++I)
for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI)
CSRHintsForAllocOrder[*AI] = STI.ignoreCSRForAllocationOrder(mf, *AI);
if (IgnoreCSRForAllocOrder.size() != CSRHintsForAllocOrder.size() ||
IgnoreCSRForAllocOrder != CSRHintsForAllocOrder) {
Update = true;
IgnoreCSRForAllocOrder = CSRHintsForAllocOrder;
}
RegCosts = TRI->getRegisterCosts(*MF);
// Different reserved registers?
const BitVector &RR = MF->getRegInfo().getReservedRegs();
if (Reserved.size() != RR.size() || RR != Reserved) {
Update = true;
Reserved = RR;
}
// Invalidate cached information from previous function.
if (Update) {
unsigned NumPSets = TRI->getNumRegPressureSets();
PSetLimits.reset(new unsigned[NumPSets]);
std::fill(&PSetLimits[0], &PSetLimits[NumPSets], 0);
++Tag;
}
}
/// compute - Compute the preferred allocation order for RC with reserved
/// registers filtered out. Volatile registers come first followed by CSR
/// aliases ordered according to the CSR order specified by the target.
void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
assert(RC && "no register class given");
RCInfo &RCI = RegClass[RC->getID()];
auto &STI = MF->getSubtarget();
// Raw register count, including all reserved regs.
unsigned NumRegs = RC->getNumRegs();
if (!RCI.Order)
RCI.Order.reset(new MCPhysReg[NumRegs]);
unsigned N = 0;
SmallVector<MCPhysReg, 16> CSRAlias;
uint8_t MinCost = uint8_t(~0u);
uint8_t LastCost = uint8_t(~0u);
unsigned LastCostChange = 0;
// FIXME: Once targets reserve registers instead of removing them from the
// allocation order, we can simply use begin/end here.
ArrayRef<MCPhysReg> RawOrder = RC->getRawAllocationOrder(*MF);
for (unsigned PhysReg : RawOrder) {
// Remove reserved registers from the allocation order.
if (Reserved.test(PhysReg))
continue;
uint8_t Cost = RegCosts[PhysReg];
MinCost = std::min(MinCost, Cost);
if (CalleeSavedAliases[PhysReg] &&
!STI.ignoreCSRForAllocationOrder(*MF, PhysReg))
// PhysReg aliases a CSR, save it for later.
CSRAlias.push_back(PhysReg);
else {
if (Cost != LastCost)
LastCostChange = N;
RCI.Order[N++] = PhysReg;
LastCost = Cost;
}
}
RCI.NumRegs = N + CSRAlias.size();
assert(RCI.NumRegs <= NumRegs && "Allocation order larger than regclass");
// CSR aliases go after the volatile registers, preserve the target's order.
for (unsigned i = 0, e = CSRAlias.size(); i != e; ++i) {
unsigned PhysReg = CSRAlias[i];
uint8_t Cost = RegCosts[PhysReg];
if (Cost != LastCost)
LastCostChange = N;
RCI.Order[N++] = PhysReg;
LastCost = Cost;
}
// Register allocator stress test. Clip register class to N registers.
if (StressRA && RCI.NumRegs > StressRA)
RCI.NumRegs = StressRA;
// Check if RC is a proper sub-class.
if (const TargetRegisterClass *Super =
TRI->getLargestLegalSuperClass(RC, *MF))
if (Super != RC && getNumAllocatableRegs(Super) > RCI.NumRegs)
RCI.ProperSubClass = true;
RCI.MinCost = MinCost;
RCI.LastCostChange = LastCostChange;
LLVM_DEBUG({
dbgs() << "AllocationOrder(" << TRI->getRegClassName(RC) << ") = [";
for (unsigned I = 0; I != RCI.NumRegs; ++I)
dbgs() << ' ' << printReg(RCI.Order[I], TRI);
dbgs() << (RCI.ProperSubClass ? " ] (sub-class)\n" : " ]\n");
});
// RCI is now up-to-date.
RCI.Tag = Tag;
}
/// This is not accurate because two overlapping register sets may have some
/// nonoverlapping reserved registers. However, computing the allocation order
/// for all register classes would be too expensive.
unsigned RegisterClassInfo::computePSetLimit(unsigned Idx) const {
const TargetRegisterClass *RC = nullptr;
unsigned NumRCUnits = 0;
for (const TargetRegisterClass *C : TRI->regclasses()) {
const int *PSetID = TRI->getRegClassPressureSets(C);
for (; *PSetID != -1; ++PSetID) {
if ((unsigned)*PSetID == Idx)
break;
}
if (*PSetID == -1)
continue;
// Found a register class that counts against this pressure set.
// For efficiency, only compute the set order for the largest set.
unsigned NUnits = TRI->getRegClassWeight(C).WeightLimit;
if (!RC || NUnits > NumRCUnits) {
RC = C;
NumRCUnits = NUnits;
}
}
assert(RC && "Failed to find register class");
compute(RC);
unsigned NAllocatableRegs = getNumAllocatableRegs(RC);
unsigned RegPressureSetLimit = TRI->getRegPressureSetLimit(*MF, Idx);
// If all the regs are reserved, return raw RegPressureSetLimit.
// One example is VRSAVERC in PowerPC.
// Avoid returning zero, getRegPressureSetLimit(Idx) assumes computePSetLimit
// return non-zero value.
if (NAllocatableRegs == 0)
return RegPressureSetLimit;
unsigned NReserved = RC->getNumRegs() - NAllocatableRegs;
return RegPressureSetLimit - TRI->getRegClassWeight(RC).RegWeight * NReserved;
}
|