LLVM学习笔记(54)

Posted wuhui_gdnt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LLVM学习笔记(54)相关的知识,希望对你有一定的参考价值。

3.11.2.2. 匹配表的生成对象

GlobalISelEmitter::run() 4267行循环遍历前面生成的所有PatternToMatch对象(PatternToMatch的生成参考DAG指令选择器的生成代码一节),对每个PatternToMatch对象调用下面的方法来构建对应的Matcher实例(类似于SelectionDAG生成代码时构建的另一个版本的Matcher)。在下面3837行对每个PatternToMatch对象都会创建一个新的RuleMatcher实例来执行对它的处理。

3834  Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P)

3835    // Keep track of the matchers and actions to emit.

3836    int Score = P.getPatternComplexity(CGP);

3837    RuleMatcher M(P.getSrcRecord()->getLoc());

3838    RuleMatcherScores[M.getRuleID()] = Score;

3839    M.addAction<DebugCommentAction>(llvm::to_string(*P.getSrcPattern()) +

3840                                    "  =>  " +

3841                                    llvm::to_string(*P.getDstPattern()));

3842 

3843    if (auto Error = importRulePredicates(M, P.getPredicates()))

3844      return std::move(Error);

3845 

3846    // Next, analyze the pattern operators.

3847    TreePatternNode *Src = P.getSrcPattern();

3848    TreePatternNode *Dst = P.getDstPattern();

3849 

3850    // If the root of either pattern isn't a simple operator, ignore it.

3851    if (auto Err = isTrivialOperatorNode(Dst))

3852      return failedImport("Dst pattern root isn't a trivial operator (" +

3853                          toString(std::move(Err)) + ")");

3854    if (auto Err = isTrivialOperatorNode(Src))

3855      return failedImport("Src pattern root isn't a trivial operator (" +

3856                          toString(std::move(Err)) + ")");

3857 

3858    // The different predicates and matchers created during

3859    // addInstructionMatcher use the RuleMatcher M to set up their

3860    // instruction ID (InsnVarID) that are going to be used when

3861    // M is going to be emitted.

3862    // However, the code doing the emission still relies on the IDs

3863    // returned during that process by the RuleMatcher when issuing

3864    // the recordInsn opcodes.

3865    // Because of that:

3866    // 1. The order in which we created the predicates

3867    //    and such must be the same as the order in which we emit them,

3868    //    and

3869    // 2. We need to reset the generation of the IDs in M somewhere between

3870    //    addInstructionMatcher and emit

3871    //

3872    // FIXME: Long term, we don't want to have to rely on this implicit

3873    // naming being the same. One possible solution would be to have

3874    // explicit operator for operation capture and reference those.

3875    // The plus side is that it would expose opportunities to share

3876    // the capture accross rules. The downside is that it would

3877    // introduce a dependency between predicates (captures must happen

3878    // before their first use.)

3879    InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName());

3880    unsigned TempOpIdx = 0;

3881    auto InsnMatcherOrError =

3882        createAndImportSelDAGMatcher(M, InsnMatcherTemp, Src, TempOpIdx);

3883    if (auto Error = InsnMatcherOrError.takeError())

3884      return std::move(Error);

3885    InstructionMatcher &InsnMatcher = InsnMatcherOrError.get();

3.11.2.2.1. ​​​​​​​对象体系

GlobalISelEmitterMatcher对象分为四大类。一类是Matcher直接派生类GroupMatcherSwitchMatcher以及RuleMatcher,它们负责从各个PatternToMatch实例优化、构建出指令匹配的过程路径表。Matcher是它们的基类:

622     class Matcher

623     public:

624       virtual ~Matcher() = default;

625       virtual void optimize()

626       virtual void emit(MatchTable &Table) = 0;

627    

628       virtual bool hasFirstCondition() const = 0;

629       virtual const PredicateMatcher &getFirstCondition() const = 0;

630       virtual std::unique_ptr<PredicateMatcher> popFirstCondition() = 0;

631     ;

另一类则是完成各种操作数匹配操作的谓词(predicate)类,它们将具体实现操作数各属性的匹配。PredicateMatcher是它们最底层的基类:

1003  class PredicateMatcher

1004  public:

1005    /// This enum is used for RTTI and also defines the priority that is given to

1006    /// the predicate when generating the matcher code. Kinds with higher priority

1007    /// must be tested first.

1008    ///

1009    /// The relative priority of OPM_LLT, OPM_RegBank, and OPM_MBB do not matter

1010    /// but OPM_Int must have priority over OPM_RegBank since constant integers

1011    /// are represented by a virtual register defined by a G_CONSTANT instruction.

1012    ///

