LLVM学习笔记(18)

来源:互联网 发布:施工组织设计软件 编辑:程序博客网 时间:2024/06/05 18:41

3.4.2.5.       Instruction的处理

CodeGenDAGPatterns下一步开始处理指令定义。在Instruction的定义里有一个list<dag>类型的成员Pattern,如果不是空,它指定了该指令的匹配模式。在3072行获取Pattern的定义。

3065   void CodeGenDAGPatterns::ParseInstructions(){

3066     std::vector<Record*> Instrs =Records.getAllDerivedDefinitions("Instruction");

3067  

3068     for (unsignedi = 0, e = Instrs.size(); i != e; ++i) {

3069       ListInit *LI = nullptr;

3070  

3071       if(isa<ListInit>(Instrs[i]->getValueInit("Pattern")))

3072         LI =Instrs[i]->getValueAsListInit("Pattern");

3073  

3074       // If there isno pattern, only collect minimal information about the

3075      // instructionfor its operand list.  We have to assumethat there is one

3076      // result, aswe have no detailed info. A pattern which references the

3077      // null_fragoperator is as-if no pattern were specified. Normally this

3078      // is from amulticlass expansion w/ a SDPatternOperator passed in as

3079      // null_frag.

3080       if (!LI || LI->empty() ||hasNullFragReference(LI)) {

3081         std::vector<Record*> Results;

3082         std::vector<Record*> Operands;

3083  

3084         CodeGenInstruction &InstInfo =Target.getInstruction(Instrs[i]);

3085  

3086         if (InstInfo.Operands.size() != 0) {

3087           for(unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j)

3088            Results.push_back(InstInfo.Operands[j].Rec);

3089  

3090           // The restare inputs.

3091           for(unsigned j = InstInfo.Operands.NumDefs,

3092                  e = InstInfo.Operands.size(); j< e; ++j)

3093             Operands.push_back(InstInfo.Operands[j].Rec);

3094         }

3095  

3096         // Create andinsert the instruction.

3097         std::vector<Record*> ImpResults;

3098        Instructions.insert(std::make_pair(Instrs[i],

3099                            DAGInstruction(nullptr, Results, Operands, ImpResults)));

3100         continue// no pattern.

3101       }

3102  

3103       CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]);

3104       constDAGInstruction &DI = parseInstructionPattern(CGI,LI, Instructions);

3105  

3106       (void)DI;

3107       DEBUG(DI.getPattern()->dump());

3108     }

3.4.5.2.1.  无匹配模式的Instruction

在TargetSelectionDAG.td文件里有一个null_frag的定义,专用于表示空模式。在一个展开的模式里,一旦援引了null_frag的定义,这个模式将被丢弃。这可以实现可选模式。那么,3080行的hasNullFragReference在模式中查找是否使用null_frag作为操作符,一旦找到就返回true。

如果Instruction定义没有定义Pattern(使用null_frag作为操作符也等同于没有Pattern),仅需要生成收集最少量参数列表信息的CodeGenInstruction实例。

157       CodeGenInstruction &getInstruction(const Record *InstRec)const{

158          if (Instructions.empty())ReadInstructions();

159          auto I =Instructions.find(InstRec);

160          assert(I !=Instructions.end() && "Not an instruction");

161          return*I->second;

162        }

Instructions是mutable DenseMap<const Record*,std::unique_ptr<CodeGenInstruction>>类型的容器(CodeGenTarget的成员),这时它一定是空的。因此,由下面的方法创建所有Instruction定义所对应的CodeGenInstruction实例。

267      void CodeGenTarget::ReadInstructions()const {

268        std::vector<Record*> Insts =Records.getAllDerivedDefinitions("Instruction");

269        if (Insts.size() <= 2)

270          PrintFatalError("No 'Instruction'subclasses defined!");

271     

272        // Parse theinstructions defined in the .td file.

273        for (unsignedi = 0, e = Insts.size(); i != e; ++i)

274          Instructions[Insts[i]] =llvm::make_unique<CodeGenInstruction>(Insts[i]);

275      }

274行调用了CodeGenInstruction的构造函数。

