3.3.6.4. CodeGen使用的寄存器描述
这部分可视为MC对寄存器信息描述的延伸。MC对寄存器信息的描述也是目标机器所需要的,但MC本身不关心寄存器分配。下面这个函数及其调用的函数将产生一系列重要的数据结构,它们将以C++语言进一步勾画寄存器与寄存器类。这些都将是寄存器分配的算法构成部分。
1122 void
1123 RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
1124 CodeGenRegBank &RegBank){
1125 emitSourceFileHeader("Target Register and Register Classes Information", OS);
1126
1127 OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
1128 OS << "#undef GET_REGINFO_TARGET_DESC\n";
1129
1130 OS << "namespace llvm {\n\n";
1131
1132 // Get access to MCRegisterClass data.
1133 OS << "extern const MCRegisterClass " << Target.getName()
1134 << "MCRegisterClasses[];\n";
1135
1136 // Start out by emitting each of the register classes.
1137 const auto &RegisterClasses = RegBank.getRegClasses();
1138 const auto &SubRegIndices = RegBank.getSubRegIndices();
1139
1140 // Collect all registers belonging to any allocatable class.
1141 std::set<Record*> AllocatableRegs;
1142
1143 // Collect allocatable registers.
1144 for (const auto &RC : RegisterClasses) {
1145 ArrayRef<Record*> Order = RC.getOrder();
1146
1147 if (RC.Allocatable)
1148 AllocatableRegs.insert(Order.begin(), Order.end());
1149 }
1150 <-- v7.0增加
const CodeGenHwModes &CGH = Target.getHwModes();
unsigned NumModes = CGH.getNumModeIds();
1151 // Build a shared array of value types.
1152 SequenceToOffsetTable<SmallVector<MVT::SimpleValueType, 4> > VTSeqs;
for (unsigned M = 0; M < NumModes; ++M) { <-- v7.0增加
1153 for (const auto &RC : RegisterClasses) {
std::vector<MVT::SimpleValueType> S; <-- v7.0增加
for (const ValueTypeByHwMode &VVT : RC.VTs)
S.push_back(VVT.get(M).SimpleTy);
1154 VTSeqs.add(RC.VTs); <-- v7.0删除
VTSeqs.add(S); <-- v7.0增加
}
}
1155 VTSeqs.layout();
1156 OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n";
1157 VTSeqs.emit(OS, printSimpleValueType, "MVT::Other");
1158 OS << "};\n";
1159
1160 // Emit SubRegIndex names, skipping 0.
1161 OS << "\nstatic const char *const SubRegIndexNameTable[] = { \"";
1162
1163 for (const auto &Idx : SubRegIndices) {
1164 OS << Idx.getName();
1165 OS << "\", \"";
1166 }
1167 OS << "\" };\n\n";
1168
1169 // Emit SubRegIndex lane masks, including 0.
1170 OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; <-- v7.0删除
OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " <-- v7.0增加
"LaneBitmask::getAll(),\n";
1171 for (const auto &Idx : SubRegIndices) {
1172 OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n';
1173 }
1174 OS << " };\n\n";
1175
1176 OS << "\n";
1177
1178 // Now that all of the structs have been emitted, emit the instances.
1179 if (!RegisterClasses.empty()) {
OS << "\nstatic const TargetRegisterInfo::RegClassInfo RegClassInfos[]" <-- v7.0增加
<< " = {\n";
for (unsigned M = 0; M < NumModes; ++M) {
unsigned EV = 0;
OS << " // Mode = " << M << " (";
if (M == 0)
OS << "Default";
else
OS << CGH.getMode(M).Name;
OS << ")\n";
for (const auto &RC : RegisterClasses) {
assert(RC.EnumValue == EV++ && "Unexpected order of register classes");
(void)EV;
const RegSizeInfo &RI = RC.RSI.get(M);
OS << " { " << RI.RegSize << ", " << RI.SpillSize << ", "
<< RI.SpillAlignment;
std::vector<MVT::SimpleValueType> VTs;
for (const ValueTypeByHwMode &VVT : RC.VTs)
VTs.push_back(VVT.get(M).SimpleTy);
OS << ", VTLists+" << VTSeqs.get(VTs) << " }, // "
<< RC.getName() << '\n';
}
}
OS << "};\n";
1180 OS << "\nstatic const TargetRegisterClass *const "
1181 << "NullRegClasses[] = { nullptr };\n\n";
1182
1183 // Emit register class bit mask tables. The first bit mask emitted for a
1184 // register class, RC, is the set of sub-classes, including RC itself.
1185 //
1186 // If RC has super-registers, also create a list of subreg indices and bit
1187 // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass,
1188 // SuperRC, that satisfies:
1189 //
1190 // For all SuperReg in SuperRC: SuperReg:Idx in RC
1191 //
1192 // The 0-terminated list of subreg indices starts at:
1193 //
1194 // RC->getSuperRegIndices() = SuperRegIdxSeqs + ...
1195 //
1196 // The corresponding bitmasks follow the sub-class mask in memory. Each
1197 // mask has RCMaskWords uint32_t entries.
1198 //
1199 // Every bit mask present in the list has at least one bit set.
1200
1201 // Compress the sub-reg index lists.
1202 typedef std::vector<const CodeGenSubRegIndex*> IdxList;
1203 SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
1204 SequenceToOffsetTable<IdxList, deref<llvm::less>> SuperRegIdxSeqs;
1205 BitVector MaskBV(RegisterClasses.size());
1206
1207 for (const auto &RC : RegisterClasses) {
1208 OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n ";
1209 printBitVectorAsHex(OS, RC.getSubClasses(), 32);
1210
1211 // Emit super-reg class masks for any relevant SubRegIndices that can
1212 // project into RC.
1213 IdxList &SRIList = SuperRegIdxLists[RC.EnumValue];
1214 for (auto &Idx : SubRegIndices) {
1215 MaskBV.reset();
1216 RC.getSuperRegClasses(&Idx, MaskBV);
1217 if (MaskBV.none())
1218 continue;
1219 SRIList.push_back(&Idx);
1220 OS << "\n ";
1221 printBitVectorAsHex(OS, MaskBV, 32);
1222 OS << "// " << Idx.getName();
1223 }
1224 SuperRegIdxSeqs.add(SRIList);
1225 OS << "\n};\n\n";
1226 }
1227
1228 OS << "static const uint16_t SuperRegIdxSeqs[] = {\n";
1229 SuperRegIdxSeqs.layout();
1230 SuperRegIdxSeqs.emit(OS, printSubRegIndex);
1231 OS << "};\n\n";
1232
1233 // Emit NULL terminated super-class lists.
1234 for (const auto &RC : RegisterClasses) {
1235 ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
1236
1237 // Skip classes without supers. We can reuse NullRegClasses.
1238 if (Supers.empty())
1239 continue;
1240
1241 OS << "static const TargetRegisterClass *const "
1242 << RC.getName() << "Superclasses[] = {\n";
1243 for (const auto *Super : Supers)
1244 OS << " &" << Super->getQualifiedName() << "RegClass,\n";
1245 OS << " nullptr\n};\n\n";
1246 }
1247
1248 // Emit methods.
1249 for (const auto &RC : RegisterClasses) {
1250 if (!RC.AltOrderSelect.empty()) {
1251 OS << "\nstatic inline unsigned " << RC.getName()
1252 << "AltOrderSelect(const MachineFunction &MF) {"
1253 << RC.AltOrderSelect << "}\n\n"
1254 << "static ArrayRef<MCPhysReg> " << RC.getName()
1255 << "GetRawAllocationOrder(const MachineFunction &MF) {\n";
1256 for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) {
1257 ArrayRef<Record*> Elems = RC.getOrder(oi);
1258 if (!Elems.empty()) {
1259 OS << " static const MCPhysReg AltOrder" << oi << "[] = {";
1260 for (unsigned elem = 0; elem != Elems.size(); ++elem)
1261 OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
1262 OS << " };\n";
1263 }
1264 }
1265 OS << " const MCRegisterClass &MCR = " << Target.getName()
1266 << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n"
1267 << " const ArrayRef<MCPhysReg> Order[] = {\n"
1268 << " makeArrayRef(MCR.begin(), MCR.getNumRegs()";
1269 for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
1270 if (RC.getOrder(oi).empty())
1271 OS << "),\n ArrayRef<MCPhysReg>(";
1272 else
1273 OS << "),\n makeArrayRef(AltOrder" << oi;
1274 OS << ")\n };\n const unsigned Select = " << RC.getName()
1275 << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
1276 << ");\n return Order[Select];\n}\n";
1277 }
1278 }
1279
1280 // Now emit the actual value-initialized register class instances.
1281 OS << "\nnamespace " << RegisterClasses.front().Namespace
1282 << " { // Register class instances\n";
1283
1284 for (const auto &RC : RegisterClasses) {
1285 OS << " extern const TargetRegisterClass " << RC.getName()
1286 << "RegClass = {\n " << '&' << Target.getName()
1287 << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n "
1288 << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() <-- v7.0删除
1289 << "SubClassMask,\n SuperRegIdxSeqs + "
1290 << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "
1291 << format("0x%08x,\n ", RC.LaneMask) <-- v7.0删除
printMask(OS, RC.LaneMask); <-- v7.0增加
1292 << (unsigned)RC.AllocationPriority << ",\n "
1293 << (RC.HasDisjunctSubRegs?"true":"false")
1294 << ", /* HasDisjunctSubRegs */\n ";
<< (RC.CoveredBySubRegs?"true":"false") <-- v7.0增加
<< ", /* CoveredBySubRegs */\n ";
1295 if (RC.getSuperClasses().empty())
1296 OS << "NullRegClasses,\n ";
1297 else
1298 OS << RC.getName() << "Superclasses,\n ";
1299 if (RC.AltOrderSelect.empty())
1300 OS << "nullptr\n";
1301 else
1302 OS << RC.getName() << "GetRawAllocationOrder\n";
1303 OS << " };\n\n";
1304 }
1305
1306 OS << "}\n";
1307 }
1308
1309 OS << "\nnamespace {\n";
1310 OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
1311 for (const auto &RC : RegisterClasses)
1312 OS << " &" << RC.getQualifiedName() << "RegClass,\n";
1313 OS << " };\n";
1314 OS << "}\n"; // End of anonymous namespace...
1315
1316 // Emit extra information about registers.
1317 const std::string &TargetName = Target.getName();
1318 OS << "\nstatic const TargetRegisterInfoDesc "
1319 << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
1320 OS << " { 0, 0 fasle },\n"; <-- v7.0改为false
1321
1322 const auto &Regs = RegBank.getRegisters();
1323 for (const auto &Reg : Regs) {
1324 OS << " { ";
1325 OS << Reg.CostPerUse << ", "
1326 << int(AllocatableRegs.count(Reg.TheDef)) << " },\n";
1327 }
1328 OS << "};\n"; // End of register descriptors...
同样1125行的emitSourceFileHeader()为这部分输出产生一个描述性的注释。1127、1128行为这部分输出生成一个选择使用宏定义。在1133行则输出了X86MCRegisterClasses数组的一个前向声明。1144行循环将可分配的寄存器记录在容器AllocatableRegs里。
3.3.6.4.1. 寄存器类型与索引
1153行循环对每个寄存器类别的类型进行差分编码,然后输出下面这个描述寄存器类类型信息的差分表。
static const MVT::SimpleValueType VTLists[] = {
/* 0 */ MVT::i1, MVT::Other,
/* 2 */ MVT::i8, MVT::Other,
/* 4 */ MVT::i16, MVT::Other,
/* 6 */ MVT::i32, MVT::Other,
/* 8 */ MVT::i64, MVT::Other,
/* 10 */ MVT::f80, MVT::f64, MVT::f32, MVT::Other,
/* 14 */ MVT::f64, MVT::Other,
/* 16 */ MVT::f80, MVT::Other,
/* 18 */ MVT::v2i1, MVT::Other,
/* 20 */ MVT::v4i1, MVT::Other,
/* 22 */ MVT::v8i1, MVT::Other,
/* 24 */ MVT::v16i1, MVT::Other,
/* 26 */ MVT::v32i1, MVT::Other,
/* 28 */ MVT::v64i1, MVT::Other,
/* 30 */ MVT::v2i64, MVT::Other,
/* 32 */ MVT::v16f32, MVT::v8f64, MVT::v64i8, MVT::v32i16, MVT::v16i32, MVT::v8i64, MVT::Other,
/* 39 */ MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64, MVT::Other,
/* 46 */ MVT::v32i8, MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v8f32, MVT::v4f64, MVT::Other,
/* 53 */ MVT::x86mmx, MVT::Other,
};
1163行循环则是输出寄存器索引名字的数组(v7.0增加了蓝色部分)。
static const char *const SubRegIndexNameTable[] = { "sub_8bit", "sub_8bit_hi", "sub_8bit_hi_phony", "sub_16bit", "sub_16bit_hi", "sub_32bit", "sub_xmm", "sub_ymm", "" };
1171行循环输出记录寄存器索引LaneMask的数组。
static const unsigned SubRegIndexLaneMaskTable[] = {
~0u,
0x00000001, // sub_8bit
0x00000002, // sub_8bit_hi
0x00000003, // sub_16bit
0x00000003, // sub_32bit
0x00000004, // sub_xmm
0x00000004, // sub_ymm
};
V7.0则生成这样的数组:
static const LaneBitmask SubRegIndexLaneMaskTable[] = {
LaneBitmask::getAll(),
LaneBitmask(0x00000001), // sub_8bit
LaneBitmask(0x00000002), // sub_8bit_hi
LaneBitmask(0x00000004), // sub_8bit_hi_phony
LaneBitmask(0x00000007), // sub_16bit
LaneBitmask(0x00000008), // sub_16bit_hi
LaneBitmask(0x0000000F), // sub_32bit
LaneBitmask(0x00000010), // sub_xmm
LaneBitmask(0x00000010), // sub_ymm
};
在前面构建子寄存器关系一节中,我们知道如果索引A+B=C,那么A的LaneMask是它所构成的复合索引LaneMask的合集,B、C的LaneMask则是它们在SubRegIndices容器中的序号。从上面的数组可以看出,X86没有复合索引关系。
不过总有例外,ARM的SubRegIndexLaneMaskTable就相当复杂:
static const unsigned SubRegIndexLaneMaskTable[] = {
~0u,
0x0000000c, // dsub_0
0x00000030, // dsub_1
0x000000c0, // dsub_2
0x00000300, // dsub_3
0x00030000, // dsub_4
0x0000c000, // dsub_5
0x00003000, // dsub_6
0x00000c00, // dsub_7
0x00000001, // gsub_0
0x00000002, // gsub_1
0x000003fc, // qqsub_0
0x0003fc00, // qqsub_1
0x0000003c, // qsub_0
0x000003c0, // qsub_1
0x0003c000, // qsub_2
0x00003c00, // qsub_3
0x00000004, // ssub_0
0x00000008, // ssub_1
0x00000010, // ssub_2
0x00000020, // ssub_3
0x00000040, // dsub_2_then_ssub_0
0x00000080, // dsub_2_then_ssub_1
0x00000100, // dsub_3_then_ssub_0
0x00000200, // dsub_3_then_ssub_1
0x00000400, // dsub_7_then_ssub_0
0x00000800, // dsub_7_then_ssub_1
0x00001000, // dsub_6_then_ssub_0
0x00002000, // dsub_6_then_ssub_1
0x00004000, // dsub_5_then_ssub_0
0x00008000, // dsub_5_then_ssub_1
0x00010000, // dsub_4_then_ssub_0
0x00020000, // dsub_4_then_ssub_1
0x000000cc, // dsub_0_dsub_2
0x000000fc, // dsub_0_dsub_1_dsub_2
0x00000330, // dsub_1_dsub_3
0x000003f0, // dsub_1_dsub_2_dsub_3
0x000000f0, // dsub_1_dsub_2
0x000300cc, // dsub_0_dsub_2_dsub_4
0x000330cc, // dsub_0_dsub_2_dsub_4_dsub_6
0x0000c330, // dsub_1_dsub_3_dsub_5
0x0000cf30, // dsub_1_dsub_3_dsub_5_dsub_7
0x000303f0, // dsub_1_dsub_2_dsub_3_dsub_4
0x000300c0, // dsub_2_dsub_4
0x000303c0, // dsub_2_dsub_3_dsub_4
0x000330c0, // dsub_2_dsub_4_dsub_6
0x0000c300, // dsub_3_dsub_5
0x0003c300, // dsub_3_dsub_4_dsub_5
0x0000cf00, // dsub_3_dsub_5_dsub_7
0x00030300, // dsub_3_dsub_4
0x0003f300, // dsub_3_dsub_4_dsub_5_dsub_6
0x00033000, // dsub_4_dsub_6
0x0003f000, // dsub_4_dsub_5_dsub_6
0x0000cc00, // dsub_5_dsub_7
0x0000fc00, // dsub_5_dsub_6_dsub_7
0x0000f000, // dsub_5_dsub_6
0x0003c3c0, // qsub_1_qsub_2
};
这里有的索引名字很简单,比如dusb_5,它们都是TD文件里直接定义的索引。剩下具有复杂名字的索引都是合成出来,比如名字中带有“then”的索引是在CodeGenRegister::computeSubRegs()方法里由CodeGenRegBank::getCompositeSubRegIndex()方法合成的,余下的索引则是在推导隐含孙子寄存器的过程中由CodeGenRegister::computeSecondarySubRegs()方法通过CodeGenRegBank:: getConcatSubRegIndex()方法合成的。
这里以qsub_2为例,它的值是0x0003c000,可以看到它能复合出dsub_5_then_ssub_0,dsub_5_then_ssub_1,dsub_4_then_ssub_0,dsub_4_then_ssub_1这四个索引。
索引的名字还表示了获取它们的过程。
比如dsub_5_then_ssub_0表示先在qsub_2援引的子寄存器上访问dsub_5援引的部分,然后在该部分上访问ssub_0援引的部分。
而形如dsub_2_dsub_4_dsub_6这样的名字则表示援引的部分,连续覆盖了dsub_2,dsub_4及dsub_6所援引的部分。
3.3.6.4.2. 寄存器类的描述
类似的MCRegisterClass对CodeGen而言是不足够的,MCRegisterClass只关心与汇编代码有关的东西,因此,汇编以外的东东就需要TargetRegisterClass代劳了:
36 class TargetRegisterClass {
37 public:
38 typedef const MCPhysReg* iterator;
39 typedef const MCPhysReg* const_iterator;
40 typedef const MVT::SimpleValueType* vt_iterator; <-- v7.0删除
41 typedef const TargetRegisterClass* const * sc_iterator;
42
43 // Instance variables filled by tablegen, do not use!
44 const MCRegisterClass *MC;
45 const vt_iterator VTs; <-- v7.0删除
46 const uint32_t *SubClassMask;
47 const uint16_t *SuperRegIndices;
48 const unsigned LaneMask;
49 /// Classes with a higher priority value are assigned first by register
50 /// allocators using a greedy heuristic. The value is in the range [0,63].
51 const uint8_t AllocationPriority;
52 /// Whether the class supports two (or more) disjunct subregister indices.
53 const bool HasDisjunctSubRegs;
/// Whether a combination of subregisters can cover every register in the
/// class. See also the CoveredBySubRegs description in Target.td.
const bool CoveredBySubRegs; <-- v7.0增加
54 const sc_iterator SuperClasses;
这次没有使用继承,而是选择了复合(44行)。
填充TargetRegisterClass所需的数据都在前面准备好了。在1179行开始输出TargetRegisterClass数组的定义。V7.0改进了TargetRegisterInfo的定义,将RegSize、SpillSize、SpillAlignment、VTList封装到嵌套结构体RegClassInfo中,并声明指针成员RCInfos指向相应的数组,因此v7.0会首先生成一个RegClassInfo数组,像这样:
static const TargetRegisterInfo::RegClassInfo RegClassInfos[] = {
// Mode = 0 (Default)
{ 8, 8, 8, VTLists+0 }, // GR8
{ 8, 8, 8, VTLists+0 }, // GRH8
{ 8, 8, 8, VTLists+0 }, // GR8_NOREX
{ 8, 8, 8, VTLists+0 }, // GR8_ABCD_H
{ 8, 8, 8, VTLists+0 }, // GR8_ABCD_L
…
{ 512, 512, 512, VTLists+47 }, // VR512_with_sub_xmm_in_VR128L
};
首先定义在下面各个TargetRegisterClass数组中表示空迭代器的NullRegClasses。
static const TargetRegisterClass *const NullRegClasses[] = { nullptr };
1207行循环遍历所有的寄存器类。在1209行输出每个寄存器类包含的子类(由CodeGenRegisterClass::computeSubClasses()方法收集,SubClasses容器里保存的是子寄存器类EnumValue的or集)。另一方面,1214行循环遍历所有的寄存器索引,获取RC类寄存器关于指定索引的超级类(参考超级寄存器类一节),由SuperRegIdxSeqs对这些索引进行差分编码,并将得到的超级类输出到相应SubClassMask数组的末尾。输出的SubClassMask数组大致是:
static const uint32_t GR8SubClassMask[] = {
0x00000c03, 0x00000000, 0x00000000,
0x35e23000, 0xf399e0bf, 0x0000007f, // sub_8bit
0x00020000, 0x000000be, 0x0000007d, // sub_8bit_hi
};
第一行的元素是由1209行输出的,一共包含了96个比特(X86目标机器的实际寄存器类别数是80,因此是足够的。注:V7.0是86个)。GR8本身所包含的子寄存器类别是GR8RegClass(比特0对应EnumValue值1),GR8_NOREXRegClass(比特1对应EnumValue值2),GR8_ABCD_HRegClass以及GR8_ABCD_LRegClass。
第二、三行都是由1214行循环输出的。
比如第二行指出哪些寄存器类是包含GR8关于sub_8bit索引的超级类:GR16RegClass,GR16_NOREXRegClass,GR16_ABCDRegClass,GR32RegClass,GR32_NOAXRegClass,GR32_NOSPRegClass,GR32_NOAX_and_GR32_NOSPRegClass,GR32_NOREXRegClass,GR32_NOAX_and_GR32_NOREXRegClass,GR32_NOREX_NOSPRegClass, GR32_NOAX_and_GR32_NOREX_NOSPRegClass,GR32_ABCDRegClass,GR32_ABCD_and_GR32_NOAXRegClass,GR32_ADRegClass,GR32_NOAX_and_GR32_TCRegClass,GR32_AD_and_GR32_NOAXRegClass,GR64_with_sub_8bitRegClass,GR64_NOSPRegClass,GR64_with_sub_32bit_in_GR32_NOAXRegClass,GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOSPRegClass,GR64_NOSP_and_GR64_TCRegClass,GR64_with_sub_16bit_in_GR16_NOREXRegClass,GR64_NOREX_NOSPRegClass,GR64_TC_and_GR64_with_sub_32bit_in_GR32_NOAXRegClass,GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOREXRegClass,GR64_TCW64RegClass,GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOREX_NOSPRegClass,GR64_NOREX_NOSP_and_GR64_TCRegClass,GR64_TCW64_and_GR64_with_sub_32bit_in_GR32_NOAXRegClass,GR64_ABCDRegClass,GR64_TC_and_GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOREXRegClass,GR64_with_sub_32bit_in_GR32_ABCD_and_GR32_NOAXRegClass,GR64_with_sub_32bit_in_GR32_TCRegClass,GR64_with_sub_32bit_in_GR32_ADRegClass,GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_TCRegClass,GR64_with_sub_32bit_in_GR32_AD_and_GR32_NOAXRegClass。
通过索引sub_8bit,从这些寄存器类中的寄存器将可以访问GR8类的寄存器。
对每个寄存器类定义了相应的SubClassMask数组后,输出这些映射有超级类的寄存器索引的差分表:
static const uint16_t SuperRegIdxSeqs[] = {
/* 0 */ 1, 0,
/* 2 */ 1, 2, 0,
/* 5 */ 3, 0,
/* 7 */ 4, 0,
/* 9 */ 5, 0,
/* 11 */ 6, 0,
};
另一个寄存器类间的关系是包含关系(SuperClass),比如GR8包含GR8_NOREX。1234行的循环输出每个寄存器类间的包含关系(如果有的话),以NULL结尾。如GR8_NOREX被GR8包含:
static const TargetRegisterClass *const GR8_NOREXSuperclasses[] = {
&X86::GR8RegClass,
nullptr
};
接下来,如果在寄存器类别中定义了AltOrders与AltOrderSelect(表示有另外的分配次序),需要为这些寄存器类别定义*AltOrderSelect()方法。以X86机器的GR8为例,将输出下面的代码:
static inline unsigned GR8AltOrderSelect(const MachineFunction &MF) {
return MF.getSubtarget<X86Subtarget>().is64Bit();
}
static ArrayRef<MCPhysReg> GR8GetRawAllocationOrder(const MachineFunction &MF) {
static const MCPhysReg AltOrder1[] = { X86::AL, X86::CL, X86::DL, X86::BL, X86::SIL, X86::DIL, X86::BPL, X86::SPL, X86::R8B, X86::R9B, X86::R10B, X86::R11B, X86::R14B, X86::R15B, X86::R12B, X86::R13B };
const MCRegisterClass &MCR = X86MCRegisterClasses[X86::GR8RegClassID];
const ArrayRef<MCPhysReg> Order[] = {
makeArrayRef(MCR.begin(), MCR.getNumRegs()),
makeArrayRef(AltOrder1)
};
const unsigned Select = GR8AltOrderSelect(MF);
assert(Select < 2);
return Order[Select];
}
GR8在X86RegisterInfo.td中的定义是这样子的:
328 def GR8 : RegisterClass<"X86", [i8], 8,
329 (add AL, CL, DL, AH, CH, DH, BL, BH, SIL, DIL, BPL, SPL,
330 R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B)> {
331 let AltOrders = [(sub GR8, AH, BH, CH, DH)];
332 let AltOrderSelect = [{
333 return MF.getSubtarget<X86Subtarget>().is64Bit();
334 }];
335 }
上面GR8GetRawAllocationOrder中的MCR.begin返回数组GR8的首地址(参考前面对这个数组的输出),这是上面329与330行给出的列表内容。而数组AltOrder1则是对331行AltOrders的实现。方法GR8AltOrderSelect()则执行具体的选择。在64位模式下,AH,BH,CH与DH被排除在GR8外。
1284行循环开始输出每个寄存器类的TargetRegisterClass实例。
1288行的VTSeqs是寄存器类包含数据类型的差分编码对象,差分编码表就是前面输出的VTLists。类似的1290行的SuperRegIdxSeqs也是一个差分编码对象,SuperRegIdxSeqs是对应的差分编码表。因此,输出的TargetRegisterClass实例定义像这个样子:
namespace X86 { // Register class instances
extern const TargetRegisterClass GR8RegClass = {
&X86MCRegisterClasses[GR8RegClassID],
VTLists + 2,
GR8SubClassMask,
SuperRegIdxSeqs + 2,
0x00000000,
0,
false, /* HasDisjunctSubRegs */
NullRegClasses,
GR8GetRawAllocationOrder
};
V7.0则是这样的:
extern const TargetRegisterClass GR8RegClass = {
&X86MCRegisterClasses[GR8RegClassID],
GR8SubClassMask,
SuperRegIdxSeqs + 2,
LaneBitmask(0x00000001),
0,
false, /* HasDisjunctSubRegs */
false, /* CoveredBySubRegs */
NullRegClasses,
GR8GetRawAllocationOrder
};
接下来,1309~1314行输出一个数组,指向所有寄存器类的TargetRegisterClass。而1322~1328行则输出一个TargetRegisterInfoDesc数组X86RegInfoDesc。TargetRegisterInfoDesc是这样定义的:
210 struct TargetRegisterInfoDesc {
211 unsigned CostPerUse; // Extra cost of instructions using register.
212 bool inAllocatableClass; // Register belongs to an allocatable regclass.
213 };
显然X86RegInfoDesc也是以寄存器的EnumValue值为下标的数组。