1013    /// Note: The relative priority between IPM_ and OPM_ does not matter, they

1014    /// are currently not compared between each other.

1015    enum PredicateKind

1016      IPM_Opcode,

1017      IPM_NumOperands,

1018      IPM_ImmPredicate,

1019      IPM_AtomicOrderingMMO,

1020      IPM_MemoryLLTSize,

1021      IPM_MemoryVsLLTSize,

1022      IPM_GenericPredicate,

1023      OPM_SameOperand,

1024      OPM_ComplexPattern,

1025      OPM_IntrinsicID,

1026      OPM_Instruction,

1027      OPM_Int,

1028      OPM_LiteralInt,

1029      OPM_LLT,

1030      OPM_PointerToAny,

1031      OPM_RegBank,

1032      OPM_MBB,

1033    ;

1034 

1035  protected:

1036    PredicateKind Kind;

1037    unsigned InsnVarID;

1038    unsigned OpIdx;

1039 

1040  public:

1041    PredicateMatcher(PredicateKind Kind, unsigned InsnVarID, unsigned OpIdx = ~0)

1042        : Kind(Kind), InsnVarID(InsnVarID), OpIdx(OpIdx)

1043 

1044    unsigned getInsnVarID() const return InsnVarID;

1045    unsigned getOpIdx() const return OpIdx;

1046 

1047    virtual ~PredicateMatcher() = default;

1048    /// Emit MatchTable opcodes that check the predicate for the given operand.

1049    virtual void emitPredicateOpcodes(MatchTable &Table,

1050                                      RuleMatcher &Rule) const = 0;

1051 

1052    PredicateKind getKind() const return Kind;

1053 

1054    virtual bool isIdentical(const PredicateMatcher &B) const

1055      return B.getKind() == getKind() && InsnVarID == B.InsnVarID &&

1056             OpIdx == B.OpIdx;

1057   

1058 

1059    virtual bool isIdenticalDownToValue(const PredicateMatcher &B) const

1060      return hasValue() && PredicateMatcher::isIdentical(B);

1061   

1062 

1063    virtual MatchTableRecord getValue() const

1064      assert(hasValue() && "Can not get a value of a value-less predicate!");

1065      llvm_unreachable("Not implemented yet");

1066   

1067    virtual bool hasValue() const return false;

1068 

1069    /// Report the maximum number of temporary operands needed by the predicate

1070    /// matcher.

1071    virtual unsigned countRendererFns() const return 0;

1072  ;

PredicateMatcher派生出OperandPredicateMatcher,这是操作数属性谓词Matcher的基类:

1080  class OperandPredicateMatcher : public PredicateMatcher

1081  public:

1082    OperandPredicateMatcher(PredicateKind Kind, unsigned InsnVarID,

1083                            unsigned OpIdx)

1084        : PredicateMatcher(Kind, InsnVarID, OpIdx)

1085    virtual ~OperandPredicateMatcher()

1086 

1087    /// Compare the priority of this object and B.

1088    ///

1089    /// Returns true if this object is more important than B.

1090    virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const;

1091  ;

OperandPredicateMatcher最后派生出SameOperandMatcherPointerToAnyOperandMatcherComplexPatternOperandMatcherRegisterBankOperandMatcherMBBOperandMatcherConstantIntOperandMatcherLiteralIntOperandMatcherIntrinsicIDOperandMatcherInstructionOperandMatcherLLTOperandMatcher

第三类是完成各种指令属性匹配的Matcher类。它们最底下基类仍然是PredicateMatcher,在这之上派生出InstructionPredicateMatcher

1521  class InstructionPredicateMatcher : public PredicateMatcher

1522  public:

1523    InstructionPredicateMatcher(PredicateKind Kind, unsigned InsnVarID)

1524        : PredicateMatcher(Kind, InsnVarID)

1525    virtual ~InstructionPredicateMatcher()

1526 

1527    /// Compare the priority of this object and B.

1528    ///

1529    /// Returns true if this object is more important than B.

1530    virtual bool

1531    isHigherPriorityThan(const InstructionPredicateMatcher &B) const

1532      return Kind < B.Kind;

1533    ;

1534  ;

InstructionPredicateMatcher最后派生出InstructionOpcodeMatcherInstructionNumOperandsMatcherInstructionImmPredicateMatcherAtomicOrderingMMOPredicateMatcherMemorySizePredicateMatcherMemoryVsLLTSizePredicateMatcherGenericInstructionPredicateMatcher

最后是使用前面操作数属性匹配Matcher执行操作数匹配的Matcher类,以及使用指令属性匹配Matcher与操作数匹配Matcher执行指令匹配的Matcher类,PredicateListMatcher是它们的基类。