295      CodeGenInstruction::CodeGenInstruction(Record*R)

296        : TheDef(R), Operands(R),InferredFrom(nullptr) {

297        Namespace =R->getValueAsString("Namespace");

298        AsmString =R->getValueAsString("AsmString");

299     

300        isReturn    = R->getValueAsBit("isReturn");

301        isBranch    = R->getValueAsBit("isBranch");

302        isIndirectBranch =R->getValueAsBit("isIndirectBranch");

303        isCompare   = R->getValueAsBit("isCompare");

304        isMoveImm   = R->getValueAsBit("isMoveImm");

305        isBitcast   = R->getValueAsBit("isBitcast");

306        isSelect    = R->getValueAsBit("isSelect");

307        isBarrier   = R->getValueAsBit("isBarrier");

308        isCall      = R->getValueAsBit("isCall");

309        canFoldAsLoad =R->getValueAsBit("canFoldAsLoad");

310        isPredicable = Operands.isPredicable ||R->getValueAsBit("isPredicable");

311        isConvertibleToThreeAddress =R->getValueAsBit("isConvertibleToThreeAddress");

312        isCommutable =R->getValueAsBit("isCommutable");

313        isTerminator =R->getValueAsBit("isTerminator");

314        isReMaterializable =R->getValueAsBit("isReMaterializable");

315        hasDelaySlot =R->getValueAsBit("hasDelaySlot");

316        usesCustomInserter =R->getValueAsBit("usesCustomInserter");

317        hasPostISelHook =R->getValueAsBit("hasPostISelHook");

318        hasCtrlDep  = R->getValueAsBit("hasCtrlDep");

319        isNotDuplicable =R->getValueAsBit("isNotDuplicable");

320        isRegSequence =R->getValueAsBit("isRegSequence");

321        isExtractSubreg = R->getValueAsBit("isExtractSubreg");

322        isInsertSubreg =R->getValueAsBit("isInsertSubreg");

323        isConvergent =R->getValueAsBit("isConvergent");

324     

325        bool Unset;

326        mayLoad     = R->getValueAsBitOrUnset("mayLoad", Unset);

327        mayLoad_Unset = Unset;

328       mayStore    = R->getValueAsBitOrUnset("mayStore", Unset);

329        mayStore_Unset = Unset;

330        hasSideEffects =R->getValueAsBitOrUnset("hasSideEffects", Unset);

331        hasSideEffects_Unset = Unset;

332     

333        isAsCheapAsAMove =R->getValueAsBit("isAsCheapAsAMove");

334        hasExtraSrcRegAllocReq =R->getValueAsBit("hasExtraSrcRegAllocReq");

335        hasExtraDefRegAllocReq =R->getValueAsBit("hasExtraDefRegAllocReq");

336        isCodeGenOnly =R->getValueAsBit("isCodeGenOnly");

337        isPseudo =R->getValueAsBit("isPseudo");

338        ImplicitDefs =R->getValueAsListOfDefs("Defs");

339        ImplicitUses =R->getValueAsListOfDefs("Uses");

340     

341        // ParseConstraints.

342        ParseConstraints(R->getValueAsString("Constraints"),Operands);

343     

344        // Parse theDisableEncoding field.

345        Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));

346     

347        // First checkfor a ComplexDeprecationPredicate.

348        if(R->getValue("ComplexDeprecationPredicate")) {

349          HasComplexDeprecationPredicate = true;

350          DeprecatedReason =R->getValueAsString("ComplexDeprecationPredicate");

351        } else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")){

352          // Check if wehave a Subtarget feature mask.

353          HasComplexDeprecationPredicate = false;

354          DeprecatedReason =Dep->getValue()->getAsString();

355        } else {

356          // Thisinstruction isn't deprecated.

357          HasComplexDeprecationPredicate = false;

358          DeprecatedReason = "";

359        }

360      }

296行的Operands是CGIOperandList类型的成员,因此在该行调用了CGIOperandList的构造函数,为Instruction定义中的操作数构建OperandInfo实例。

