LLVM学习笔记(14)补2

栏目: 服务器 · 编程工具 · 发布时间: 5年前

3.3.6.4.5. 定义获取权重及压力数据方法

目标机器需要提供以下方法来让CodeGen获取权重以及压力数据:

getRegPressureLimit(),getRegClassWeight(),getRegUnitWeight(),getNumRegPressureSets(),getRegPressureSetName(),getRegPressureSetLimit(),getRegClassPressureSets(),getRegUnitPressureSets()。

首先被输出的getRegClassWeight()方法的定义。它返回以所属寄存器单元(RegUnit)权重来衡量的寄存器类权重。

RegisterInfoEmitter::runTargetDesc(续)

1373  (OS, RegBank, ClassName);

1374 

1375  // Emit the constructor of the class...

1376  OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";

1377  OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n";

1378  OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n";

1379  OS << "extern const char " << TargetName << "RegStrings[];\n";

1380  OS << "extern const char " << TargetName << "RegClassStrings[];\n";

1381  OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n";

1382  OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n";

1383  OS << "extern const MCRegisterInfo::SubRegCoveredBits "

1384  << TargetName << "SubRegIdxRanges[];\n";

1385  OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n";

RegisterInfoEmitter::EmitRegUnitPressure()的176行,CodeGenRegBank::getNumRegPressureSets()方法返回容器RegUnitSets的大小。RegUnitSets容器里记录了与寄存器类相关的RegUnit同类集,这个同类集的权重,以及这些同类集间的顺序号。

172     void RegisterInfoEmitter::

