3.3. 寄存器的后端描述
选项“-gen-register-info”会促使Tablegen根据文件TargetRegisterInfo.td中的寄存器定义生成源文件TargetGenRegisterInfo.inc。
3.3.1. 概述
对TD文件中定义的每个寄存器而言,TableGen都会将它们处理为DAG,这些寄存器作为根,它们的子寄存器作为DAG内部节点,其中不包含任何子寄存器的子寄存器作为叶子。TableGen将遍历这些DAG,为每个寄存器构建包含次级子寄存器的完整子寄存器列表。同时,TableGen为包含子寄存器的寄存器构建子寄存器索引,以记录指定子寄存器在该寄存器中的位置。由于子寄存器通常也会包含自己的子寄存器,TableGen还需要为这样的次级子寄存器构建复合索引。
除此之外,TableGen还需要建立这些数据结构间的若干关系,比如从一个索引出发能构建出哪些复合索引(Lane掩码),还有一个寄存器会覆盖哪些索引(寄存器单元Lane掩码)。而对寄存器DAG中的叶子寄存器,TableGen将其视为一个寄存器单元(以RegUnit抽象之),每个寄存器都视为这些寄存器单元的一个集合。根据这些集合,TableGen计算用于寄存器压力模型的寄存器Weight权重。
至于寄存器类别,它描述了一组可以互换使用的寄存器。TableGen会构建它们所包含的寄存器单元集,用于寄存器压力模型。
所有这一切处理的入口在EmitRegisterInfo():
1487 void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS) {
1488 RegisterInfoEmitter(RK).run(OS);
1489 }
1488行的RegisterInfoEmitter是一个简单的类,其方法RegisterInfoEmitter::run()定义如下:
1474 void RegisterInfoEmitter::run(raw_ostream &OS) {
1475 CodeGenTarget Target(Records); <-- v7.0删除
1476 CodeGenRegBank &RegBank = Target.getRegBank();
1477 RegBank.computeDerivedInfo(); <-- v7.0删除
1478
1479 runEnums(OS, Target, RegBank);
1480 runMCDesc(OS, Target, RegBank);
1481 runTargetHeader(OS, Target, RegBank);
1482 runTargetDesc(OS, Target, RegBank);
1483 }
RegisterInfoEmitter::Run()的处理分两部分。第一部分需要将TD描述转换为LLVM的DAG表示形式,第二分别则是根据DAG生成所需的输出文件——TargetGenRegisterInfo.inc。
因为V7.0里RegisterInfoEmitter的构造函数不是平凡的。
RegisterInfoEmitter(RecordKeeper &R) : Target(R), Records(R) {
CodeGenRegBank &RegBank = Target.getRegBank();
RegBank.computeDerivedInfo();
}
3.3.2. SetTheory
寄存器的定义可以使用TableGen内置的工作在dag值上的集合操作,比如 (add set1, set2)产生set1、set2的合集。这些操作语义的处理是由TableGen提供的。现在我们就来看一下相关的数据结构与处理(v7.0稍有改动,但基本处理没有变化,因此不列出其间差异)。
类SetTheory用于提供这些处理。
63 class SetTheory {
64 public:
65 typedef std::vector<Record*> RecVec;
66 typedef SmallSetVector<Record*, 16> RecSet;
67
68 /// Operator - A callback representing a DAG operator.
69 class Operator {
70 virtual void anchor();
71 public:
72 virtual ~Operator() {}
73
74 /// apply - Apply this operator to Expr's arguments and insert the result
75 /// in Elts.
76 virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts,
77 ArrayRef<SMLoc> Loc) =0;
78 };
79
80 /// Expander - A callback function that can transform a Record representing a
81 /// set into a fully expanded list of elements. Expanders provide a way for
82 /// users to define named sets that can be used in DAG expressions.
83 class Expander {
84 virtual void anchor();
85 public:
86 virtual ~Expander() {}
87
88 virtual void expand(SetTheory&, Record*, RecSet &Elts) =0;
89 };
90
91 private:
92 // Map set defs to their fully expanded contents. This serves as a memoization
93 // cache and it makes it possible to return const references on queries.
94 typedef std::map<Record*, RecVec> ExpandMap;
95 ExpandMap Expansions;
96
97 // Known DAG operators by name.
98 StringMap<std::unique_ptr<Operator>> Operators;
99
100 // Typed expanders by class name.
101 StringMap<std::unique_ptr<Expander>> Expanders;
102
103 public:
104 /// Create a SetTheory instance with only the standard operators.
105 SetTheory();
106
107 /// addExpander - Add an expander for Records with the named super class.
108 void addExpander(StringRef ClassName, std::unique_ptr<Expander>);
109
110 /// addFieldExpander - Add an expander for ClassName that simply evaluates
111 /// FieldName in the Record to get the set elements. That is all that is
112 /// needed for a class like:
113 ///
114 /// class Set<dag d> {
115 /// dag Elts = d;
116 /// }
117 ///
118 void addFieldExpander(StringRef ClassName, StringRef FieldName);
119
120 /// addOperator - Add a DAG operator.
121 void addOperator(StringRef Name, std::unique_ptr<Operator>);
122
123 /// evaluate - Evaluate Expr and append the resulting set to Elts.
124 void evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc);
125
126 /// evaluate - Evaluate a sequence of Inits and append to Elts.
127 template<typename Iter>
128 void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef<SMLoc> Loc) {
129 while (begin != end)
130 evaluate(*begin++, Elts, Loc);
131 }
132
133 /// expand - Expand a record into a set of elements if possible. Return a
134 /// pointer to the expanded elements, or NULL if Set cannot be expanded
135 /// further.
136 const RecVec *expand(Record *Set);
137 };
在SetTheory的构造函数里,所有有关的运算类对象都向它注册:
247 SetTheory::SetTheory() {
248 addOperator("add", llvm::make_unique<AddOp>());
249 addOperator("sub", llvm::make_unique<SubOp>());
250 addOperator("and", llvm::make_unique<AndOp>());
251 addOperator("shl", llvm::make_unique<ShlOp>());
252 addOperator("trunc", llvm::make_unique<TruncOp>());
253 addOperator("rotl", llvm::make_unique<RotOp>(false));
254 addOperator("rotr", llvm::make_unique<RotOp>(true));
255 addOperator("decimate", llvm::make_unique<DecimateOp>());
256 addOperator("interleave", llvm::make_unique<InterleaveOp>());
257 addOperator("sequence", llvm::make_unique<SequenceOp>());
258 }
方法addOperator()的第一个参数就是执行操作符的名称。
260 void SetTheory::addOperator(StringRef Name, std::unique_ptr<Operator> Op) {
261 Operators[Name] = std::move(Op);
262 }
负责提供处理功能的对象则都是上面69行SetTheory内置类Operator的派生类。
除了Operator,SetTheory还存在Expander这个概念。就处理内容来说,Operator与Expandor没有区别,都是(op …)这样的dag值。唯一的区别是,Expandor用于会反复访问的dag值,它的结果将被保存下来,供以后访问使用。目前使用Expandor的实例有:RegisterClass的MemberList,CalleeSavedRegs的SaveList以及TupleExpander。SetTheory通过下面的方法绑定Expandor。
264 void SetTheory::addExpander(StringRef ClassName, std::unique_ptr<Expander> E) {
265 Expanders[ClassName] = std::move(E);
266 }
267
268 void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) {
269 addExpander(ClassName, llvm::make_unique<FieldExpander>(FieldName));
270 }
执行Expandor的入口是SetTheory::expand()方法,SetTheory的Expansions容器用于保存展开后的结果,这样只要处理一次,就可以重复使用结果。参数Set是潜在的、需要展开处理的域。
298 const RecVec *SetTheory::expand(Record *Set) {
299 // Check existing entries for Set and return early.
300 ExpandMap::iterator I = Expansions.find(Set);
301 if (I != Expansions.end())
302 return &I->second;
303
304 // This is the first time we see Set. Find a suitable expander.
305 ArrayRef<Record *> SC = Set->getSuperClasses();
306 for (unsigned i = 0, e = SC.size(); i != e; ++i) {
307 // Skip unnamed superclasses.
308 if (!dyn_cast<StringInit>(SC[i]->getNameInit()))
309 continue;
310 auto I = Expanders.find(SC[i]->getName());
311 if (I != Expanders.end()) {
312 // This breaks recursive definitions.
313 RecVec &EltVec = Expansions[Set];
314 RecSet Elts;
315 I->second->expand(*this, Set, Elts);
316 EltVec.assign(Elts.begin(), Elts.end());
317 return &EltVec;
318 }
319 }
320
321 // Set is not expandable.
322 return nullptr;
323 }
如果这个域绑定了一个Expandor,那么在315行调用相应Expandor的expand方法。RegisterClass与CalleeSavedRegs使用的FieldExpander实际上与对应Operator派生类的处理相同。TupleExpander后面来看。
231 struct FieldExpander : public SetTheory::Expander {
232 StringRef FieldName;
233
234 FieldExpander(StringRef fn) : FieldName(fn) {}
235
236 void expand(SetTheory &ST, Record *Def, RecSet &Elts) override {
237 ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc());
238 }
239 };
SetTheory::expand()与SetTheory::evaluate()都被设计为对不是处理的对象人畜无害(277行),一旦发现要处理的对象,则通过expand()方法(Expandor)或apply()方法(Operator)来处理。
272 void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
273 // A def in a list can be a just an element, or it may expand.
274 if (DefInit *Def = dyn_cast<DefInit>(Expr)) {
275 if (const RecVec *Result = expand(Def->getDef()))
276 return Elts.insert(Result->begin(), Result->end());
277 Elts.insert(Def->getDef());
278 return;
279 }
280
281 // Lists simply expand.
282 if (ListInit *LI = dyn_cast<ListInit>(Expr))
283 return evaluate(LI->begin(), LI->end(), Elts, Loc);
284
285 // Anything else must be a DAG.
286 DagInit *DagExpr = dyn_cast<DagInit>(Expr);
287 if (!DagExpr)
288 PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString());
289 DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator());
290 if (!OpInit)
291 PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString());
292 auto I = Operators.find(OpInit->getDef()->getName());
293 if (I == Operators.end())
294 PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString());
295 I->second->apply(*this, DagExpr, Elts, Loc);
296 }
Operator总是作为dag值的操作符出现的,因此对Operator而言,evaluate()递归到最后,一定会调用295行的apply()方法。以AddOp为例,它的apply()是这个样子:
29 struct AddOp : public SetTheory::Operator {
30 void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
31 ArrayRef<SMLoc> Loc) override {
32 ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc);
33 }
34 };
它与FieldExpander的expand()方法及其类似,事实上功能也是相同的,只不过Expandor保存结果。其他Operator的apply()定义都不复杂,我们不再深入。
注意,SetTheory::evaluate()最终一定是从276或277行结束递归的。另外,SetTheory只是一个辅助类,通过evaluate()或expand()方法将结果返回给真正的主角—— CodeGenTarget与CodeGenRegBank。
3.3.3. CodeGenTarget
RegisterInfoEmitter::Run()在1475行调用了下面的CodeGenTarget构造函数。CodeGenTarget对应TD描述中的Target定义。一个特定的目标机器只能有一个Target派生定义。这个Target派生定义的Record对象由CodeGenTarget的成员TargetRec保存。
137 CodeGenTarget::CodeGenTarget(RecordKeeper &records)
138 : Records(records), CGH(records) {
139 std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
140 if (Targets.size() == 0)
141 PrintFatalError("ERROR: No 'Target' subclasses defined!");
142 if (Targets.size() != 1)
143 PrintFatalError("ERROR: Multiple subclasses of Target defined!");
144 TargetRec = Targets[0];
145 }
CodeGenTarget最重要的成员是类型为mutable std::unique_ptr<CodeGenRegBank>的RegBank。它用于描述目标机器寄存器以及寄存器之间的关系。
3.3.3.1. V7.0的扩展——CodeGenHwModes
V7.0向CodeGenTarget的定义增加了一个描述硬件模式的成员CGH,它的类型定义如下:
42 struct CodeGenHwModes {
43 enum : unsigned { DefaultMode = 0 };
44 static StringRef DefaultModeName;
45
46 CodeGenHwModes(RecordKeeper &R);
47 unsigned getHwModeId(StringRef Name) const;
48 const HwMode &getMode(unsigned Id) const {
49 assert(Id != 0 && "Mode id of 0 is reserved for the default mode");
50 return Modes[Id-1];
51 }
52 const HwModeSelect &getHwModeSelect(Record *R) const;
53 unsigned getNumModeIds() const { return Modes.size()+1; }
54 void dump() const;
55
56 private:
57 RecordKeeper &Records;
58 StringMap<unsigned> ModeIds; // HwMode (string) -> HwModeId
59 std::vector<HwMode> Modes;
60 std::map<Record*,HwModeSelect> ModeSelects;
61 };
CodeGenHwModes的构造函数则定义如下。它收集HwMode与HwModeSelect的TD定义,创建对应的CodeGen定义实例,并保存在相应的容器中。
55 CodeGenHwModes::CodeGenHwModes(RecordKeeper &RK) : Records(RK) {
56 std::vector<Record*> MRs = Records.getAllDerivedDefinitions("HwMode");
57 // The default mode needs a definition in the .td sources for TableGen
58 // to accept references to it. We need to ignore the definition here.
59 for (auto I = MRs.begin(), E = MRs.end(); I != E; ++I) {
60 if ((*I)->getName() != DefaultModeName)
61 continue;
62 MRs.erase(I);
63 break;
64 }
65
66 for (Record *R : MRs) {
67 Modes.emplace_back(R);
68 unsigned NewId = Modes.size();
69 ModeIds.insert(std::make_pair(Modes[NewId-1].Name, NewId));
70 }
71
72 std::vector<Record*> MSs = Records.getAllDerivedDefinitions("HwModeSelect");
73 for (Record *R : MSs) {
74 auto P = ModeSelects.emplace(std::make_pair(R, HwModeSelect(R, *this)));
75 assert(P.second);
76 (void)P;
77 }
78 }
69行的ModeIds用于将模式名映射到ID,这个ID是HwMode实例在Modes容器里的索引。
67行调用HwMode的构造函数,74行调用HwModeSelect的构造函数。其中,相关定义如下:
28 struct HwMode {
29 HwMode(Record *R);
30 StringRef Name;
31 std::string Features;
32 void dump() const;
33 };
34
35 struct HwModeSelect {
36 HwModeSelect(Record *R, CodeGenHwModes &CGH);
37 typedef std::pair<unsigned, Record*> PairType;
38 std::vector<PairType> Items;
39 void dump() const;
40 };
HwMode的定义与TD文件里的是一致的:
22 HwMode::HwMode(Record *R) {
23 Name = R->getName();
24 Features = R->getValueAsString("Features");
25 }
TD文件中HwModeSelect是作为基类使用的,因此调用下面HwModeSelect构造函数的应该是TD文件里的ValueTypeByHwMode与RegInfoByHwMode定义。在这些对应中域Modes与Objects应该是一一对应的。
32 HwModeSelect::HwModeSelect(Record *R, CodeGenHwModes &CGH) {
33 std::vector<Record*> Modes = R->getValueAsListOfDefs("Modes");
34 std::vector<Record*> Objects = R->getValueAsListOfDefs("Objects");
35 if (Modes.size() != Objects.size()) {
36 PrintError(R->getLoc(), "in record " + R->getName() +
37 " derived from HwModeSelect: the lists Modes and Objects should "
38 "have the same size");
39 report_fatal_error("error in target description.");
40 }
41 for (unsigned i = 0, e = Modes.size(); i != e; ++i) {
42 unsigned ModeId = CGH.getHwModeId(Modes[i]->getName());
43 Items.push_back(std::make_pair(ModeId, Objects[i]));
44 }
45 }
43行的Items是HwModeSelect 类型为std::pair<unsigned, Record*>的容器,它将模式的ID与Objects域里的内容关联起来(即指定硬件模式选中什么)。
构造好的CGH实例将在下面作为引用传递给CodeGenRegBank对象。
3.3.4. CodeGenRegBank
CodeGenTarget::getRegBank()方法为CodeGenTarget实例返回一个CodeGenRegBank对象。213行的llvm::make_unique等同于C++11的std::unique_ptr。
211 CodeGenRegBank &CodeGenTarget::getRegBank() const {
212 if (!RegBank)
213 RegBank = llvm::make_unique<CodeGenRegBank>(Records, getHwModes());
214 return *RegBank;
215 }
在213行v7.0增加了对CodeGenTarget::getHwModes()的调用,获取其CGH引用。
CodeGenRegBank的构造函数中会建立描述目标机器寄存器以及寄存器之间关系的数据结构。CodeGenRegBank定义里有一个SetTheory类型的成员Sets。因此在执行CodeGenRegBank构造函数时,会隐含执行SetTheory的构造函数,同时它还注册了所需的Expandor。
923 CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
const CodeGenHwModes &Modes) : CGH(Modes) { <-- v7.0添加
924 // Configure register Sets to understand register classes and tuples.
925 Sets.addFieldExpander("RegisterClass", "MemberList");
926 Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
927 Sets.addExpander("RegisterTuples", llvm::make_unique<TupleExpander>()); <-- v7.0删除
Sets.addExpander("RegisterTuples", <-- v7.0添加
llvm::make_unique<TupleExpander>(SynthDefs));
928
929 // Read in the user-defined (named) sub-register indices.
930 // More indices will be synthesized later.
931 std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex");
932 std::sort(SRIs.begin(), SRIs.end(), LessRecord());
933 for (unsigned i = 0, e = SRIs.size(); i != e; ++i)
934 getSubRegIdx(SRIs[i]);
935 // Build composite maps from ComposedOf fields.
936 for (auto &Idx : SubRegIndices)
937 Idx.updateComponents(*this);
938
939 // Read in the register definitions.
940 std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
941 std::sort(Regs.begin(), Regs.end(), LessRecordRegister());
942 // Assign the enumeration values.
943 for (unsigned i = 0, e = Regs.size(); i != e; ++i)
944 getReg(Regs[i]);
945
946 // Expand tuples and number the new registers.
947 std::vector<Record*> Tups =
948 Records.getAllDerivedDefinitions("RegisterTuples");
949
950 for (Record *R : Tups) {
951 std::vector<Record *> TupRegs = *Sets.expand(R);
952 std::sort(TupRegs.begin(), TupRegs.end(), LessRecordRegister());
953 for (Record *RC : TupRegs)
954 getReg(RC);
955 }
956
957 // Now all the registers are known. Build the object graph of explicit
958 // register-register references.
959 for (auto &Reg : Registers)
960 Reg.buildObjectGraph(*this);
961
962 // Compute register name map.
963 for (auto &Reg : Registers)
964 // FIXME: This could just be RegistersByName[name] = register, except that
965 // causes some failures in MIPS - perhaps they have duplicate register name
966 // entries? (or maybe there's a reason for it - I don't know much about this
967 // code, just drive-by refactoring)
968 RegistersByName.insert(
969 std::make_pair(Reg.TheDef->getValueAsString("AsmName"), &Reg));
970
971 // Precompute all sub-register maps.
972 // This will create Composite entries for all inferred sub-register indices.
973 for (auto &Reg : Registers)
974 Reg.computeSubRegs(*this);
975
976 // Infer even more sub-registers by combining leading super-registers.
977 for (auto &Reg : Registers)
978 if (Reg.CoveredBySubRegs)
979 Reg.computeSecondarySubRegs(*this);
980
// Compute transitive closure of subregister index ConcatenationOf vectors <-- v7.0增加
// and initialize ConcatIdx map.
for (CodeGenSubRegIndex &SRI : SubRegIndices) {
SRI.computeConcatTransitiveClosure();
if (!SRI.ConcatenationOf.empty())
ConcatIdx.insert(std::make_pair(
SmallVector<CodeGenSubRegIndex*,8>(SRI.ConcatenationOf.begin(),
SRI.ConcatenationOf.end()), &SRI));
}
981 // After the sub-register graph is complete, compute the topologically
982 // ordered SuperRegs list.
983 for (auto &Reg : Registers)
984 Reg.computeSuperRegs(*this);
985
// For each pair of Reg:SR, if both are non-artificial, mark the <-- v7.0增加
// corresponding sub-register index as non-artificial.
for (auto &Reg : Registers) {
if (Reg.Artificial)
continue;
for (auto P : Reg.getSubRegs()) {
const CodeGenRegister *SR = P.second;
if (!SR->Artificial)
P.first->Artificial = false;
}
}
986 // Native register units are associated with a leaf register. They've all been
987 // discovered now.
988 NumNativeRegUnits = RegUnits.size();
989
990 // Read in register class definitions.
991 std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
992 if (RCs.empty())
993 PrintFatalError("No 'RegisterClass' subclasses defined!");
994
995 // Allocate user-defined register classes.
996 for (auto *RC : RCs) {
997 RegClasses.emplace_back(*this, RC);
998 addToMaps(&RegClasses.back());
999 }
1000
1001 // Infer missing classes to create a full algebra.
1002 computeInferredRegisterClasses();
1003
1004 // Order register classes topologically and assign enum values.
1005 RegClasses.sort(TopoOrderRC);
1006 unsigned i = 0;
1007 for (auto &RC : RegClasses)
1008 RC.EnumValue = i++;
1009 CodeGenRegisterClass::computeSubClasses(*this);
1010 }
上面CodeGenRegBank的getReg()、getSubRegIdx()方法将寄存器及寄存器索引的DAG对象保存在容器Registers(std::deque<CodeGenRegister>)以及容器SubRegIndices(std::deque<CodeGenSubRegIndex>)里。寄存器类别则直接使用容器RegClasses(std::list< CodeGenRegisterClass>)保存。
932行的LessRecord对SubRegIndex派生定义按它们名字字母序升序排序(如果名字中包含数字串,按代表的数值升序排序),因为这样最基本的索引最有可能出现在前面。
V7.0在CodeGenRegBank中引入了容器SynthDefs(类型std::vector<std::unique_ptr<Record>>)用于保存RegisterTuples展开时得到的寄存器Record对象。这样避免像v3.6.1里重复生成寄存器Record对象。
3.3.4.1. 复合索引
前面提到通常寄存器定义无需指定ComposedOf与CoveringSubRegIndices这两个域,TableGen可以自己推导。但在复杂情形下则需要明确给出索引的复合关系,比如前面ARM的例子一节中给出的例子,dsub_3由qsub_1与dsub_1复合得到,它用于表示一个寄存器偏移192、长度64字节的可援引部分(子寄存器)。
56 void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
57 if (!TheDef)
58 return;
59
60 std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
61 if (!Comps.empty()) {
62 if (Comps.size() != 2)
63 PrintFatalError(TheDef->getLoc(),
64 "ComposedOf must have exactly two entries");
65 CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
66 CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
67 CodeGenSubRegIndex *X = A->addComposite(B, this);
68 if (X)
69 PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
70 }
71
72 std::vector<Record*> Parts =
73 TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
74 if (!Parts.empty()) {
75 if (Parts.size() < 2)
76 PrintFatalError(TheDef->getLoc(),
77 "CoveredBySubRegs must have two or more entries");
78 SmallVector<CodeGenSubRegIndex*, 8> IdxParts;
79 for (unsigned i = 0, e = Parts.size(); i != e; ++i)
80 IdxParts.push_back(RegBank.getSubRegIdx(Parts[i]));
81 RegBank.addConcatSubRegIndex(IdxParts, this); <-- v7.0删除
setConcatenationOf(IdxParts); <-- v7.0增加
82 }
83 }
寄存器索引的DAG类是CodeGenSubRegIndex,为了快速从寄存器索引的Record对象找到对应的CodeGenSubRegIndex实例,CodeGenRegBank定义了容器Def2SubRegIdx(类型DenseMap<Record*, CodeGenRegister*>)。CodeGenSubRegIndex::updateComponents() 65行的getSubRegIdx方法利用该容器查找子寄存器Record对象对应的CodeGenSubRegIndex实例(类似的,对Register有Def2Reg快速查找容器及getReg方法,对RegisterClass有Def2RC快速查找容器及getRegClass方法):
1019 CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
1020 CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
1021 if (Idx)
1022 return Idx;
1023 SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);
1024 Idx = &SubRegIndices.back();
1025 return Idx;
1026 }
CodeGenSubRegIndex使用std::map<CodeGenSubRegIndex*, CodeGenSubRegIndex*, deref<llvm:: less>>类型的容器Composed来记录由自己牵头的复合索引。容器的第一个项是另一个组成索引,第二项是得到的复合索引。之所以这样,为了能够检查是否出现了具有歧义的复合定义,另外在后面CodeGenRegister::computeSubRegs的处理中,这样的结构是有利的。
因此在67行,第一个组成索引使用addComposite方法向Composed容器添加这个复合索引记录。
90 CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A,
91 CodeGenSubRegIndex *B) {
92 assert(A && B);
93 std::pair<CompMap::iterator, bool> Ins =
94 Composed.insert(std::make_pair(A, B));
95 // Synthetic subreg indices that aren't contiguous (for instance ARM
96 // register tuples) don't have a bit range, so it's OK to let
97 // B->Offset == -1. For the other cases, accumulate the offset and set
98 // the size here. Only do so if there is no offset yet though.
99 if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) &&
100 (B->Offset == (uint16_t)-1)) {
101 B->Offset = Offset + A->Offset;
102 B->Size = A->Size;
103 }
104 return (Ins.second || Ins.first->second == B) ? nullptr
105 : Ins.first->second;
106 }
CoveringSubRegIndices可用于描述哪些索引包含了当前的索引。不过,通常TableGen能自动推导出这些SubRegIndex,不需要明确给出(后面会看到这个过程)。
CodeGenRegBank有一个std::map<SmallVector<CodeGenSubRegIndex*, 8>, CodeGenSubRegIndex*>类型的容器ConcatIdx,用于记录这些索引对应子寄存器包含的子寄存器索引。
V7.0在CoveringSubRegIndices在增加了容器ConcatenationOf(类型SmallVector< CodeGenSubRegIndex*, 4>),用于保存串联成这个CodeGenSubRegIndex的CodeGenSubRegIndex。它是CodeGenRegBank::ConcatIdx的逆
3.3.4.2. Register DAG
3.3.4.2.1. 寄存器的表示
回到CodeGenRegBank构造函数。接下来处理Register与RegisterTuples。类LessRecordRegister类似的,按名字的字母、数字序升序排序寄存器定义。对所有寄存器定义,通过getReg方法向容器Registers添加DAG对象(CodeGenRegister实例)。
至RegisterTuples定义,已经注册的TupleExpander是它的专属,因此调用SetTheory::expand()方法来召唤它的expand()方法:
541 struct TupleExpander : SetTheory::Expander {
542 void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) override {
543 std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices");
544 unsigned Dim = Indices.size();
545 ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
546 if (Dim != SubRegs->size())
547 PrintFatalError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch");
548 if (Dim < 2)
549 PrintFatalError(Def->getLoc(),
550 "Tuples must have at least 2 sub-registers");
551
552 // Evaluate the sub-register lists to be zipped.
553 unsigned Length = ~0u;
554 SmallVector<SetTheory::RecSet, 4> Lists(Dim);
555 for (unsigned i = 0; i != Dim; ++i) {
556 ST.evaluate(SubRegs->getElement(i), Lists[i], Def->getLoc());
557 Length = std::min(Length, unsigned(Lists[i].size()));
558 }
559
560 if (Length == 0)
561 return;
562
563 // Precompute some types.
564 Record *RegisterCl = Def->getRecords().getClass("Register");
565 RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
566 StringInit *BlankName = StringInit::get("");
567
568 // Zip them up.
569 for (unsigned n = 0; n != Length; ++n) {
570 std::string Name;
571 Record *Proto = Lists[0][n];
572 std::vector<Init*> Tuple;
573 unsigned CostPerUse = 0;
574 for (unsigned i = 0; i != Dim; ++i) {
575 Record *Reg = Lists[i][n];
576 if (i) Name += '_';
577 Name += Reg->getName();
578 Tuple.push_back(DefInit::get(Reg));
579 CostPerUse = std::max(CostPerUse,
580 unsigned(Reg->getValueAsInt("CostPerUse")));
581 }
582
583 // Create a new Record representing the synthesized register. This record
584 // is only for consumption by CodeGenRegister, it is not added to the
585 // RecordKeeper.
586 Record *NewReg = new Record(Name, Def->getLoc(), Def->getRecords()); <-- v7.0删除
// Create a new Record representing the synthesized register. This record <-- v7.0增加
// is only for consumption by CodeGenRegister, it is not added to the
// RecordKeeper.
SynthDefs.emplace_back(
llvm::make_unique<Record>(Name, Def->getLoc(), Def->getRecords()));
Record *NewReg = SynthDefs.back().get();
587 Elts.insert(NewReg);
588
589 // Copy Proto super-classes.
590 ArrayRef<Record *> Supers = Proto->getSuperClasses();
591 ArrayRef<SMRange> Ranges = Proto->getSuperClassRanges();
592 for (unsigned i = 0, e = Supers.size(); i != e; ++i)
593 NewReg->addSuperClass(Supers[i], Ranges[i]);
594
595 // Copy Proto fields.
596 for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) {
597 RecordVal RV = Proto->getValues()[i];
598
599 // Skip existing fields, like NAME.
600 if (NewReg->getValue(RV.getNameInit()))
601 continue;
602
603 StringRef Field = RV.getName();
604
605 // Replace the sub-register list with Tuple.
606 if (Field == "SubRegs")
607 RV.setValue(ListInit::get(Tuple, RegisterRecTy));
608
609 // Provide a blank AsmName. MC hacks are required anyway.
610 if (Field == "AsmName")
611 RV.setValue(BlankName);
612
613 // CostPerUse is aggregated from all Tuple members.
614 if (Field == "CostPerUse")
615 RV.setValue(IntInit::get(CostPerUse));
616
617 // Composite registers are always covered by sub-registers.
618 if (Field == "CoveredBySubRegs")
619 RV.setValue(BitInit::get(true));
620
621 // Copy fields from the RegisterTuples def.
622 if (Field == "SubRegIndices" ||
623 Field == "CompositeIndices") {
624 NewReg->addValue(*Def->getValue(Field));
625 continue;
626 }
627
628 // Some fields get their default uninitialized value.
629 if (Field == "DwarfNumbers" ||
630 Field == "DwarfAlias" ||
631 Field == "Aliases") {
632 if (const RecordVal *DefRV = RegisterCl->getValue(Field))
633 NewReg->addValue(*DefRV);
634 continue;
635 }
636
637 // Everything else is copied from Proto.
638 NewReg->addValue(RV);
639 }
640 }
641 }
642 };
554行的SetTheory::RecSet是std::vector<Record*>的typedef。556行通过SetTheory::evaluate()方法对RegisterTuples的SubRegs域中包含的表达式进行求值,获取对应的Register列表,然后在569~640行的循环里将这些列表中的对应的寄存器合成为一个超级寄存器(参考ARM的例子一节的例子)。
在生成了所有的CodeGenRegister实例后,在CodeGenRegBank构造函数的959行逐个调用它们的buildObjectGraph()方法,进一步完善生成的DAG:
117 void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
118 std::vector<Record*> SRIs = TheDef->getValueAsListOfDefs("SubRegIndices");
119 std::vector<Record*> SRs = TheDef->getValueAsListOfDefs("SubRegs");
120
121 if (SRIs.size() != SRs.size())
122 PrintFatalError(TheDef->getLoc(),
123 "SubRegs and SubRegIndices must have the same size");
124
125 for (unsigned i = 0, e = SRIs.size(); i != e; ++i) {
126 ExplicitSubRegIndices.push_back(RegBank.getSubRegIdx(SRIs[i]));
127 ExplicitSubRegs.push_back(RegBank.getReg(SRs[i]));
128 }
129
130 // Also compute leading super-registers. Each register has a list of
131 // covered-by-subregs super-registers where it appears as the first explicit
132 // sub-register.
133 //
134 // This is used by computeSecondarySubRegs() to find candidates.
135 if (CoveredBySubRegs && !ExplicitSubRegs.empty())
136 ExplicitSubRegs.front()->LeadingSuperRegs.push_back(this);
137
138 // Add ad hoc alias links. This is a symmetric relationship between two
139 // registers, so build a symmetric graph by adding links in both ends.
140 std::vector<Record*> Aliases = TheDef->getValueAsListOfDefs("Aliases");
141 for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
142 CodeGenRegister *Reg = RegBank.getReg(Aliases[i]);
143 ExplicitAliases.push_back(Reg);
144 Reg->ExplicitAliases.push_back(this);
145 }
146 }
CodeGenRegister使用容器:ExplicitSubRegIndices(SmallVector<CodeGenSubRegIndex*, 8>)以及ExplicitSubRegs(SmallVector<CodeGenRegister*, 8>)来记录对应的子寄存器索引与子寄存器。
135行的CoveredBySubRegs是Register定义中CoveredBySubRegs的值,它如果不为0,表示它的子寄存器能完全覆盖它所有的比特位。在这种情况下,第一个子寄存器的CodeGenRegister实例使用LeadingSuperRegs容器(std::vector<const CodeGenRegister*>)把当前的CodeGenRegister实例记录成自己作为起始的上级寄存器。
另外,同一个寄存器的不同Register定义视做互为“别名”(ARMRegisterInfo.td中有一个例子),这由Register定义中的Aliases域来描述。具体到CodeGenRegister则通过容器ExplicitAliases(类型SmallVector<CodeGenRegister*, 8>)来记录。
3.3.4.2.2. 构建子寄存器关系
CodeGenRegBank的容器RegistersByName(StringMap<CodeGenRegister*>)用于将寄存器名关联到CodeGenRegister实例,963行循环完成这个关联。接着,在974行对所有的CodeGenRegister对象,调用方法computeSubRegs()来推导它们的子寄存器组成。
CodeGenRegister使用容器SubRegs(std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref< llvm::less>>)记录包含的子寄存器。另外,容器SubReg2Idx(DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*>)关联子寄存器与子寄存器索引。
因此,computeSubRegs()的第一步根据上面准备的ExplicitSubRegs与ExplicitSubRegIndices容器,关联起子寄存器与子寄存器索引。
214 const CodeGenRegister::SubRegMap &
215 CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
216 // Only compute this map once.
217 if (SubRegsComplete)
218 return SubRegs;
219 SubRegsComplete = true;
220
221 HasDisjunctSubRegs = ExplicitSubRegs.size() > 1;
222
223 // First insert the explicit subregs and make sure they are fully indexed.
224 for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
225 CodeGenRegister *SR = ExplicitSubRegs[i];
226 CodeGenSubRegIndex *Idx = ExplicitSubRegIndices[i];
if (!SR->Artificial) <-- v7.0增加
Idx->Artificial = false;
227 if (!SubRegs.insert(std::make_pair(Idx, SR)).second)
228 PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() +
229 " appears twice in Register " + getName());
230 // Map explicit sub-registers first, so the names take precedence.
231 // The inherited sub-registers are mapped below.
232 SubReg2Idx.insert(std::make_pair(SR, Idx));
233 }
234
235 // Keep track of inherited subregs and how they can be reached.
236 SmallPtrSet<CodeGenRegister*, 8> Orphans;
237
238 // Clone inherited subregs and place duplicate entries in Orphans.
239 // Here the order is important - earlier subregs take precedence.
240 for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
241 CodeGenRegister *SR = ExplicitSubRegs[i];
242 const SubRegMap &Map = SR->computeSubRegs(RegBank);
243 HasDisjunctSubRegs |= SR->HasDisjunctSubRegs;
244
245 for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
246 ++SI) {
247 if (!SubRegs.insert(*SI).second)
248 Orphans.insert(SI->second);
249 }
250 }
251
252 // Expand any composed subreg indices.
253 // If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a
254 // qsub_1 subreg, add a dsub_2 subreg. Keep growing Indices and process
255 // expanded subreg indices recursively.
256 SmallVector<CodeGenSubRegIndex*, 8> Indices = ExplicitSubRegIndices;
257 for (unsigned i = 0; i != Indices.size(); ++i) {
258 CodeGenSubRegIndex *Idx = Indices[i];
259 const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites();
260 CodeGenRegister *SR = SubRegs[Idx];
261 const SubRegMap &Map = SR->computeSubRegs(RegBank);
262
263 // Look at the possible compositions of Idx.
264 // They may not all be supported by SR.
265 for (CodeGenSubRegIndex::CompMap::const_iterator I = Comps.begin(),
266 E = Comps.end(); I != E; ++I) {
267 SubRegMap::const_iterator SRI = Map.find(I->first);
268 if (SRI == Map.end())
269 continue; // Idx + I->first doesn't exist in SR.
270 // Add I->second as a name for the subreg SRI->second, assuming it is
271 // orphaned, and the name isn't already used for something else.
272 if (SubRegs.count(I->second) || !Orphans.erase(SRI->second))
273 continue;
274 // We found a new name for the orphaned sub-register.
275 SubRegs.insert(std::make_pair(I->second, SRI->second));
276 Indices.push_back(I->second);
277 }
278 }
279
280 // Now Orphans contains the inherited subregisters without a direct index.
281 // Create inferred indexes for all missing entries.
282 // Work backwards in the Indices vector in order to compose subregs bottom-up.
283 // Consider this subreg sequence:
284 //
285 // qsub_1 -> dsub_0 -> ssub_0
286 //
287 // The qsub_1 -> dsub_0 composition becomes dsub_2, so the ssub_0 register
288 // can be reached in two different ways:
289 //
290 // qsub_1 -> ssub_0
291 // dsub_2 -> ssub_0
292 //
293 // We pick the latter composition because another register may have [dsub_0,
294 // dsub_1, dsub_2] subregs without necessarily having a qsub_1 subreg. The
295 // dsub_2 -> ssub_0 composition can be shared.
296 while (!Indices.empty() && !Orphans.empty()) {
297 CodeGenSubRegIndex *Idx = Indices.pop_back_val();
298 CodeGenRegister *SR = SubRegs[Idx];
299 const SubRegMap &Map = SR->computeSubRegs(RegBank);
300 for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
301 ++SI)
302 if (Orphans.erase(SI->second))
303 SubRegs[RegBank.getCompositeSubRegIndex(Idx, SI->first)] = SI->second;
304 }
305
306 // Compute the inverse SubReg -> Idx map.
307 for (SubRegMap::const_iterator SI = SubRegs.begin(), SE = SubRegs.end();
308 SI != SE; ++SI) {
309 if (SI->second == this) {
310 ArrayRef<SMLoc> Loc;
311 if (TheDef)
312 Loc = TheDef->getLoc();
313 PrintFatalError(Loc, "Register " + getName() +
314 " has itself as a sub-register");
315 }
316
317 // Compute AllSuperRegsCovered.
318 if (!CoveredBySubRegs)
319 SI->first->AllSuperRegsCovered = false;
320
321 // Ensure that every sub-register has a unique name.
322 DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*>::iterator Ins =
323 SubReg2Idx.insert(std::make_pair(SI->second, SI->first)).first;
324 if (Ins->second == SI->first)
325 continue;
326 // Trouble: Two different names for SI->second.
327 ArrayRef<SMLoc> Loc;
328 if (TheDef)
329 Loc = TheDef->getLoc();
330 PrintFatalError(Loc, "Sub-register can't have two names: " +
331 SI->second->getName() + " available as " +
332 SI->first->getName() + " and " + Ins->second->getName());
333 }
334
335 // Derive possible names for sub-register concatenations from any explicit
336 // sub-registers. By doing this before computeSecondarySubRegs(), we ensure
337 // that getConcatSubRegIndex() won't invent any concatenated indices that the
338 // user already specified.
339 for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
340 CodeGenRegister *SR = ExplicitSubRegs[i];
341 if (!SR->CoveredBySubRegs || SR->ExplicitSubRegs.size() <= 1 ||
SR->Artificial) <-- v7.0增加
342 continue;
343
344 // SR is composed of multiple sub-regs. Find their names in this register.
345 SmallVector<CodeGenSubRegIndex*, 8> Parts;
346 for (unsigned j = 0, e = SR->ExplicitSubRegs.size(); j != e; ++j)
347 Parts.push_back(getSubRegIndex(SR->ExplicitSubRegs[j]));
348
349 // Offer this as an existing spelling for the concatenation of Parts.
350 RegBank.addConcatSubRegIndex(Parts, ExplicitSubRegIndices[i]); <-- v7.0删除
CodeGenSubRegIndex &Idx = *ExplicitSubRegIndices[i]; <-- v7.0增加
Idx.setConcatenationOf(Parts);
351 }
352
353 // Initialize RegUnitList. Because getSubRegs is called recursively, this
354 // processes the register hierarchy in postorder.
355 //
356 // Inherit all sub-register units. It is good enough to look at the explicit
357 // sub-registers, the other registers won't contribute any more units.
358 for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
359 CodeGenRegister *SR = ExplicitSubRegs[i];
360 RegUnits |= SR->RegUnits;
361 }
362
363 // Absent any ad hoc aliasing, we create one register unit per leaf register.
364 // These units correspond to the maximal cliques in the register overlap
365 // graph which is optimal.
366 //
367 // When there is ad hoc aliasing, we simply create one unit per edge in the
368 // undirected ad hoc aliasing graph. Technically, we could do better by
369 // identifying maximal cliques in the ad hoc graph, but cliques larger than 2
370 // are extremely rare anyway (I've never seen one), so we don't bother with
371 // the added complexity.
372 for (unsigned i = 0, e = ExplicitAliases.size(); i != e; ++i) {
373 CodeGenRegister *AR = ExplicitAliases[i];
374 // Only visit each edge once.
375 if (AR->SubRegsComplete)
376 continue;
377 // Create a RegUnit representing this alias edge, and add it to both
378 // registers.
379 unsigned Unit = RegBank.newRegUnit(this, AR);
380 RegUnits.set(Unit);
381 AR->RegUnits.set(Unit);
382 }
383
384 // Finally, create units for leaf registers without ad hoc aliases. Note that
385 // a leaf register with ad hoc aliases doesn't get its own unit - it isn't
386 // necessary. This means the aliasing leaf registers can share a single unit.
387 if (RegUnits.empty())
388 RegUnits.set(RegBank.newRegUnit(this));
389
390 // We have now computed the native register units. More may be adopted later
391 // for balancing purposes.
392 NativeRegUnits = RegUnits;
393
394 return SubRegs;
395 }
前面提到TableGen能根据寄存器与索引的定义推导寄存器间的层次关系,并合成援引孙子寄存器的索引。比如X86的EAX寄存器,它的SubRegs定义为[AX],而AX的SubRegs定义为[AL, AH]。对EAX的定义来说,它不知道[AL, AH]的存在。但在汇编代码里使用AL或AH,都是来自EAX的部分。因此我们需要一个索引来表示AL等在EAX中的位置与大小。
240行以下就是实现这个功能。240行的for循环首先让子寄存器递归调用computeSubRegs()返回自己的子寄存器与索引,将当前寄存器所不知道的孙子寄存器及其索引记录到Orphans容器。
如果寄存器索引定义中明确使用了ComposedOf来说明组成的索引,我们需要确保组成索引所对应的寄存器及其子寄存器,如果是复合索引所对应寄存器的子寄存器,它们被正确记录。接着257行的for循环执行这个操作。
如果在296行Orphans还存有寄存器,这表示这些寄存器还没有关联索引,那么从已有的索引出发(保存在Indices容器里),遍历所有可能的子索引,找出与Orphans中寄存器对应的索引,并调用下面的方法合成所需的索引(也就是前面提到的推导)。
1071 CodeGenSubRegIndex*
1072 CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
1073 CodeGenSubRegIndex *B) {
1074 // Look for an existing entry.
1075 CodeGenSubRegIndex *Comp = A->compose(B);
1076 if (Comp)
1077 return Comp;
1078
1079 // None exists, synthesize one.
1080 std::string Name = A->getName() + "_then_" + B->getName();
1081 Comp = createSubRegIndex(Name, A->getNamespace());
1082 A->addComposite(B, Comp);
1083 return Comp;
1084 }
1013 CodeGenSubRegIndex*
1014 CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) {
1015 SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1);
1016 return &SubRegIndices.back();
1017 }
然后307行循环设置SubReg2Idx容器建立子寄存器到索引的映射。
如果寄存器有多级子寄存器可作为独立寄存器使用,且每级有多个子寄存器,那么可能存在寄存器定义中没有(难以)给出的可用子寄存器,339行循环为下面computeSecondarySubRegs()中推导这些可用的子寄存器做准备。另外,346行循环将这些个子寄存器的子寄存器索引记录下来,在下面用于隐含孙子寄存器的推导。
最后的代码片段使用了两个RegUnits容器。其一来自CodeGenRegBank,类型是SmallVector< RegUnit, 8>。它用于寄存器压力与干扰模型。
每个最小可援引寄存器部分将分配一个独立的RegUnit实例,其他寄存器继承子寄存器RegUnit。
RegUnit有以下的定义,其中成员Weight用于估算寄存器压力:
435 struct RegUnit {
436 // Weight assigned to this RegUnit for estimating register pressure.
437 // This is useful when equalizing weights in register classes with mixed
438 // register topologies.
439 unsigned Weight;
440
441 // Each native RegUnit corresponds to one or two root registers. The full
442 // set of registers containing this unit can be computed as the union of
443 // these two registers and their super-registers.
444 const CodeGenRegister *Roots[2];
445
446 // Index into RegClassUnitSets where we can find the list of UnitSets that
447 // contain this unit.
448 unsigned RegClassUnitSetsIdx;
// A register unit is artificial if at least one of its roots is <-- v7.0增加
// artificial.
bool Artificial;
449
450 RegUnit() : Weight(0), RegClassUnitSetsIdx(0) , Artificial(false) {
451 Roots[0] = Roots[1] = nullptr;
452 }
453
454 ArrayRef<const CodeGenRegister*> getRoots() const {
455 assert(!(Roots[1] && !Roots[0]) && "Invalid roots array");
456 return makeArrayRef(Roots, !!Roots[0] + !!Roots[1]);
457 }
458 };
方法newRegUnit创建一个RegUnit实例给叶子寄存器。
620 unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = nullptr) {
621 RegUnits.resize(RegUnits.size() + 1);
622 RegUnits.back().Roots[0] = R0;
623 RegUnits.back().Roots[1] = R1;
RU.Artificial = R0->Artificial; <-- v7.0增加
if (R1)
RU.Artificial |= R1->Artificial;
624 return RegUnits.size() - 1;
625 }
上面的RegUnits容器则来自CodeGenRegister,类型是SparseBitVector<>,它实际上保存了对应RegUnit实例在前一个RegUnits容器中的索引。很明显,非叶子寄存器的RegUnit都继承自它的(孙)子寄存器。
3.3.4.2.3. V7.0推导寄存器串接闭包
在v7.0中CodeGenSubRegIndex的容器ConcatenationOf记录了能串联成该寄存器的子寄存器索引。因此,通过下面的方法将里面的子寄存器索引展开为叶子索引。
void CodeGenSubRegIndex::computeConcatTransitiveClosure() {
for (SmallVectorImpl<CodeGenSubRegIndex*>::iterator
I = ConcatenationOf.begin(); I != ConcatenationOf.end(); /*empty*/) {
CodeGenSubRegIndex *SubIdx = *I;
SubIdx->computeConcatTransitiveClosure();
#ifndef NDEBUG
for (CodeGenSubRegIndex *SRI : SubIdx->ConcatenationOf)
assert(SRI->ConcatenationOf.empty() && "No transitive closure?");
#endif
if (SubIdx->ConcatenationOf.empty()) {
++I;
} else {
I = ConcatenationOf.erase(I);
I = ConcatenationOf.insert(I, SubIdx->ConcatenationOf.begin(),
SubIdx->ConcatenationOf.end());
I += SubIdx->ConcatenationOf.size();
}
}
}
3.3.4.2.4. 隐含的孙子寄存器
前面说过,如果寄存器存在比较复杂的多层可用子寄存器,会存在寄存器定义中没有办法给出的可用子寄存器,前面的computeSubRegs()方法已经在CodeGenRegBank的ConcatIdx容器里做好了准备,现在开始调用computeSecondarySubRegs()方法来推导这些隐含的子寄存器。比如从定义:QQ0 = {Q0, Q1}, Q0 = {D0, D1}, Q1 = {D2, D3}, Q2={D1, D2},推断出Q2也是QQ0的子寄存器。另外,还要构建从QQ0到Q2的寄存器索引,以及由此引出的所有子寄存器。
410 void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
411 // Collect new sub-registers first, add them later.
412 SmallVector<SubRegMap::value_type, 8> NewSubRegs;
413
414 // Look at the leading super-registers of each sub-register. Those are the
415 // candidates for new sub-registers, assuming they are fully contained in
416 // this register.
417 for (SubRegMap::iterator I = SubRegs.begin(), E = SubRegs.end(); I != E; ++I){
418 const CodeGenRegister *SubReg = I->second;
419 const CodeGenRegister::SuperRegList &Leads = SubReg->LeadingSuperRegs;
420 for (unsigned i = 0, e = Leads.size(); i != e; ++i) {
421 CodeGenRegister *Cand = const_cast<CodeGenRegister*>(Leads[i]);
422 // Already got this sub-register?
423 if (Cand == this || getSubRegIndex(Cand))
424 continue;
425 // Check if each component of Cand is already a sub-register.
426 // We know that the first component is I->second, and is present with the
427 // name I->first.
428 SmallVector<CodeGenSubRegIndex*, 8> Parts(1, I->first);
429 assert(!Cand->ExplicitSubRegs.empty() &&
430 "Super-register has no sub-registers");
431 for (unsigned j = 1, e = Cand->ExplicitSubRegs.size(); j != e; ++j) {
432 if (CodeGenSubRegIndex *Idx = getSubRegIndex(Cand->ExplicitSubRegs[j]))
433 Parts.push_back(Idx);
434 else {
435 // Sub-register doesn't exist.
436 Parts.clear();
437 break;
438 }
439 }
440 // If some Cand sub-register is not part of this register, or if Cand only
441 // has one sub-register, there is nothing to do.
442 if (Parts.size() <= 1)
443 continue;
444
445 // Each part of Cand is a sub-register of this. Make the full Cand also
446 // a sub-register with a concatenated sub-register index.
447 CodeGenSubRegIndex *Concat= RegBank.getConcatSubRegIndex(Parts);
448 NewSubRegs.push_back(std::make_pair(Concat, Cand));
449 }
450 }
451
452 // Now add all the new sub-registers.
453 for (unsigned i = 0, e = NewSubRegs.size(); i != e; ++i) {
454 // Don't add Cand if another sub-register is already using the index.
455 if (!SubRegs.insert(NewSubRegs[i]).second)
456 continue;
457
458 CodeGenSubRegIndex *NewIdx = NewSubRegs[i].first;
459 CodeGenRegister *NewSubReg = NewSubRegs[i].second;
460 SubReg2Idx.insert(std::make_pair(NewSubReg, NewIdx));
461 }
462
463 // Create sub-register index composition maps for the synthesized indices.
464 for (unsigned i = 0, e = NewSubRegs.size(); i != e; ++i) {
465 CodeGenSubRegIndex *NewIdx = NewSubRegs[i].first;
466 CodeGenRegister *NewSubReg = NewSubRegs[i].second;
467 for (SubRegMap::const_iterator SI = NewSubReg->SubRegs.begin(),
468 SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) {
469 CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second);
470 if (!SubIdx)
471 PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
472 SI->second->getName() + " in " + getName());
473 NewIdx->addComposite(SI->first, SubIdx);
474 }
475 }
476 }
419行的LeadingSuperRegs容器记录了该寄存器作为领头子寄存器的寄存器,其中SuperRegList是std::vector<const CodeGenRegister*>的typedef。以前面的例子来说,D0的LeadingSuperRegs容器包含了Q0,D1则包含Q2,D2包含Q1。对这个例子,一定是QQ0在执行417行的循环才有可能找出D1_D2这个子寄存器。而对于QQ0,目前它的子寄存器包括:Q0,Q1,D0,D1,D2及D3。在420行循环遍历这些子寄存器的上级寄存器。423行的判定如果成立,表示上级寄存器是当前寄存器,或者上级寄存器已知,否则在431行遍历、保存该上级寄存器除第一个的所有子寄存器索引。这里,ConcatIdx中有Q2的子寄存器索引集合,与从QQ0得到的D1与D2索引集合一致,因此如果这个复合索引还没创建,getConcatSubRegIndex()方法将合成、返回它,同时记录在ConcatIdx容器里,使该子寄存器索引唯一。
1086 CodeGenSubRegIndex *CodeGenRegBank::
1087 getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
1088 assert(Parts.size() > 1 && "Need two parts to concatenate");
1089
1090 // Look for an existing entry.
1091 CodeGenSubRegIndex *&Idx = ConcatIdx[Parts];
1092 if (Idx)
1093 return Idx;
1094
1095 // None exists, synthesize one.
1096 std::string Name = Parts.front()->getName();
1097 // Determine whether all parts are contiguous.
1098 bool isContinuous = true;
1099 unsigned Size = Parts.front()->Size;
1100 unsigned LastOffset = Parts.front()->Offset;
1101 unsigned LastSize = Parts.front()->Size;
1102 for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
1103 Name += '_';
1104 Name += Parts[i]->getName();
1105 Size += Parts[i]->Size;
1106 if (Parts[i]->Offset != (LastOffset + LastSize))
1107 isContinuous = false;
1108 LastOffset = Parts[i]->Offset;
1109 LastSize = Parts[i]->Size;
1110 }
1111 Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
1112 Idx->Size = Size;
1113 Idx->Offset = isContinuous ? Parts.front()->Offset : -1;
1114 return Idx;
1115 }
NewSubRegs只是一个临时容器。在453行的循环,它的内容被转移到了正式的SubReg2Idx容器。最后,以我们的例子来说,从QQ0访问Q2部分的索引已经建立,在464行循环进一步构建从QQ0访问Q2子寄存器的复合索引。
V7.0的computeSecondarySubRegs有如下定义:
465 void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
466 SmallVector<SubRegMap::value_type, 8> NewSubRegs;
467
468 std::queue<std::pair<CodeGenSubRegIndex*,CodeGenRegister*>> SubRegQueue;
469 for (std::pair<CodeGenSubRegIndex*,CodeGenRegister*> P : SubRegs)
470 SubRegQueue.push(P);
471
472 // Look at the leading super-registers of each sub-register. Those are the
473 // candidates for new sub-registers, assuming they are fully contained in
474 // this register.
475 while (!SubRegQueue.empty()) {
476 CodeGenSubRegIndex *SubRegIdx;
477 const CodeGenRegister *SubReg;
478 std::tie(SubRegIdx, SubReg) = SubRegQueue.front();
479 SubRegQueue.pop();
480
481 const CodeGenRegister::SuperRegList &Leads = SubReg->LeadingSuperRegs;
482 for (unsigned i = 0, e = Leads.size(); i != e; ++i) {
483 CodeGenRegister *Cand = const_cast<CodeGenRegister*>(Leads[i]);
484 // Already got this sub-register?
485 if (Cand == this || getSubRegIndex(Cand))
486 continue;
487 // Check if each component of Cand is already a sub-register.
488 assert(!Cand->ExplicitSubRegs.empty() &&
489 "Super-register has no sub-registers");
490 if (Cand->ExplicitSubRegs.size() == 1)
491 continue;
492 SmallVector<CodeGenSubRegIndex*, 8> Parts;
493 // We know that the first component is (SubRegIdx,SubReg). However we
494 // may still need to split it into smaller subregister parts.
495 assert(Cand->ExplicitSubRegs[0] == SubReg && "LeadingSuperRegs correct");
496 assert(getSubRegIndex(SubReg) == SubRegIdx && "LeadingSuperRegs correct");
497 for (CodeGenRegister *SubReg : Cand->ExplicitSubRegs) {
498 if (CodeGenSubRegIndex *SubRegIdx = getSubRegIndex(SubReg)) {
499 if (SubRegIdx->ConcatenationOf.empty()) {
500 Parts.push_back(SubRegIdx);
501 } else
502 for (CodeGenSubRegIndex *SubIdx : SubRegIdx->ConcatenationOf)
503 Parts.push_back(SubIdx);
504 } else {
505 // Sub-register doesn't exist.
506 Parts.clear();
507 break;
508 }
509 }
510 // There is nothing to do if some Cand sub-register is not part of this
511 // register.
512 if (Parts.empty())
513 continue;
514
515 // Each part of Cand is a sub-register of this. Make the full Cand also
516 // a sub-register with a concatenated sub-register index.
517 CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts);
518 std::pair<CodeGenSubRegIndex*,CodeGenRegister*> NewSubReg =
519 std::make_pair(Concat, Cand);
520
521 if (!SubRegs.insert(NewSubReg).second)
522 continue;
523
524 // We inserted a new subregister.
525 NewSubRegs.push_back(NewSubReg);
526 SubRegQueue.push(NewSubReg);
527 SubReg2Idx.insert(std::make_pair(Cand, Concat));
528 }
529 }
530
531 // Create sub-register index composition maps for the synthesized indices.
532 for (unsigned i = 0, e = NewSubRegs.size(); i != e; ++i) {
533 CodeGenSubRegIndex *NewIdx = NewSubRegs[i].first;
534 CodeGenRegister *NewSubReg = NewSubRegs[i].second;
535 for (SubRegMap::const_iterator SI = NewSubReg->SubRegs.begin(),
536 SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) {
537 CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second);
538 if (!SubIdx)
539 PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
540 SI->second->getName() + " in " + getName());
541 NewIdx->addComposite(SI->first, SubIdx);
542 }
543 }
544 }
它分为两个大循环。以上面的QQ0寄存器为例,从475~529行,构建QQ0对应的以D0~D3索引的Q0、Q1子寄存器。在532~543行,创建D0~D3的连续子寄存器索引,这里是D1_D2。
3.3.4.2.5. 构建上级寄存器关系
向下搞清楚了子寄存器与相关索引后,接下来就要向上搞清楚哪些寄存器是上级寄存器。
CodeGenRegister通过容器SuperRegs(std::vector<const CodeGenRegister*>)记录包含自己的上级寄存器。上级寄存器的枚举工作由下面的computeSuperRegs()方法完成。
478 void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
479 // Only visit each register once.
480 if (SuperRegsComplete)
481 return;
482 SuperRegsComplete = true;
483
484 // Make sure all sub-registers have been visited first, so the super-reg
485 // lists will be topologically ordered.
486 for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
487 I != E; ++I)
488 I->second->computeSuperRegs(RegBank);
489
490 // Now add this as a super-register on all sub-registers.
491 // Also compute the TopoSigId in post-order.
492 TopoSigId Id;
493 for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
494 I != E; ++I) {
495 // Topological signature computed from SubIdx, TopoId(SubReg).
496 // Loops and idempotent indices have TopoSig = ~0u.
497 Id.push_back(I->first->EnumValue);
498 Id.push_back(I->second->TopoSig);
499
500 // Don't add duplicate entries.
501 if (!I->second->SuperRegs.empty() && I->second->SuperRegs.back() == this)
502 continue;
503 I->second->SuperRegs.push_back(this);
504 }
505 TopoSig = RegBank.getTopoSig(Id);
506 }
在497行,CodeGenSubRegIndex的成员EnumValue实际上是该CodeGenSubRegIndex对象添加到CodeGenRegBank的SubRegIndices容器时的序号。而498行TopoSig是在488行的computeSuperRegs()递归调用里计算好的。对当前CodeGenRegister,由505行的getTopoSig()方法计算TopoSig。
614 unsigned getTopoSig(const TopoSigId &Id) {
615 return TopoSigs.insert(std::make_pair(Id, TopoSigs.size())).first->second;
616 }
TopoSigs是std::map<TopoSigId, unsigned>类型的容器,TopoSigId是SmallVector<unsigned, 16>的typedef。显然,getTopoSig方法返回的是参数Id在TopoSigs容器中的序号,这个序号接着返回给了当前CodeGenRegister对象的TopoSig。因为,Id的内容来自子寄存器,而且不同的叶子寄存器有不同的EnumValue(来自CodeGenSubRegIndex)与TopoSig(来自CodeGenRegister),因此,拥有相同TopoSig值的寄存器,一定具有相同的子寄存器结构。
V7.0在寄存器定义中引入了isArtificial域,表示该寄存器是人为的,这个寄存器不能用于创建寄存器类。对此,在CodeGenSubRegIndex中也引入了Artificial域,反映对应子寄存器的这个属性。因此,在当前寄存器的SubRegs容器中,如果子寄存器是Artificial的,对应的索引也是Artificial。
3.3.4.3. RegisterClass DAG
3.3.4.3.1. 寄存器类的表示
接下来在CodeGenRegBank构造函数的991行,开始着手寄存器类别的处理。RegisterClass对应的DAG类型是CodeGenRegisterClass,CodeGenRegBank使用容器RegClasses(类型std::list< CodeGenRegisterClass>)保存它们。在997行添加到容器时,调用CodeGenRegisterClass的构造函数:
654 CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
655 : TheDef(R),
656 Name(R->getName()),
657 TopoSigs(RegBank.getNumTopoSigs()),
658 EnumValue(-1),
659 LaneMask(0) { <-- v7.0删除
660 // Rename anonymous register classes. <-- v7.0删除,不支持匿名寄存器类
661 if (R->getName().size() > 9 && R->getName()[9] == '.') {
662 static unsigned AnonCounter = 0;
663 R->setName("AnonRegClass_" + utostr(AnonCounter++));
664 }
665
666 std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
667 for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
668 Record *Type = TypeList[i];
669 if (!Type->isSubClassOf("ValueType"))
670 PrintFatalError("RegTypes list member '" + Type->getName() +
671 "' does not derive from the ValueType class!");
672 VTs.push_back(getValueType(Type)); <-- v7.0删除
VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes())); <-- v7.0增加
673 }
674 assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
675
676 // Allocation order 0 is the full set. AltOrders provides others.
677 const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
678 ListInit *AltOrders = R->getValueAsListInit("AltOrders");
679 Orders.resize(1 + AltOrders->size());
680
681 // Default allocation order always contains all registers.
682 for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
683 Orders[0].push_back((*Elements)[i]);
684 const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
685 Members.push_back(Reg);
686 TopoSigs.set(Reg->getTopoSig());
687 }
688 sortAndUniqueRegisters(Members);
689
690 // Alternative allocation orders may be subsets.
691 SetTheory::RecSet Order;
692 for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) {
693 RegBank.getSets().evaluate(AltOrders->getElement(i), Order, R->getLoc());
694 Orders[1 + i].append(Order.begin(), Order.end());
695 // Verify that all altorder members are regclass members.
696 while (!Order.empty()) {
697 CodeGenRegister *Reg = RegBank.getReg(Order.back());
698 Order.pop_back();
699 if (!contains(Reg))
700 PrintFatalError(R->getLoc(), " AltOrder register " + Reg->getName() +
701 " is not a class member");
702 }
703 }
704
705 // Allow targets to override the size in bits of the RegisterClass.
706 unsigned Size = R->getValueAsInt("Size"); <-- v7.0删除
707
708 Namespace = R->getValueAsString("Namespace");
709 SpillSize = Size ? Size : MVT(VTs[0]).getSizeInBits(); <-- v7.0删除
710 SpillAlignment = R->getValueAsInt("Alignment"); <-- v7.0删除
if (const RecordVal *RV = R->getValue("RegInfos")) <-- v7.0增加
if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue()))
RSI = RegSizeInfoByHwMode(DI->getDef(), RegBank.getHwModes());
unsigned Size = R->getValueAsInt("Size");
assert((RSI.hasDefault() || Size != 0 || VTs[0].isSimple()) &&
"Impossible to determine register size");
if (!RSI.hasDefault()) {
RegSizeInfo RI;
RI.RegSize = RI.SpillSize = Size ? Size
: VTs[0].getSimple().getSizeInBits();
RI.SpillAlignment = R->getValueAsInt("Alignment");
RSI.Map.insert({DefaultMode, RI});
}
711 CopyCost = R->getValueAsInt("CopyCost");
712 Allocatable = R->getValueAsBit("isAllocatable");
713 AltOrderSelect = R->getValueAsString("AltOrderSelect");
714 int AllocationPriority = R->getValueAsInt("AllocationPriority");
715 if (AllocationPriority < 0 || AllocationPriority > 63)
716 PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,63]");
717 this->AllocationPriority = AllocationPriority;
718 }
TableGen在解析RegisterClass时是不处理MemberList成员的(保存为一个DagInit实例),前面已经在CodeGenRegBank构造函数中注册了MemberList的Expandor,因此677行调用它来展开这个域。
686行的容器TopoSigs的类型是BitVector,同一行上的set方法是设置参数所指定的比特位。前面看到不同的寄存器有不同的TopoSig,除非它们有相同的子寄存器结构。因此,TopoSigs能唯一地确定一个RegisterClass。
接着在688行,通过sortAndUniqueRegisters()对成员寄存器进行排序(按地址先后)并去除重复的对象。然后,如果RegisterClass中指定了AltOrders,给出了MemberList以外的分配次序(由AltOrderSelect确定用谁),在693行对这个域“求值”(AltOrders可以是一个复杂的dag值),并将结果附加到容器Orders末尾,就像我们在前面提到的那样。
在v7.0中VTs是SmallVector<ValueTypeByHwMode, 4>类型容器。ValueTypeByHwMode从InfoByHwMode派生(InfoByHwMode将HwMode与特定类型信息关联),因此ValueTypeByHwMode将HwMode与MVT关联。RegSizeInfoByHwMode将HwMode与RegSizeInfo关联。
而getValueTypeByHwMode()的定义是:
105 ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec,
106 const CodeGenHwModes &CGH) {
107 #ifndef NDEBUG
108 if (!Rec->isSubClassOf("ValueType"))
109 Rec->dump();
110 #endif
111 assert(Rec->isSubClassOf("ValueType") &&
112 "Record must be derived from ValueType");
113 if (Rec->isSubClassOf("HwModeSelect"))
114 return ValueTypeByHwMode(Rec, CGH);
115 return ValueTypeByHwMode(llvm::getValueType(Rec));
116 }
如果不指定HwMode,即115行,缺省使用DefaultMode。
V7.0新增的代码是处理与HwMode相关的RegInfos,结果保存在RegSizeInfoByHwMode实例中(CodeGenRegisterClass的成员RSI)。注意,前面在CodeGenRegBank的构造函数中,RegInfos(CodeGenRegisterClass的TD定义成员)如果不是空,会将DefaultMode删掉(这个DefaultMode是HwMode的派生定义),而上面的DefaultMode则是CodeGenHwModes里的枚举值DefaultMode。因此,需要费此周折。
接下来,对生成的CodeGenRegisterClass实例调用addToMaps()方法。
首先,CodeGenRegBank通过容器Def2RC(DenseMap<Record*, CodeGenRegisterClass*>)将RegisterClass的Record实例与CodeGenRegisterClass实例关联起来。
1037 void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
1038 if (Record *Def = RC->getDef())
1039 Def2RC.insert(std::make_pair(Def, RC));
1040
1041 // Duplicate classes are rejected by insert().
1042 // That's OK, we only care about the properties handled by CGRC::Key.
1043 CodeGenRegisterClass::Key K(*RC);
1044 Key2RC.insert(std::make_pair(K, RC));
1045 }
另外,在LLVM中通过寄存器成员列表(MemberList)、溅出大小(SpillSize,709行)、溅出边界(SpillAlignment,710行)这三个值来唯一确定一个RegisterClass。为此CodeGenRegisterClass定义了一个内嵌类Key来封装这三个值。CodeGenRegBank据此定义了关联容器Key2RC(std::map< CodeGenRegisterClass::Key, CodeGenRegisterClass*>),从Key快速查找CodeGenRegisterClass实例。
3.3.4.3.2. 进一步的推导
就像寄存器一样,仅仅是对RegisterClass定义生成CodeGenRegisterClass实例是不足够的。寄存器分配算法等后端用户想知道更多,比如:
- 对某个寄存器类,其中包含指定寄存器索引的寄存器最大子集。
- 对某两个寄存器类,找出它们的最大公共子集(在跨越寄存器类的情形里,使用这些寄存器会有额外的好处,比如可以直接在这些寄存器间进行拷贝)。
- 给定一个寄存器索引及一个寄存器类A,如果该类全体寄存器成员都包含这个索引;给定另一个寄存器类B,如果它的成员包含A中该索引援引的子寄存器,给出A中对应寄存器的集合(成员是指RegisterClass定义中MemberList给出的寄存器)。根据这个信息,给定一个小寄存器,可以找出包含它的大寄存器,以及它在这个大寄存器中的索引。
为此,TableGen需要努力工作,满足它们的要求。
1997 void CodeGenRegBank::computeInferredRegisterClasses() {
1998 assert(!RegClasses.empty());
1999 // When this function is called, the register classes have not been sorted
2000 // and assigned EnumValues yet. That means getSubClasses(),
2001 // getSuperClasses(), and hasSubClass() functions are defunct.
2002
2003 // Use one-before-the-end so it doesn't move forward when new elements are
2004 // added.
2005 auto FirstNewRC = std::prev(RegClasses.end());
2006
2007 // Visit all register classes, including the ones being added by the loop.
2008 // Watch out for iterator invalidation here.
2009 for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) {
2010 CodeGenRegisterClass *RC = &*I;
if (RC->Artificial) <-- v7.0增加
continue;
2011
2012 // Synthesize answers for getSubClassWithSubReg().
2013 inferSubClassWithSubReg(RC);
2014
2015 // Synthesize answers for getCommonSubClass().
2016 inferCommonSubClass(RC);
2017
2018 // Synthesize answers for getMatchingSuperRegClass().
2019 inferMatchingSuperRegClass(RC);
2020
2021 // New register classes are created while this loop is running, and we need
2022 // to visit all of them. I particular, inferMatchingSuperRegClass needs
2023 // to match old super-register classes with sub-register classes created
2024 // after inferMatchingSuperRegClass was called. At this point,
2025 // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC =
2026 // [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci].
2027 if (I == FirstNewRC) {
2028 auto NextNewRC = std::prev(RegClasses.end());
2029 for (auto I2 = RegClasses.begin(), E2 = std::next(FirstNewRC); I2 != E2;
2030 ++I2)
2031 inferMatchingSuperRegClass(&*I2, E2);
2032 FirstNewRC = NextNewRC;
2033 }
2034 }
2035 }
3.3.4.3.2.1. 包含指定寄存器索引的最大子集
CodeGenRegisterClass通过容器SubClassWithSubReg(DenseMap<const CodeGenSubRegIndex *, CodeGenRegisterClass *>)来记录这个关系。下面1891行的CodeGenRegister::Vec是std::vector<const CodeGenRegister*>的typedef。
1889 void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
1890 // Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
1891 typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec,
1892 deref<llvm::less>> SubReg2SetMap;
1893
1894 // Compute the set of registers supporting each SubRegIndex.
1895 SubReg2SetMap SRSets;
1896 for (const auto R : RC->getMembers()) {
if (R->Artificial) <-- v7.0增加
continue;
1897 const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
1898 for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
1899 E = SRM.end(); I != E; ++I)
1900 SRSets[I->first].push_back(R);
1901 }
1902
1903 for (auto I : SRSets)
1904 sortAndUniqueRegisters(I.second);
1905
1906 // Find matching classes for all SRSets entries. Iterate in SubRegIndex
1907 // numerical order to visit synthetic indices last.
1908 for (const auto &SubIdx : SubRegIndices) {
if (R->Artificial) <-- v7.0增加
continue;
1909 SubReg2SetMap::const_iterator I = SRSets.find(&SubIdx);
1910 // Unsupported SubRegIndex. Skip it.
1911 if (I == SRSets.end())
1912 continue;
1913 // In most cases, all RC registers support the SubRegIndex.
1914 if (I->second.size() == RC->getMembers().size()) {
1915 RC->setSubClassWithSubReg(&SubIdx, RC);
1916 continue;
1917 }
1918 // This is a real subset. See if we have a matching class.
1919 CodeGenRegisterClass *SubRC =
1920 getOrCreateSubClass(RC, &I->second,
1921 RC->getName() + "_with_" + I->first->getName());
1922 RC->setSubClassWithSubReg(&SubIdx, SubRC);
1923 }
1924 }
1896行循环通过临时容器SRSets将CodeGenSubRegIndex实例与所有使用它的CodeGenRegister实例关联起来。1903行循环对分别这些CodeGenRegister集合按地址进行排序,删除重复对象。接着1908行循环遍历所有寄存器索引,取出援引它的CodeGenRegister集合。如果RC所有的寄存器都支持这个索引,把RC标记为RC中包含所有支持该索引的寄存器的类别。而如果RC中只有部分寄存器支持这个索引,需要通过getOrCreateSubClass()方法创建这个新的寄存器类。
1048 CodeGenRegisterClass*
1049 CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
1050 const CodeGenRegister::Vec *Members,
1051 StringRef Name) {
1052 // Synthetic sub-class has the same size and alignment as RC.
1053 CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment); <-- v7.0删除
CodeGenRegisterClass::Key K(Members, RC->RSI); <-- v7.0增加
1054 RCKeyMap::const_iterator FoundI = Key2RC.find(K);
1055 if (FoundI != Key2RC.end())
1056 return FoundI->second;
1057
1058 // Sub-class doesn't exist, create a new one.
1059 RegClasses.emplace_back(*this, Name, K);
1060 addToMaps(&RegClasses.back());
1061 return &RegClasses.back();
1062 }
前面说过不同的CodeGenRegisterClass实例由CodeGenRegisterClass::Key对象区分,在这里它确保每个CodeGenRegisterClass都是唯一的一个类别。
最后通过CodeGenRegisterClass的setSubClassWithSubReg()方法向其SubClassWithSubReg容器添加这层关系。
3.3.4.3.2.2. 两个寄存器类的公共子集
CodeGenRegisterClass没有专门储存这部分信息的容器。CodeGenRegBank为这个子集创建了一个新的寄存器类。
1848 void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
1849 assert(!RegClasses.empty());
1850 // Stash the iterator to the last element so that this loop doesn't visit
1851 // elements added by the getOrCreateSubClass call within it.
1852 for (auto I = RegClasses.begin(), E = std::prev(RegClasses.end());
1853 I != std::next(E); ++I) {
1854 CodeGenRegisterClass *RC1 = RC;
1855 CodeGenRegisterClass *RC2 = &*I;
1856 if (RC1 == RC2)
1857 continue;
1858
1859 // Compute the set intersection of RC1 and RC2.
1860 const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
1861 const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
1862 CodeGenRegister::Vec Intersection;
1863 std::set_intersection(
1864 Memb1.begin(), Memb1.end(), Memb2.begin(), Memb2.end(),
1865 std::inserter(Intersection, Intersection.begin()), deref<llvm::less>());
1866
1867 // Skip disjoint class pairs.
1868 if (Intersection.empty())
1869 continue;
1870
1871 // If RC1 and RC2 have different spill sizes or alignments, use the
1872 // larger size for sub-classing. If they are equal, prefer RC1.
1873 if (RC2->SpillSize > RC1->SpillSize ||
1874 (RC2->SpillSize == RC1->SpillSize &&
1875 RC2->SpillAlignment > RC1->SpillAlignment))
1876 std::swap(RC1, RC2);
1877
1878 getOrCreateSubClass(RC1, &Intersection,
1879 RC1->getName() + "_and_" + RC2->getName());
1880 }
1881 }
3.3.4.3.2.3. 超级寄存器类
如果寄存器类A完全支持一个寄存器索引I(即所有成员都有I可援引的子寄存器),I所援引的子寄存器都是另一个寄存器类B的成员,称A是B关于索引I的超级类。对同一个索引,这样的超级类可能不止一个,另外也可能在多个索引上存在超级类。显然,超类的存在拓展了可用寄存器的分配范围(A可以替代B)。
535 void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) {
536 inferMatchingSuperRegClass(RC, RegClasses.begin());
537 }
临时容器SSPairs记录该寄存器类中每一对寄存器与索引援引子寄存器。1937行的TopoSigs将对应成员寄存器TopoSig位的比特设置为1,用于快速比较两个寄存器集合是否有相同成员(因为寄存器的TopoSig是唯一的,是CodeGenRegister实例的分配序号)。
1933 void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
1934 std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) {
1935 SmallVector<std::pair<const CodeGenRegister*,
1936 const CodeGenRegister*>, 16> SSPairs;
1937 BitVector TopoSigs(getNumTopoSigs());
1938
1939 // Iterate in SubRegIndex numerical order to visit synthetic indices last.
1940 for (auto &SubIdx : SubRegIndices) {
1941 // Skip indexes that aren't fully supported by RC's registers. This was
1942 // computed by inferSubClassWithSubReg() above which should have been
1943 // called first.
1944 if (RC->getSubClassWithSubReg(&SubIdx) != RC)
1945 continue;
1946
1947 // Build list of (Super, Sub) pairs for this SubIdx.
1948 SSPairs.clear();
1949 TopoSigs.reset();
1950 for (const auto Super : RC->getMembers()) {
1951 const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
1952 assert(Sub && "Missing sub-register");
1953 SSPairs.push_back(std::make_pair(Super, Sub));
1954 TopoSigs.set(Sub->getTopoSig());
1955 }
1956
1957 // Iterate over sub-register class candidates. Ignore classes created by
1958 // this loop. They will never be useful.
1959 // Store an iterator to the last element (not end) so that this loop doesn't
1960 // visit newly inserted elements.
1961 assert(!RegClasses.empty());
1962 for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end());
1963 I != std::next(E); ++I) {
1964 CodeGenRegisterClass &SubRC = *I;
1965 // Topological shortcut: SubRC members have the wrong shape.
1966 if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
1967 continue;
1968 // Compute the subset of RC that maps into SubRC.
1969 CodeGenRegister::Vec SubSetVec;
1970 for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
1971 if (SubRC.contains(SSPairs[i].second))
1972 SubSetVec.push_back(SSPairs[i].first);
1973
1974 if (SubSetVec.empty())
1975 continue;
1976
1977 // RC injects completely into SubRC.
1978 sortAndUniqueRegisters(SubSetVec);
1979 if (SubSetVec.size() == SSPairs.size()) {
1980 SubRC.addSuperRegClass(&SubIdx, RC);
1981 continue;
1982 }
1983
1984 // Only a subset of RC maps into SubRC. Make sure it is represented by a
1985 // class.
1986 getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
1987 SubIdx.getName() + "_in_" +
1988 SubRC.getName());
1989 }
1990 }
1991 }
CodeGenRegisterClass实例使用SuperRegClasses容器来保存指定索引的超级类。可以想见这个容器必然是以寄存器索引为键值的关联容器(类型DenseMap<const CodeGenSubRegIndex *, SmallPtrSet<CodeGenRegisterClass *, 8>>)。
如果A不能完全映射到B,不构成超集关系,必须在1986行通过getOrCreateSubClass()方法创建A的一个子集。
回到CodeGenRegBank::computeInferredRegisterClasses(),接着在2027行开始的if块将新加的类别也考虑进来,为了避免无谓的遍历,代码就成了那个样子。
回到CodeGenRegBank的构造函数,1005行的TopoOrderRC()方法对已有的CodeGenRegisterClass实例进行排序。排序规则是依次考虑:1. SpillSize升序,2. SpillAlignment升序,3. 成员数降序,4.名字字母序。排序完成后,由1007行循环将排序序号赋给CodeGenRegisterClass实例的EnumValue。
3.3.4.3.3. 寄存器类的包含关系
在CodeGenRegBank构造函数的最后推导所有寄存器类之间的包含关系。CodeGenRegisterClass的容器SubClasses(BitVector)与SuperClasses(SmallVector<CodeGenRegisterClass*, 4>)分别用于记录作为该寄存器类子集与超集的寄存器类,其中SubClasses记录的寄存器类的EnumValue,这个值能唯一识别寄存器类。首先自己是自己的子集(858行)。
851 void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
852 auto &RegClasses = RegBank.getRegClasses();
853
854 // Visit backwards so sub-classes are seen first.
855 for (auto I = RegClasses.rbegin(), E = RegClasses.rend(); I != E; ++I) {
856 CodeGenRegisterClass &RC = *I;
857 RC.SubClasses.resize(RegClasses.size());
858 RC.SubClasses.set(RC.EnumValue);
if (RC.Artificial) <-- v7.0增加
continue;
859
860 // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
861 for (auto I2 = I.base(), E2 = RegClasses.end(); I2 != E2; ++I2) {
862 CodeGenRegisterClass &SubRC = *I2;
863 if (RC.SubClasses.test(SubRC.EnumValue))
864 continue;
865 if (!testSubClass(&RC, &SubRC))
866 continue;
867 // SubRC is a sub-class. Grap all its sub-classes so we won't have to
868 // check them again.
869 RC.SubClasses |= SubRC.SubClasses;
870 }
871
872 // Sweep up missed clique members. They will be immediately preceding RC.
873 for (auto I2 = std::next(I); I2 != E && testSubClass(&RC, &*I2); ++I2)
874 RC.SubClasses.set(I2->EnumValue);
875 }
876
877 // Compute the SuperClasses lists from the SubClasses vectors.
878 for (auto &RC : RegClasses) {
879 const BitVector &SC = RC.getSubClasses();
880 auto I = RegClasses.begin();
881 for (int s = 0, next_s = SC.find_first(); next_s != -1;
882 next_s = SC.find_next(s)) {
883 std::advance(I, next_s - s);
884 s = next_s;
885 if (&*I == &RC)
886 continue;
887 I->SuperClasses.push_back(&RC);
888 }
889 }
890
891 // With the class hierarchy in place, let synthesized register classes inherit
892 // properties from their closest super-class. The iteration order here can
893 // propagate properties down multiple levels.
894 for (auto &RC : RegClasses)
895 if (!RC.getDef())
896 RC.inheritProperties(RegBank);
897 }
如果对于任何要求一个RC类别寄存器的指令操作数,SubRC类别的寄存器都是一个有效的替换,那么SubRC就是RC的一个子类别。它必须满足以下条件:1. 所有SubRC的寄存器必须属于RC,2. SubRC的溅出大小必须不小于RC,3. SubRC的溅出边界必须与RC兼容(865行的testSubClass()检查这3个条件)。另一方面,RC就是SubRC的超级寄存器类(878行循环设置)。
最后,如果寄存器类是在前面合成出来的,它一定满足895行条件,因为我们没在TD文件里定义它,因此它的属性需要从其超级类中继承(因为它是合成的,一定存在超级类。另外,又因为前面TopoOrderRC的排序,最后一个超级类则一定是最小的)。
740 void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
741 assert(!getDef() && "Only synthesized classes can inherit properties");
742 assert(!SuperClasses.empty() && "Synthesized class without super class");
743
744 // The last super-class is the smallest one.
745 CodeGenRegisterClass &Super = *SuperClasses.back();
746
747 // Most properties are copied directly.
748 // Exceptions are members, size, and alignment
749 Namespace = Super.Namespace;
750 VTs = Super.VTs;
751 CopyCost = Super.CopyCost;
752 Allocatable = Super.Allocatable;
753 AltOrderSelect = Super.AltOrderSelect;
754 AllocationPriority = Super.AllocationPriority;
755
756 // Copy all allocation orders, filter out foreign registers from the larger
757 // super-class.
758 Orders.resize(Super.Orders.size());
759 for (unsigned i = 0, ie = Super.Orders.size(); i != ie; ++i)
760 for (unsigned j = 0, je = Super.Orders[i].size(); j != je; ++j)
761 if (contains(RegBank.getReg(Super.Orders[i][j])))
762 Orders[i].push_back(Super.Orders[i][j]);
763 }
从CodeGenRegisterClass::inheritProperties()返回CodeGenRegisterClass::computeSubClasses(),进而返回CodeGenRegBank构造函数,对寄存器类别的处理就结束了。CodeGenRegBank的构造工作也宣告完成。