28       CGIOperandList::CGIOperandList(Record*R) : TheDef(R) {

29          isPredicable = false;

30          hasOptionalDef = false;

31          isVariadic = false;

32       

33          DagInit *OutDI =R->getValueAsDag("OutOperandList");

34       

35          if (DefInit *Init =dyn_cast<DefInit>(OutDI->getOperator())) {

36            if (Init->getDef()->getName() !="outs")

37              PrintFatalError(R->getName() + ":invalid def name for output list: use 'outs'");

38          } else

39            PrintFatalError(R->getName() + ":invalid output list: use 'outs'");

40       

41          NumDefs = OutDI->getNumArgs();

42       

43          DagInit *InDI = R->getValueAsDag("InOperandList");

44          if (DefInit *Init =dyn_cast<DefInit>(InDI->getOperator())) {

45            if (Init->getDef()->getName() !="ins")

46              PrintFatalError(R->getName() + ":invalid def name for input list: use 'ins'");

47          } else

48            PrintFatalError(R->getName() + ":invalid input list: use 'ins'");

49       

50          unsigned MIOperandNo = 0;

51          std::set<std::string> OperandNames;

52          for (unsignedi = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){

53            Init *ArgInit;

54            std::string ArgName;

55            if (i < NumDefs) {

56              ArgInit = OutDI->getArg(i);

57              ArgName = OutDI->getArgName(i);

58            } else {

59              ArgInit = InDI->getArg(i-NumDefs);

60              ArgName = InDI->getArgName(i-NumDefs);

61            }

62       

63            DefInit *Arg =dyn_cast<DefInit>(ArgInit);

64            if (!Arg)

65              PrintFatalError("Illegal operand forthe '" + R->getName() + "' instruction!");

66       

67            Record *Rec = Arg->getDef();

68            std::string PrintMethod ="printOperand";

69            std::string EncoderMethod;

70            std::string OperandType ="OPERAND_UNKNOWN";

71            std::string OperandNamespace ="MCOI";

72            unsigned NumOps = 1;

73            DagInit *MIOpInfo = nullptr;

74            if(Rec->isSubClassOf("RegisterOperand")) {

75              PrintMethod =Rec->getValueAsString("PrintMethod");

76              OperandType =Rec->getValueAsString("OperandType");

77              OperandNamespace =Rec->getValueAsString("OperandNamespace");

78            } else if(Rec->isSubClassOf("Operand")) {

79              PrintMethod =Rec->getValueAsString("PrintMethod");

80              OperandType =Rec->getValueAsString("OperandType");

81              // If thereis an explicit encoder method, use it.

82              EncoderMethod =Rec->getValueAsString("EncoderMethod");

83              MIOpInfo = Rec->getValueAsDag("MIOperandInfo");

84       

85              // Verifythat MIOpInfo has an 'ops' root value.

86              if(!isa<DefInit>(MIOpInfo->getOperator()) ||

87                 cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName()!= "ops")

88                PrintFatalError("Bad value forMIOperandInfo in operand '" + Rec->getName() +

89                  "'\n");

90       

91             // If we haveMIOpInfo, then we have #operands equal to number of entries

92             // inMIOperandInfo.

93              if (unsigned NumArgs =MIOpInfo->getNumArgs())

94                NumOps = NumArgs;

95       

96              if(Rec->isSubClassOf("PredicateOp"))

97                isPredicable = true;

98              else if(Rec->isSubClassOf("OptionalDefOperand"))

99                hasOptionalDef = true;

100          } else if (Rec->getName() =="variable_ops") {

101            isVariadic = true;

102            continue;

103          } else if(Rec->isSubClassOf("RegisterClass")) {

104            OperandType ="OPERAND_REGISTER";

105          } else if(!Rec->isSubClassOf("PointerLikeRegClass") &&

106                    !Rec->isSubClassOf("unknown_class"))

107            PrintFatalError("Unknown operandclass '" + Rec->getName() +

108              "' in '" + R->getName() +"' instruction!");

109     

110          // Check thatthe operand has a name and that it's unique.

111          if (ArgName.empty())

112            PrintFatalError("In instruction'" + R->getName() + "', operand #" +

113                            Twine(i) + " has noname!");

114          if (!OperandNames.insert(ArgName).second)

115            PrintFatalError("In instruction'" + R->getName() + "', operand #" +

116                            Twine(i) + " has thesame name as a previous operand!");

117     

118          OperandList.emplace_back(Rec, ArgName,PrintMethod, EncoderMethod,

119                                   OperandNamespace +"::" + OperandType, MIOperandNo,

120                                   NumOps, MIOpInfo);

121          MIOperandNo += NumOps;

122        }

123     

124     

125        // Make sure theconstraints list for each operand is large enough to hold

126       // constraintinfo, even if none is present.

127        for (unsignedi = 0, e = OperandList.size(); i != e; ++i)

128         OperandList[i].Constraints.resize(OperandList[i].MINumOperands);

129      }

