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. 对象体系
在GlobalISelEmitter中Matcher对象分为四大类。一类是Matcher直接派生类GroupMatcher、SwitchMatcher以及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最后派生出SameOperandMatcher、PointerToAnyOperandMatcher、ComplexPatternOperandMatcher、RegisterBankOperandMatcher、MBBOperandMatcher、ConstantIntOperandMatcher、LiteralIntOperandMatcher、IntrinsicIDOperandMatcher、InstructionOperandMatcher、LLTOperandMatcher。
第三类是完成各种指令属性匹配的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最后派生出InstructionOpcodeMatcher、InstructionNumOperandsMatcher、InstructionImmPredicateMatcher、AtomicOrderingMMOPredicateMatcher、MemorySizePredicateMatcher、MemoryVsLLTSizePredicateMatcher、GenericInstructionPredicateMatcher。
最后是使用前面操作数属性匹配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派生出DebugCommentAction、ConstrainOperandsToDefinitionAction、BuildMIAction、ConstrainOperandToRegClassAction、MakeTempRegisterAction。后面,我们会看到其中一些的定义。
不过,对于指令操作数,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)的主要内容,如果未能解决你的问题,请参考以下文章