173     EmitRegUnitPressure (raw_ostream &OS, const CodeGenRegBank &RegBank,

174     const std::string &ClassName) {

175     unsigned NumRCs = RegBank.getRegClasses().size();

176     unsigned NumSets = RegBank.getNumRegPressureSets();

177    

178     OS << "/// Get the weight in units of pressure for this register class.\n"

179     << "const RegClassWeight &" << ClassName << "::\n"

180     << "getRegClassWeight(const TargetRegisterClass *RC) const {\n"

181     << "  static const RegClassWeight RCWeightTable[] = {\n";

182     for ( const auto &RC : RegBank.getRegClasses()) {

183     const CodeGenRegister::Vec &Regs = RC.getMembers();

184     if (Regs.empty())

185     OS << "    {0, 0";

186     else {

187     std::vector RegUnits;

188     RC.(RegUnits);

189   OS << "    {" << (*Regs.begin())->getWeight(RegBank)

190     << ", " << RegBank.getRegUnitSetWeight(RegUnits);

191     }

192     OS << "},  \t// " << RC.getName() << "\n";

193     }

194     OS << "  };\n"

195     << "  return RCWeightTable[RC->getID()];\n"

196     << "}\n\n";

182行循环通过CodeGenRegisterClass::buildRegUnitSet()方法计算一个寄存器类的RegUnit同类集,189行通过getWeight()方法得到该寄存器类中第一个寄存器的权重,190行的getRegUnitSetWeight()方法则计算RegUnit同类集的权重。那么以X86目标机器为例,我们将输出这个方法:

const RegClassWeight &X86GenRegisterInfo::

getRegClassWeight( const TargetRegisterClass *RC) const {

static const RegClassWeight RCWeightTable[] = {

{1, 20}, // GR8

{1, 8}, // GR8_NOREX

{1, 8}, // VK1

{1, 8}, // VK2

{1, 8}, // VK4

{1, 8}, // VK8

{1, 7}, // VK1WM

{1, 7}, // VK2WM

{1, 7}, // VK4WM

{1, 7}, // VK8WM

{1, 4}, // GR8_ABCD_H

{1, 4}, // GR8_ABCD_L

{2, 32}, // GR16

{2, 16}, // GR16_NOREX

{1, 8}, // VK16

{1, 7}, // VK16WM

{1, 6}, // SEGMENT_REG

{2, 8}, // GR16_ABCD

{0, 0}, // FPCCR

{1, 32}, // FR32X

{1, 16}, // FR32

{2, 32}, // GR32

{2, 30}, // GR32_NOAX

{2, 30}, // GR32_NOSP

{2, 28}, // GR32_NOAX_and_GR32_NOSP

{1, 8}, // DEBUG_REG

{2, 16}, // GR32_NOREX

{1, 8}, // VK32

{2, 14}, // GR32_NOAX_and_GR32_NOREX

{2, 14}, // GR32_NOREX_NOSP

{1, 7}, // RFP32

{1, 7}, // VK32WM

{2, 12}, // GR32_NOAX_and_GR32_NOREX_NOSP

{2, 8}, // GR32_ABCD

{2, 6}, // GR32_ABCD_and_GR32_NOAX

{2, 6}, // GR32_TC

{2, 4}, // GR32_AD

{2, 4}, // GR32_NOAX_and_GR32_TC

{0, 0}, // CCR

{2, 2}, // GR32_AD_and_GR32_NOAX

{1, 7}, // RFP64

{1, 32}, // FR64X

{2, 34}, // GR64

{1, 16}, // CONTROL_REG

{1, 16}, // FR64

{2, 32}, // GR64_with_sub_8bit

{2, 30}, // GR64_NOSP

{2, 30}, // GR64_with_sub_32bit_in_GR32_NOAX

{2, 28}, // GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOSP

{2, 18}, // GR64_NOREX

{2, 18}, // GR64_TC

{2, 16}, // GR64_NOSP_and_GR64_TC

{2, 16}, // GR64_with_sub_16bit_in_GR16_NOREX

{1, 8}, // VK64

{1, 8}, // VR64

{2, 14}, // GR64_NOREX_NOSP

{2, 14}, // GR64_TC_and_GR64_with_sub_32bit_in_GR32_NOAX

{2, 14}, // GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOREX

{1, 7}, // VK64WM

{2, 12}, // GR64_NOREX_and_GR64_TC

{2, 12}, // GR64_TCW64

{2, 12}, // GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOREX_NOSP

{2, 10}, // GR64_NOREX_NOSP_and_GR64_TC

{2, 10}, // GR64_TCW64_and_GR64_with_sub_32bit_in_GR32_NOAX

{2, 8}, // GR64_ABCD

{2, 8}, // GR64_TC_and_GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_NOREX

{2, 6}, // GR64_with_sub_32bit_in_GR32_ABCD_and_GR32_NOAX

{2, 6}, // GR64_with_sub_32bit_in_GR32_TC

{2, 4}, // GR64_with_sub_32bit_in_GR32_AD

{2, 4}, // GR64_with_sub_32bit_in_GR32_NOAX_and_GR32_TC

{2, 2}, // GR64_with_sub_32bit_in_GR32_AD_and_GR32_NOAX

{0, 0}, // RST

{1, 7}, // RFP80

{1, 32}, // VR128X

{1, 16}, // VR128

{1, 4}, // BNDR

{1, 32}, // VR256X

{1, 16}, // VR256

{1, 32}, // VR512

{1, 16}, // VR512_with_sub_xmm_in_FR32

};

return RCWeightTable[RC->getID()];

}

数组RCWeightTable的每一项对应一个寄存器类,而每一项里第一个数字是该类中第一个寄存器的权重,第二个数字则是该类寄存器RegUnit同类集的权重,也称为该寄存器类的权重上限。

接下来输出获取寄存器单元权重的方法getRegUnitWeight()。

RegisterInfoEmitter::EmitRegUnitPressure(续)

198     // Reasonable targets (not ARMv7) have unit weight for all units, so don't

199       // bother generating a table.

200     bool RegUnitsHaveUnitWeight = true;

201     for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();

202     UnitIdx < UnitEnd; ++UnitIdx) {

203     if (RegBank.getRegUnit(UnitIdx).Weight > 1)

204     RegUnitsHaveUnitWeight = false;

205     }

206     OS << "/// Get the weight in units of pressure for this register unit.\n"

207     << "unsigned " << ClassName << "::\n"

208     << "getRegUnitWeight(unsigned RegUnit) const {\n"

209     << "  assert(RegUnit < " << RegBank.getNumNativeRegUnits()

210     << " && \"invalid register unit\");\n";