上面的Record实例的getValue*方法通过参数指定要访问的成员名,*部分则指明了成员的类型,这些方法将返回对应类型的成员值。

首先,确定Instruction定义中的OutOperandList与InOperandList分别是以out及ins作为操作符的dag。在52行的循环里依次访问OutOperandList与InOperandList的操作数。可以作为输入、输出操作数的类型有:RegisterOperand,Operand,RegisterClass,variable_ops,PointerLikeRegClass。其中部分的TD定义分别是:

144      classDAGOperand { }

 

519      def variable_ops;

 

526      classPointerLikeRegClass<intKind> {

526        int RegClassKind = Kind;

528      }

构建了CGIOperandList实例后,要解析对这些操作数限定的描述。在CodeGenInstruction构造函数的342行通过ParseConstraints方法进行解析这些描述。

256      static voidParseConstraints(conststd::string &CStr, CGIOperandList &Ops) {

257        if (CStr.empty()) return;

258     

259        conststd::string delims(",");

260        std::string::size_type bidx, eidx;

261     

262        bidx = CStr.find_first_not_of(delims);

263        while (bidx!= std::string::npos) {

264          eidx = CStr.find_first_of(delims, bidx);

265          if (eidx == std::string::npos)

266            eidx = CStr.length();

267     

268          ParseConstraint(CStr.substr(bidx,eidx - bidx), Ops);

269          bidx = CStr.find_first_not_of(delims,eidx);

270        }

271      }

Constraints字符串可以描述多个限定,它们由字符“,”分割。因此263行的循环找出每个限定描述字符串,并由下面的方法进行分析。

201      static voidParseConstraint(conststd::string &CStr, CGIOperandList &Ops) {

202        // EARLY_CLOBBER:@early $reg

203        std::string::size_type wpos =CStr.find_first_of(" \t");

204        std::string::size_type start =CStr.find_first_not_of(" \t");

205        std::string Tok = CStr.substr(start, wpos -start);

206        if (Tok == "@earlyclobber") {

207          std::string Name = CStr.substr(wpos+1);

208          wpos = Name.find_first_not_of("\t");

209          if (wpos == std::string::npos)

210            PrintFatalError("Illegal format for@earlyclobber constraint: '" + CStr + "'");

211          Name = Name.substr(wpos);

212          std::pair<unsigned,unsigned> Op =Ops.ParseOperandName(Name, false);

213     

214          // Build thestring for the operand

215          if(!Ops[Op.first].Constraints[Op.second].isNone())

216            PrintFatalError("Operand '" +Name + "' cannot have multiple constraints!");

217          Ops[Op.first].Constraints[Op.second] =

218          CGIOperandList::ConstraintInfo::getEarlyClobber();

219          return;

220        }

222        // Only otherconstraint is "TIED_TO" for now.

223        std::string::size_type pos =CStr.find_first_of('=');

224        assert(pos !=std::string::npos && "Unrecognized constraint");

225        start = CStr.find_first_not_of("\t");

226        std::string Name = CStr.substr(start, pos -start);

227     

228        // TIED_TO: $src1= $dst

229        wpos = Name.find_first_of(" \t");

230        if (wpos == std::string::npos)

231          PrintFatalError("Illegal format fortied-to constraint: '" + CStr + "'");

232        std::string DestOpName = Name.substr(0,wpos);

233        std::pair<unsigned,unsigned> DestOp =Ops.ParseOperandName(DestOpName,false);

234     

235        Name = CStr.substr(pos+1);

236        wpos = Name.find_first_not_of("\t");

237        if (wpos == std::string::npos)

238          PrintFatalError("Illegal format fortied-to constraint: '" + CStr + "'");

239     

240        std::string SrcOpName = Name.substr(wpos);

241        std::pair<unsigned,unsigned> SrcOp =Ops.ParseOperandName(SrcOpName, false);

242        if (SrcOp > DestOp) {

243          std::swap(SrcOp, DestOp);

244          std::swap(SrcOpName, DestOpName);

245        }

246     

247        unsigned FlatOpNo =Ops.getFlattenedOperandNumber(SrcOp);

248     

249        if (!Ops[DestOp.first].Constraints[DestOp.second].isNone())

250          PrintFatalError("Operand '" +DestOpName +

251            "' cannot have multipleconstraints!");

252        Ops[DestOp.first].Constraints[DestOp.second]=

253          CGIOperandList::ConstraintInfo::getTied(FlatOpNo);

254      }