935     template <class PredicateTy> class PredicateListMatcher

936     private:

937       /// Template instantiations should specialize this to return a string to use

938       /// for the comment emitted when there are no predicates.

939       std::string getNoPredicateComment() const;

940    

941     protected:

942       using PredicatesTy = std::deque<std::unique_ptr<PredicateTy>>;

943       PredicatesTy Predicates;

944    

945      /// Track if the list of predicates was manipulated by one of the optimization

946       /// methods.

947       bool Optimized = false;

948    

949     public:

950       /// Construct a new predicate and add it to the matcher.

951       template <class Kind, class... Args>

952       Optional<Kind *> addPredicate(Args &&... args);

953    

954       typename PredicatesTy::iterator predicates_begin()

955         return Predicates.begin();

956      

957       typename PredicatesTy::iterator predicates_end()

958         return Predicates.end();

959      

960       iterator_range<typename PredicatesTy::iterator> predicates()

961         return make_range(predicates_begin(), predicates_end());

962      

963       typename PredicatesTy::size_type predicates_size() const

964         return Predicates.size();

965      

966     bool predicates_empty() const return Predicates.empty();

967    

968       std::unique_ptr<PredicateTy> predicates_pop_front()

969         std::unique_ptr<PredicateTy> Front = std::move(Predicates.front());

970         Predicates.pop_front();

971         Optimized = true;

972         return Front;

973      

974    

975       void prependPredicate(std::unique_ptr<PredicateTy> &&Predicate)

976         Predicates.push_front(std::move(Predicate));

977      

978    

979       void eraseNullPredicates()

980         const auto NewEnd =

981             std::stable_partition(Predicates.begin(), Predicates.end(),

982                                   std::logical_not<std::unique_ptr<PredicateTy>>());

983         if (NewEnd != Predicates.begin())

984           Predicates.erase(Predicates.begin(), NewEnd);

985           Optimized = true;

986        

987      

988    

989       /// Emit MatchTable opcodes that tests whether all the predicates are met.

990       template <class... Args>

991       void emitPredicateListOpcodes(MatchTable &Table, Args &&... args)

992         if (Predicates.empty() && !Optimized)

993           Table << MatchTable::Comment(getNoPredicateComment())

994                 << MatchTable::LineBreak;

995           return;

996        

997    

998         for (const auto &Predicate : predicates())

999           Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);

1000   

1001  ;

目前PredicateListMatcher的一个派生类之一是OperandMatcher

1382  class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher>

1383  protected:

1384    InstructionMatcher &Insn;

1385    unsigned OpIdx;

1386    std::string SymbolicName;

1387 

1388    /// The index of the first temporary variable allocated to this operand. The

1389    /// number of allocated temporaries can be found with

1390    /// countRendererFns().

1391    unsigned AllocatedTemporariesBaseID;

1392 

1393  public:

1394    OperandMatcher(InstructionMatcher &Insn, unsigned OpIdx,

1395                   const std::string &SymbolicName,

1396                   unsigned AllocatedTemporariesBaseID)

1397        : Insn(Insn), OpIdx(OpIdx), SymbolicName(SymbolicName),

1398          AllocatedTemporariesBaseID(AllocatedTemporariesBaseID)

1399 

1400    bool hasSymbolicName() const return !SymbolicName.empty();

1401    const StringRef getSymbolicName() const return SymbolicName;

1402    void setSymbolicName(StringRef Name)

1403      assert(SymbolicName.empty() && "Operand already has a symbolic name");

1404      SymbolicName = Name;

1405   

1406 

1407    /// Construct a new operand predicate and add it to the matcher.

1408    template <class Kind, class... Args>

1409    Optional<Kind *> addPredicate(Args &&... args)

1410      if (isSameAsAnotherOperand())

1411        return None;

1412      Predicates.emplace_back(llvm::make_unique<Kind>(

1413          getInsnVarID(), getOpIdx(), std::forward<Args>(args)...));

1414      return static_cast<Kind *>(Predicates.back().get());

1415   

1416 

1417    unsigned getOpIdx() const return OpIdx;

1418    unsigned getInsnVarID() const;

1419 

1420    std::string getOperandExpr(unsigned InsnVarID) const

1421      return "State.MIs[" + llvm::to_string(InsnVarID) + "]->getOperand(" +

1422             llvm::to_string(OpIdx) + ")";

1423   

1424 

1425    InstructionMatcher &getInstructionMatcher() const return Insn;

1426 

1427    Error addTypeCheckPredicate(const TypeSetByHwMode &VTy,

1428                                bool OperandIsAPointer);

1429 

1430    /// Emit MatchTable opcodes that test whether the instruction named in