211     if (!RegUnitsHaveUnitWeight) {

212     OS << "  static const uint8_t RUWeightTable[] = {\n    ";

213     for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();

214     UnitIdx < UnitEnd; ++UnitIdx) {

215     const RegUnit &RU = RegBank.getRegUnit(UnitIdx);

216     assert (RU.Weight < 256 && "RegUnit too heavy");

217     OS << RU.Weight << ", ";

218     }

219     OS << "};\n"

220     << "  return RUWeightTable[RegUnit];\n";

221     }

222     else {

223     OS << "  // All register units have unit weight.\n"

224     << "  return 1;\n";

225     }

226     OS << "}\n\n";

227

228     OS << "\n"

229     << "// Get the number of dimensions of register pressure.\n"

230     << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n"

231     << "  return " << NumSets << ";\n}\n\n";

230

233     OS << "// Get the name of this register unit pressure set.\n"

234     << "const char *" << ClassName << "::\n"

235     << "getRegPressureSetName(unsigned Idx) const {\n"

236     << "  static const char *const PressureNameTable[] = {\n";

237     unsigned MaxRegUnitWeight = 0;

238     for (unsigned i = 0; i < NumSets; ++i ) {

239     const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);

240     MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight);

241     OS << "    \"" << RegUnits.Name << "\",\n";

242     }

243     OS << "    nullptr };\n"

244     << "  return PressureNameTable[Idx];\n"

245     << "}\n\n";

246    

247     OS << "// Get the register unit pressure limit for this dimension.\n"

248     << "// This limit must be adjusted dynamically for reserved registers.\n"

249     << "unsigned " << ClassName << "::\n"

250     << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const {\n"

251     << "  static const " << getMinimalTypeForRange(MaxRegUnitWeight)

252     << " PressureLimitTable[] = {\n";

253     for (unsigned i = 0; i < NumSets; ++i ) {

254     const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);

255     OS << "    " << RegUnits.Weight << ",  \t// " << i << ": "

256     << RegUnits.Name << "\n";

257     }

258     OS << "  };\n"

259     << "  return PressureLimitTable[Idx];\n"

260     << "}\n\n";

前面看到Native单元,如果没有特殊情况,其Weight就是1,它是寄存器真正可用的部分(相比为调整权重加入的单元)。201行循环遍历所有的Native单元,确定是否存在权重大于1的单元。如果没有,就可以直接返回1,否则需要声明一个RUWeightTable数组来给出相应的权重。对于X86目标机器,输出的方法是这样的。

unsigned X86GenRegisterInfo::

getRegUnitWeight(unsigned RegUnit) const {

assert (RegUnit < 131 && "invalid register unit");

// All register units have unit weight.

return 1;

}

接下来输出返回寄存器压力描述维度数(即RegUnit的同类集)的方法getNumRegPressureSets()。X86目标机器的是:

unsigned X86GenRegisterInfo::getNumRegPressureSets() const {

return 22;             <-- v7.0 这个值是 30

}

以及返回寄存器压力描述维度数名字的方法getRegPressureSetName()。RegUnit的同类集的名字在构建时已经设置好。

const char *X86GenRegisterInfo::

getRegPressureSetName(unsigned Idx) const {

static const char * const PressureNameTable[] = {

"GR8_ABCD_H",

"GR8_ABCD_L",

"BNDR",

"SEGMENT_REG",

"RFP32",

"GR8_NOREX",

"VK1",

"DEBUG_REG",

"VR64",

"GR8_NOREX+GR64_NOREX_and_GR64_TC",

"GR8_NOREX+GR64_TCW64",

"FR32",

"CONTROL_REG",

"GR64_NOREX",

"GR8",

"GR8_NOREX+GR64_TC",

"GR8+GR64_TCW64",

"GR64_NOREX+GR64_TC",

"GR8+GR64_NOREX",

"GR8+GR64_TC",

"FR32X",

"GR64",

nullptr };

return PressureNameTable[Idx];

}

接下来输出获取出寄存器压力指定维度数据(即指定RegUnit同类集,这些同类集参见上面getRegPressureSetName()定义的名字)的getRegPressureSetLimit()方法。

unsigned X86GenRegisterInfo::

