LLVM学习笔记(14)

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的定义,将RegSizeSpillSizeSpillAlignmentVTList封装到嵌套结构体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.086)。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值为下标的数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值