有两种约束形式。一个是@earlyclobber $reg,表示寄存器reg的内容很早就被破坏了。另一种就是所谓的绑定(TIED_TO)约束,诸如$src = $dst的形式。但无论何种约束形式,都要识别出操作数的名字。

156      std::pair<unsigned,unsigned>

157      CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {

158        if (Op.empty() || Op[0] != '$')

159          PrintFatalError(TheDef->getName() +": Illegal operand name: '" + Op + "'");

160     

161        std::string OpName = Op.substr(1);

162        std::string SubOpName;

163     

164        // Check to seeif this is $foo.bar.

165        std::string::size_type DotIdx =OpName.find_first_of(".");

166        if (DotIdx != std::string::npos) {

167          SubOpName = OpName.substr(DotIdx+1);

168          if (SubOpName.empty())

169            PrintFatalError(TheDef->getName() +": illegal empty suboperand name in '" +Op +"'");

170          OpName = OpName.substr(0, DotIdx);

171        }

172     

173        unsigned OpIdx = getOperandNamed(OpName);

174     

175        if (SubOpName.empty()) { // If no suboperandname was specified:

176         // If one wasneeded, throw.

177          if (OperandList[OpIdx].MINumOperands > 1&& !AllowWholeOp &&

178              SubOpName.empty())

179            PrintFatalError(TheDef->getName() +": Illegal to refer to"

180              " whole operand part of complexoperand '" + Op + "'");

181     

182          // Otherwise,return the operand.

183          return std::make_pair(OpIdx, 0U);

184        }

185     

186        // Find thesuboperand number involved.

187        DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;

188        if (!MIOpInfo)

189          PrintFatalError(TheDef->getName() +": unknown suboperand name in '" + Op + "'");

190     

191        // Find theoperand with the right name.

192        for (unsignedi = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)

193          if (MIOpInfo->getArgName(i) ==SubOpName)

194            return std::make_pair(OpIdx, i);

195     

196        // Otherwise,didn't find it!

197        PrintFatalError(TheDef->getName() +": unknown suboperand name in '" + Op + "'");

198        return std::make_pair(0U, 0U);

199      }

操作数名字必须以$开始,这个名字可以是类似于$foo.bar这样的形式。对这样的名字,foo部分称为操作数,bar部分称为子操作数(参考ssmem定义)。操作数必须在输入或输出操作数列表里出现,这个列表已经被保存到OperandList容器里了,因此只需要操作数在容器里的索引。

136      unsigned CGIOperandList::getOperandNamed(StringRefName) const {

137        unsigned OpIdx;

138        if (hasOperandNamed(Name,OpIdx))return OpIdx;

139        PrintFatalError("'" +TheDef->getName() +

140                        "' does not have anoperand named '$" + Name + "'!");

141      }

 