getRegPressureSetLimit( const MachineFunction &MF, unsigned Idx) const {

static const uint8_t PressureLimitTable[] = {

4, // 0: GR8_ABCD_H

4, // 1: GR8_ABCD_L

4, // 2: BNDR

6, // 3: SEGMENT_REG

7, // 4: RFP32

8, // 5: GR8_NOREX

8, // 6: VK1

8, // 7: DEBUG_REG

8, // 8: VR64

14, // 9: GR8_NOREX+GR64_NOREX_and_GR64_TC

14, // 10: GR8_NOREX+GR64_TCW64

16, // 11: FR32

16, // 12: CONTROL_REG

18, // 13: GR64_NOREX

20, // 14: GR8

20, // 15: GR8_NOREX+GR64_TC

23, // 16: GR8+GR64_TCW64

24, // 17: GR64_NOREX+GR64_TC

26, // 18: GR8+GR64_NOREX

27, // 19: GR8+GR64_TC

32, // 20: FR32X

34, // 21: GR64

};

return PressureLimitTable[Idx];

}

给出的实际上是指定RegUnit同类集的权重。

接着,266行的getNumRegClassPressureSetLists()方法返回CodeGenRegBank的RegClassUnitSets容器的大小,这个容器记录了每个寄存器类RegUnit同类集超集的RegUnit同类集的集合。

RegisterInfoEmitter::EmitRegUnitPressure(续)

262     SequenceToOffsetTable> PSetsSeqs;

263    

264     // This table may be larger than NumRCs if some register units needed a list

265       // of unit sets that did not correspond to a register class.

266     unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists();

267     std::vector> PSets(NumRCUnitSets);

268    

269     for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) {

270     ArrayRef PSetIDs = RegBank.getRCPressureSetIDs(i);

271     PSets[i].reserve(PSetIDs.size());

272    for (ArrayRef::iterator PSetI = PSetIDs.begin(),

273     PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) {

274     PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order);

275     }

276     std::sort(PSets[i].begin(), PSets[i].end());

277     PSetsSeqs.(PSets[i]);

278     }

279    

280     PSetsSeqs.();

281    

282     OS << "/// Table of pressure sets per register class or unit.\n"

283     << "static const int RCSetsTable[] = {\n";

284     PSetsSeqs.(OS, printInt, "-1");

285     OS << "};\n\n";

286    

287     OS << "/// Get the dimensions of register pressure impacted by this "

288     << "register class.\n"

289     << "/// Returns a -1 terminated array of pressure set IDs\n"

290     << "const int* " << ClassName << "::\n"

291     << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n";

292     OS << "  static const " << getMinimalTypeForRange(PSetsSeqs.size()-1)

293     << " RCSetStartTable[] = {\n    ";

294     for (unsigned i = 0, e = NumRCs; i != e; ++i) {

295     OS << PSetsSeqs.(PSets[i]) << ",";

296     }

297     OS << "};\n"

298     << "  return &RCSetsTable[RCSetStartTable[RC->getID()]];\n"

299     << "}\n\n";

300    

301     OS << "/// Get the dimensions of register pressure impacted by this "

302     << "register unit.\n"

303     << "/// Returns a -1 terminated array of pressure set IDs\n"

304     << "const int* " << ClassName << "::\n"

305     << "getRegUnitPressureSets(unsigned RegUnit) const {\n"

306     << "  assert(RegUnit < " << RegBank.getNumNativeRegUnits()

307     << " && \"invalid register unit\");\n";

308     OS << "  static const " << getMinimalTypeForRange(PSetsSeqs.size()-1)

309     << " RUSetStartTable[] = {\n    ";

310     for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();

311     UnitIdx < UnitEnd; ++UnitIdx) {

312     OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx])

313     << ",";

314     }

315     OS << "};\n"

316     << "  return &RCSetsTable[RUSetStartTable[RegUnit]];\n"

317     << "}\n\n";

318     }

269行循环将CodeGenRegBank的RegClassUnitSets容器的内容进行差分编码。差分编码的内容是RegUnitSet实例的Order域(表示这些对象以集合大小 排序 的优先级)如果结合RegUnitSetOrder与RegUnitSets容器,可以得到这些RegUnitSet对象。在284行输出这个差分表。