1431    /// InsnVarID matches all the predicates and all the operands.

1432    void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule)

1433      if (!Optimized)

1434        std::string Comment;

1435        raw_string_ostream CommentOS(Comment);

1436        CommentOS << "MIs[" << getInsnVarID() << "] ";

1437        if (SymbolicName.empty())

1438          CommentOS << "Operand " << OpIdx;

1439        else

1440          CommentOS << SymbolicName;

1441        Table << MatchTable::Comment(CommentOS.str()) << MatchTable::LineBreak;

1442     

1443 

1444      emitPredicateListOpcodes(Table, Rule);

1445   

1446 

1447    /// Compare the priority of this object and B.

1448    ///

1449    /// Returns true if this object is more important than B.

1450    bool isHigherPriorityThan(OperandMatcher &B)

1451      // Operand matchers involving more predicates have higher priority.

1452      if (predicates_size() > B.predicates_size())

1453        return true;

1454      if (predicates_size() < B.predicates_size())

1455        return false;

1456 

1457      // This assumes that predicates are added in a consistent order.

1458      for (auto &&Predicate : zip(predicates(), B.predicates()))

1459        if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate)))

1460          return true;

1461        if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate)))

1462          return false;

1463     

1464 

1465      return false;

1466    ;

1467 

1468    /// Report the maximum number of temporary operands needed by the operand

1469    /// matcher.

1470    unsigned countRendererFns()

1471      return std::accumulate(

1472          predicates().begin(), predicates().end(), 0,

1473          [](unsigned A,

1474             const std::unique_ptr<OperandPredicateMatcher> &Predicate)

1475            return A + Predicate->countRendererFns();

1476          );

1477   

1478 

1479    unsigned getAllocatedTemporariesBaseID() const

1480      return AllocatedTemporariesBaseID;

1481   

1482 

1483    bool isSameAsAnotherOperand()

1484      for (const auto &Predicate : predicates())

1485        if (isa<SameOperandMatcher>(Predicate))

1486          return true;

1487      return false;

1488   

1489  ;

另一个则是InstructionMatcher(仅显示数据成员和构造函数):

1856  class InstructionMatcher final : public PredicateListMatcher<PredicateMatcher>

1857  protected:

1858    typedef std::vector<std::unique_ptr<OperandMatcher>> OperandVec;

1859 

1860    RuleMatcher &Rule;

1861 

1862    /// The operands to match. All rendered operands must be present even if the

1863    /// condition is always true.

1864    OperandVec Operands;

1865    bool NumOperandsCheck = true;

1866 

1867    std::string SymbolicName;

1868    unsigned InsnVarID;

1869 

1870  public:

1871    InstructionMatcher(RuleMatcher &Rule, StringRef SymbolicName)

1872        : Rule(Rule), SymbolicName(SymbolicName)

1873      // We create a new instruction matcher.

1874      // Get a new ID for that instruction.

1875      InsnVarID = Rule.implicitlyDefineInsnVar(*this);

1876   

在上述Matcher匹配成功时,可以执行某些活动。典型的活动有:改变一条指令的操作码;向一条指令添加操作数。这些通过MatchAction类型体系来描述。

2472  class MatchAction

2473  public:

2474    virtual ~MatchAction()

2475 

2476    /// Emit the MatchTable opcodes to implement the action.

2477    virtual void emitActionOpcodes(MatchTable &Table,

2478                                   RuleMatcher &Rule) const = 0;

2479  ;

MatchAction派生出DebugCommentActionConstrainOperandsToDefinitionActionBuildMIActionConstrainOperandToRegClassActionMakeTempRegisterAction。后面,我们会看到其中一些的定义。

不过,对于指令操作数,MatchAction类并不触及,而是交由OperandRenderer派生类处理。基类OperandRenderer是这样的:

2112  class OperandRenderer

2113  public:

2114    enum RendererKind

2115      OR_Copy,

2116      OR_CopyOrAddZeroReg,

2117      OR_CopySubReg,

2118      OR_CopyConstantAsImm,

2119      OR_CopyFConstantAsFPImm,

2120      OR_Imm,

2121      OR_Register,

2122      OR_TempRegister,

2123      OR_ComplexPattern,

2124      OR_Custom

2125    ;

2126 

2127  protected:

2128    RendererKind Kind;

2129 

21

以上是关于LLVM学习笔记(54)的主要内容,如果未能解决你的问题,请参考以下文章

LLVM学习笔记(52)

LLVM学习笔记(52)

LLVM学习笔记(43-2)

LLVM学习笔记(44-2)

LLVM学习笔记(53)

LLVM学习笔记(53)