146      bool CGIOperandList::hasOperandNamed(StringRefName, unsigned &OpIdx) const {

147        assert(!Name.empty()&& "Cannot search for operand with no name!");

148        for (unsignedi = 0, e = OperandList.size(); i != e; ++i)

149          if (OperandList[i].Name == Name) {

150            OpIdx = i;

151            return true;

152          }

153        return false;

154      }

如果有多个子操作数,还必须明确地给出子操作数。操作数的索引与子操作数在操作数中的索引作为一个std::pair返回给ParseConstraint。在215行,Ops是传入的CGIOperandList类型的引用,CGIOperandList重载了[]操作符,返回OperandList容器指定索引处的内容,即OperandInfo实例。同一行的Constraints是OperandInfo中类型为std::vector<ConstraintInfo>的容器,而getEarlyClobber返回一个ConstraintInfo实例来记录这个EarlyClobber约束。:

33            class ConstraintInfo {

34              enum {None, EarlyClobber, Tied } Kind;

35              unsigned OtherTiedOperand;

36            public:

37              ConstraintInfo() : Kind(None) {}

38       

39              static ConstraintInfo getEarlyClobber() {

40                ConstraintInfo I;

41                I.Kind = EarlyClobber;

42                I.OtherTiedOperand = 0;

43                return I;

44              }

45       

46              static ConstraintInfo getTied(unsigned Op) {

47                ConstraintInfo I;

48                I.Kind = Tied;

49                I.OtherTiedOperand = Op;

50                return I;

51              }

同样在253行,getTied方法返回记录绑定约束的ConstraintInfo实例。不过,由于可能涉及子操作数,在将索引交给getTied之前,需要一个方式将操作数与子操作数的索引编码。

179          unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned>Op) const {

180            return OperandList[Op.first].MIOperandNo + Op.second;

181          }

这实际上就是LLVM的MachineInstr给操作数编号的方式——把子操作数一字排开。

回到CodeGenInstruction的构造函数。Instruction定义中的DisableEncoding成员列出了不能编码入输出MachineInstr的操作数,需要通过OperandInfo类型为std::vector<bool>的容器DoNotEncode把它们标记出来。

273      void CGIOperandList::ProcessDisableEncoding(std::stringDisableEncoding) {

274        while (1) {

275          std::pair<StringRef, StringRef> P =getToken(DisableEncoding, " ,\t");

276          std::string OpName = P.first;

277          DisableEncoding = P.second;

278          if (OpName.empty()) break;

279     

280          // Figure outwhich operand this is.

281          std::pair<unsigned,unsigned> Op =ParseOperandName(OpName, false);

282     

283          // Mark theoperand as not-to-be encoded.

284          if (Op.second >=OperandList[Op.first].DoNotEncode.size())

285           OperandList[Op.first].DoNotEncode.resize(Op.second+1);

286         OperandList[Op.first].DoNotEncode[Op.second] = true;

287        }

288     

289      }

最后,如果指令被弃用,其Instruction定义还必须继承一个特殊类ComplexDeprecationPredicate(Target.td)。

1110   classComplexDeprecationPredicate<stringdep> {

1111     string ComplexDeprecationPredicate = dep;

1112   }

参数dep用于指定进行启用指令检测的函数名,比如(ARMInstrInfo.td):

5715   // 'it' blocks in ARM modejust validate the predicates. The IT itself

5716   // is discarded.

5717   def ITasm : ARMAsmPseudo<"it$mask $cc",(ins it_pred:$cc, it_mask:$mask)>,

5718            ComplexDeprecationPredicate<"IT">;

在对应的MCInstrDesc实例里将会援引函数getITDeprecationInfo来进行检启用指令测。因此,这里将这个字符串保存到CodeGenInstruction的成员DeprecatedReason里。

回到CodeGenDAGPatterns::ParseInstructions,3087行的InstInfo.Operands.NumDefs是这条指令的输出操作数的个数(在前面处理的时候,先处理输出操作数,再是输入操作数)。因此,临时容器Results与Operands分别保存输出与输入操作数,而ImpResults则保存隐含的结果。在3098行,因为没有模式,在调用DAGInstruction的构造函数时传入的第一个参数为null。

原创粉丝点击