static const int RCSetsTable[] = {

/* 0 */ 2, -1,

/* 2 */ 3, -1,

/* 4 */ 4, -1,

/* 6 */ 6, -1,

/* 8 */ 7, -1,

/ * 10 */ 8, -1,

/* 12 */ 12, -1,

/* 14 */ 11, 20, -1,

/* 17 */ 13, 17, 18, 21, -1,

/* 22 */ 15, 17, 19, 21, -1,

/* 27 */ 10, 15, 16, 17, 19, 21, -1,

/* 34 */ 14, 16, 18, 19, 21, -1,

/* 40 */ 9, 13, 15, 17, 18, 19, 21, -1,

/* 48 */ 13, 14, 16, 17, 18, 19, 21, -1,

/* 56 */ 10, 14, 15, 16, 17, 18, 19, 21, -1,

/* 65 */ 9, 13, 14, 15, 16, 17, 18, 19, 21, -1,

/* 75 */ 0, 5, 9, 10, 13, 14, 15, 16, 17, 18, 19, 21, -1,

/* 88 */ 1, 5, 9, 10, 13, 14, 15, 16, 17, 18, 19, 21, -1,

};

注意,这个差分表以-1为终结符。

因为这个差分表的内容是CodeGenRegBank的RegClassUnitSets容器的内容,因此给定一个寄存器类,我们可以知道所有作为其超集的RegUnit同类集。

293~296行输出的方法getRegClassPressureSets()返回这些同类集ID的地址。

const int* X86GenRegisterInfo::

getRegClassPressureSets( const TargetRegisterClass *RC) const {

static const uint8_t RCSetStartTable[] = {34,76,6,6,6,6,6,6,6,6,75,88,20,17,6,6,2,76,1,15,14,20,20,20,20,8,17,6,17,17,4,6,17,76,76,76,76,76,1,76,4,15,20,12,14,20,20,20,20,17,22,22,17,6,10,17,22,17,6,40,27,17,40,27,76,40,76,76,76,76,76,1,4,15,14,0,15,14,15,14,};

return &RCSetsTable[RCSetStartTable[RC->getID()]];

}

其中,数组RCSetStartTable给出在RCSetsTable中的偏移。

另一个类似的方法getRegUnitPressureSets()返回包含一个指定RegUnit的RegUnit同类集的集合。

const int* X86GenRegisterInfo::

getRegUnitPressureSets(unsigned RegUnit) const {

assert (RegUnit < 131 && "invalid register unit");

static const uint8_t RUSetStartTable[] = {75,88,75,88,48,75,88,2,75,65,88,2,1,40,1,2,65,48,1,2,2,1,2,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,8,8,8,8,8,8,8,8,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,1,6,6,6,6,6,6,6,6,10,10,10,10,10,10,10,10,56,56,34,56,34,34,34,34,1,1,1,1,1,1,1,1,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,};

return &RCSetsTable[RUSetStartTable[RegUnit]];

}

接下来声明了这样一组下面要用到的数组。

extern const MCRegisterDesc X86RegDesc[];

extern const MCPhysReg X86RegDiffLists[];

extern const unsigned X86LaneMaskLists[];

extern const char X86RegStrings[];

extern const char X86RegClassStrings[];

extern const MCPhysReg X86RegUnitRoots[][2];

extern const uint16_t X86SubRegIdxLists[];

extern const MCRegisterInfo::SubRegCoveredBits X86SubRegIdxRanges[];

extern const uint16_t X86RegEncodingTable[];


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JAVA语言规范(英文版,第3版)

JAVA语言规范(英文版,第3版)

戈斯林 / 机械工业 / 2006-4 / 79.00元

本书由“java之父”Jame Gosling 以及另外三位顶级大师撰写而成,无论是对java语言的初学者还是专业程序员都具有极高的价值,是关于java程序设计语言最权威的技术参考书。   本书侧重于java技术细节和内幕,全面,准确,详尽地介绍了java语言及其语法,论述了java编译器所要检查的语法和java运行模式的各个方面,同时还描述了java语言最重要的新特征。一起来看看 《JAVA语言规范(英文版,第3版)》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码