LLVM学习笔记(10)

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.0RegisterInfoEmitter的构造函数不是平凡的

  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.0CodeGenTarget的定义增加了一个描述硬件模式的成员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的构造函数则定义如下。它收集HwModeHwModeSelectTD定义,创建对应的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,这个IDHwMode实例在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文件里的ValueTypeByHwModeRegInfoByHwMode定义。在这些对应中域ModesObjects应该是一一对应的。

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行的ItemsHwModeSelect 类型为std::pair<unsigned, Record*>的容器,它将模式的IDObjects域里的内容关联起来(即指定硬件模式选中什么)。

构造好的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     }

213v7.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.0CodeGenRegBank中引入了容器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.0CoveringSubRegIndices在增加了容器ConcatenationOf(类型SmallVector< CodeGenSubRegIndex*, 4>),用于保存串联成这个CodeGenSubRegIndexCodeGenSubRegIndex。它是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.0CodeGenSubRegIndex的容器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.0computeSecondarySubRegs有如下定义:

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索引的Q0Q1子寄存器。在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.0VTsSmallVector<ValueTypeByHwMode, 4>类型容器。ValueTypeByHwModeInfoByHwMode派生(InfoByHwModeHwMode与特定类型信息关联),因此ValueTypeByHwModeHwModeMVT关联。RegSizeInfoByHwModeHwModeRegSizeInfo关联。

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的构造函数中,RegInfosCodeGenRegisterClassTD定义成员)如果不是空,会将DefaultMode删掉(这个DefaultModeHwMode的派生定义),而上面的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的构造工作也宣告完成。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值