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
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
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
268
269 for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) {
270
ArrayRef
271 PSets[i].reserve(PSetIDs.size());
272
for
(ArrayRef
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[];
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【每日笔记】【Go学习笔记】2019-01-04 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-02 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-07 Codis笔记
- Golang学习笔记-调度器学习
- Vue学习笔记(二)------axios学习
- 算法/NLP/深度学习/机器学习面试笔记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JAVA语言规范(英文版,第3版)
戈斯林 / 机械工业 / 2006-4 / 79.00元
本书由“java之父”Jame Gosling 以及另外三位顶级大师撰写而成,无论是对java语言的初学者还是专业程序员都具有极高的价值,是关于java程序设计语言最权威的技术参考书。 本书侧重于java技术细节和内幕,全面,准确,详尽地介绍了java语言及其语法,论述了java编译器所要检查的语法和java运行模式的各个方面,同时还描述了java语言最重要的新特征。一起来看看 《JAVA语言规范(英文版,第3版)》 这本书的介绍吧!