IRMatchers.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. //=== unittests/CodeGen/IRMatchers.h - Match on the LLVM IR -----*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. /// This file provides a simple mechanism for performing search operations over
  10. /// IR including metadata and types. It allows writing complex search patterns
  11. /// using understandable syntax. For instance, the code:
  12. ///
  13. /// \code
  14. /// const BasicBlock *BB = ...
  15. /// const Instruction *I = match(BB,
  16. /// MInstruction(Instruction::Store,
  17. /// MConstInt(4, 8),
  18. /// MMTuple(
  19. /// MMTuple(
  20. /// MMString("omnipotent char"),
  21. /// MMTuple(
  22. /// MMString("Simple C/C++ TBAA")),
  23. /// MConstInt(0, 64)),
  24. /// MSameAs(0),
  25. /// MConstInt(0))));
  26. /// \endcode
  27. ///
  28. /// searches the basic block BB for the 'store' instruction, first argument of
  29. /// which is 'i8 4', and the attached metadata has an item described by the
  30. /// given tree.
  31. //===----------------------------------------------------------------------===//
  32. #ifndef CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
  33. #define CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
  34. #include "llvm/ADT/PointerUnion.h"
  35. #include "llvm/IR/BasicBlock.h"
  36. #include "llvm/IR/Constants.h"
  37. #include "llvm/IR/Instruction.h"
  38. #include "llvm/IR/Metadata.h"
  39. #include "llvm/IR/Value.h"
  40. namespace llvm {
  41. /// Keeps information about pending match queries.
  42. ///
  43. /// This class stores state of all unfinished match actions. It allows to
  44. /// use queries like "this operand is the same as n-th operand", which are
  45. /// hard to implement otherwise.
  46. ///
  47. class MatcherContext {
  48. public:
  49. /// Describes pending match query.
  50. ///
  51. /// The query is represented by the current entity being investigated (type,
  52. /// value or metadata). If the entity is a member of a list (like arguments),
  53. /// the query also keeps the entity number in that list.
  54. ///
  55. class Query {
  56. PointerUnion3<const Value *, const Metadata *, const Type *> Entity;
  57. unsigned OperandNo;
  58. public:
  59. Query(const Value *V, unsigned N) : Entity(V), OperandNo(N) {}
  60. Query(const Metadata *M, unsigned N) : Entity(M), OperandNo(N) {}
  61. Query(const Type *T, unsigned N) : Entity(T), OperandNo(N) {}
  62. template<typename T>
  63. const T *get() const {
  64. return Entity.dyn_cast<const T *>();
  65. }
  66. unsigned getOperandNo() const { return OperandNo; }
  67. };
  68. template<typename T>
  69. void push(const T *V, unsigned N = ~0) {
  70. MatchStack.push_back(Query(V, N));
  71. }
  72. void pop() { MatchStack.pop_back(); }
  73. template<typename T>
  74. const T *top() const { return MatchStack.back().get<T>(); }
  75. size_t size() const { return MatchStack.size(); }
  76. unsigned getOperandNo() const { return MatchStack.back().getOperandNo(); }
  77. /// Returns match query at the given offset from the top of queries.
  78. ///
  79. /// Offset 0 corresponds to the topmost query.
  80. ///
  81. const Query &getQuery(unsigned Offset) const {
  82. assert(MatchStack.size() > Offset);
  83. return MatchStack[MatchStack.size() - 1 - Offset];
  84. }
  85. private:
  86. SmallVector<Query, 8> MatchStack;
  87. };
  88. /// Base of all matcher classes.
  89. ///
  90. class Matcher {
  91. public:
  92. virtual ~Matcher() {}
  93. /// Returns true if the entity on the top of the specified context satisfies
  94. /// the matcher condition.
  95. ///
  96. virtual bool match(MatcherContext &MC) = 0;
  97. };
  98. /// Base class of matchers that test particular entity.
  99. ///
  100. template<typename T>
  101. class EntityMatcher : public Matcher {
  102. public:
  103. bool match(MatcherContext &MC) override {
  104. if (auto V = MC.top<T>())
  105. return matchEntity(*V, MC);
  106. return false;
  107. }
  108. virtual bool matchEntity(const T &M, MatcherContext &C) = 0;
  109. };
  110. /// Matcher that matches any entity of the specified kind.
  111. ///
  112. template<typename T>
  113. class AnyMatcher : public EntityMatcher<T> {
  114. public:
  115. bool matchEntity(const T &M, MatcherContext &C) override { return true; }
  116. };
  117. /// Matcher that tests if the current entity satisfies the specified
  118. /// condition.
  119. ///
  120. template<typename T>
  121. class CondMatcher : public EntityMatcher<T> {
  122. std::function<bool(const T &)> Condition;
  123. public:
  124. CondMatcher(std::function<bool(const T &)> C) : Condition(C) {}
  125. bool matchEntity(const T &V, MatcherContext &C) override {
  126. return Condition(V);
  127. }
  128. };
  129. /// Matcher that save pointer to the entity that satisfies condition of the
  130. // specified matcher.
  131. ///
  132. template<typename T>
  133. class SavingMatcher : public EntityMatcher<T> {
  134. const T *&Var;
  135. std::shared_ptr<Matcher> Next;
  136. public:
  137. SavingMatcher(const T *&V, std::shared_ptr<Matcher> N) : Var(V), Next(N) {}
  138. bool matchEntity(const T &V, MatcherContext &C) override {
  139. bool Result = Next->match(C);
  140. if (Result)
  141. Var = &V;
  142. return Result;
  143. }
  144. };
  145. /// Matcher that checks that the entity is identical to another entity in the
  146. /// same container.
  147. ///
  148. class SameAsMatcher : public Matcher {
  149. unsigned OpNo;
  150. public:
  151. SameAsMatcher(unsigned N) : OpNo(N) {}
  152. bool match(MatcherContext &C) override {
  153. if (C.getOperandNo() != ~0U) {
  154. // Handle all known containers here.
  155. const MatcherContext::Query &StackRec = C.getQuery(1);
  156. if (const Metadata *MR = StackRec.get<Metadata>()) {
  157. if (const auto *MT = dyn_cast<MDTuple>(MR)) {
  158. if (OpNo < MT->getNumOperands())
  159. return C.top<Metadata>() == MT->getOperand(OpNo).get();
  160. return false;
  161. }
  162. llvm_unreachable("Unknown metadata container");
  163. }
  164. if (const Value *VR = StackRec.get<Value>()) {
  165. if (const auto *Insn = dyn_cast<Instruction>(VR)) {
  166. if (OpNo < Insn->getNumOperands())
  167. return C.top<Value>() == Insn->getOperand(OpNo);
  168. return false;
  169. }
  170. llvm_unreachable("Unknown value container");
  171. }
  172. llvm_unreachable("Unknown type container");
  173. }
  174. return false;
  175. }
  176. };
  177. /// Matcher that tests if the entity is a constant integer.
  178. ///
  179. class ConstantIntMatcher : public Matcher {
  180. uint64_t IntValue;
  181. unsigned Width;
  182. public:
  183. ConstantIntMatcher(uint64_t V, unsigned W = 0) : IntValue(V), Width(W) {}
  184. bool match(MatcherContext &Ctx) override {
  185. if (const Value *V = Ctx.top<Value>()) {
  186. if (const auto *CI = dyn_cast<ConstantInt>(V))
  187. return (Width == 0 || CI->getBitWidth() == Width) &&
  188. CI->getLimitedValue() == IntValue;
  189. }
  190. if (const Metadata *M = Ctx.top<Metadata>()) {
  191. if (const auto *MT = dyn_cast<ValueAsMetadata>(M))
  192. if (const auto *C = dyn_cast<ConstantInt>(MT->getValue()))
  193. return (Width == 0 || C->getBitWidth() == Width) &&
  194. C->getLimitedValue() == IntValue;
  195. }
  196. return false;
  197. }
  198. };
  199. /// Value matcher tuned to test instructions.
  200. ///
  201. class InstructionMatcher : public EntityMatcher<Value> {
  202. SmallVector<std::shared_ptr<Matcher>, 8> OperandMatchers;
  203. std::shared_ptr<EntityMatcher<Metadata>> MetaMatcher = nullptr;
  204. unsigned Code;
  205. public:
  206. InstructionMatcher(unsigned C) : Code(C) {}
  207. void push(std::shared_ptr<EntityMatcher<Metadata>> M) {
  208. assert(!MetaMatcher && "Only one metadata matcher may be specified");
  209. MetaMatcher = M;
  210. }
  211. void push(std::shared_ptr<Matcher> V) { OperandMatchers.push_back(V); }
  212. template<typename... Args>
  213. void push(std::shared_ptr<Matcher> V, Args... A) {
  214. push(V);
  215. push(A...);
  216. }
  217. virtual bool matchInstruction(const Instruction &I) {
  218. return I.getOpcode() == Code;
  219. }
  220. bool matchEntity(const Value &V, MatcherContext &C) override {
  221. if (const auto *I = dyn_cast<Instruction>(&V)) {
  222. if (!matchInstruction(*I))
  223. return false;
  224. if (OperandMatchers.size() > I->getNumOperands())
  225. return false;
  226. for (unsigned N = 0, E = OperandMatchers.size(); N != E; ++N) {
  227. C.push(I->getOperand(N), N);
  228. if (!OperandMatchers[N]->match(C)) {
  229. C.pop();
  230. return false;
  231. }
  232. C.pop();
  233. }
  234. if (MetaMatcher) {
  235. SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
  236. I->getAllMetadata(MDs);
  237. bool Found = false;
  238. for (auto Item : MDs) {
  239. C.push(Item.second);
  240. if (MetaMatcher->match(C)) {
  241. Found = true;
  242. C.pop();
  243. break;
  244. }
  245. C.pop();
  246. }
  247. return Found;
  248. }
  249. return true;
  250. }
  251. return false;
  252. }
  253. };
  254. /// Matcher that tests type of the current value using the specified
  255. /// type matcher.
  256. ///
  257. class ValueTypeMatcher : public EntityMatcher<Value> {
  258. std::shared_ptr<EntityMatcher<Type>> TyM;
  259. public:
  260. ValueTypeMatcher(std::shared_ptr<EntityMatcher<Type>> T) : TyM(T) {}
  261. ValueTypeMatcher(const Type *T)
  262. : TyM(new CondMatcher<Type>([T](const Type &Ty) -> bool {
  263. return &Ty == T;
  264. })) {}
  265. bool matchEntity(const Value &V, MatcherContext &Ctx) override {
  266. Type *Ty = V.getType();
  267. Ctx.push(Ty);
  268. bool Res = TyM->match(Ctx);
  269. Ctx.pop();
  270. return Res;
  271. }
  272. };
  273. /// Matcher that matches string metadata.
  274. ///
  275. class NameMetaMatcher : public EntityMatcher<Metadata> {
  276. StringRef Name;
  277. public:
  278. NameMetaMatcher(StringRef N) : Name(N) {}
  279. bool matchEntity(const Metadata &M, MatcherContext &C) override {
  280. if (auto *MDS = dyn_cast<MDString>(&M))
  281. return MDS->getString().equals(Name);
  282. return false;
  283. }
  284. };
  285. /// Matcher that matches metadata tuples.
  286. ///
  287. class MTupleMatcher : public EntityMatcher<Metadata> {
  288. SmallVector<std::shared_ptr<Matcher>, 4> Operands;
  289. public:
  290. void push(std::shared_ptr<Matcher> M) { Operands.push_back(M); }
  291. template<typename... Args>
  292. void push(std::shared_ptr<Matcher> M, Args... A) {
  293. push(M);
  294. push(A...);
  295. }
  296. bool matchEntity(const Metadata &M, MatcherContext &C) override {
  297. if (const auto *MT = dyn_cast<MDTuple>(&M)) {
  298. if (MT->getNumOperands() != Operands.size())
  299. return false;
  300. for (unsigned I = 0, E = MT->getNumOperands(); I != E; ++I) {
  301. const MDOperand &Op = MT->getOperand(I);
  302. C.push(Op.get(), I);
  303. if (!Operands[I]->match(C)) {
  304. C.pop();
  305. return false;
  306. }
  307. C.pop();
  308. }
  309. return true;
  310. }
  311. return false;
  312. }
  313. };
  314. // Helper function used to construct matchers.
  315. inline std::shared_ptr<Matcher> MSameAs(unsigned N) {
  316. return std::shared_ptr<Matcher>(new SameAsMatcher(N));
  317. }
  318. template<typename... T>
  319. std::shared_ptr<InstructionMatcher> MInstruction(unsigned C, T... Args) {
  320. auto Result = new InstructionMatcher(C);
  321. Result->push(Args...);
  322. return std::shared_ptr<InstructionMatcher>(Result);
  323. }
  324. inline std::shared_ptr<Matcher> MConstInt(uint64_t V, unsigned W = 0) {
  325. return std::shared_ptr<Matcher>(new ConstantIntMatcher(V, W));
  326. }
  327. inline std::shared_ptr<EntityMatcher<Value>>
  328. MValType(std::shared_ptr<EntityMatcher<Type>> T) {
  329. return std::shared_ptr<EntityMatcher<Value>>(new ValueTypeMatcher(T));
  330. }
  331. inline std::shared_ptr<EntityMatcher<Value>> MValType(const Type *T) {
  332. return std::shared_ptr<EntityMatcher<Value>>(new ValueTypeMatcher(T));
  333. }
  334. inline std::shared_ptr<EntityMatcher<Type>>
  335. MType(std::function<bool(const Type &)> C) {
  336. return std::shared_ptr<EntityMatcher<Type>>(new CondMatcher<Type>(C));
  337. }
  338. inline std::shared_ptr<EntityMatcher<Metadata>> MMAny() {
  339. return std::shared_ptr<EntityMatcher<Metadata>>(new AnyMatcher<Metadata>);
  340. }
  341. inline std::shared_ptr<EntityMatcher<Metadata>>
  342. MMSave(const Metadata *&V, std::shared_ptr<EntityMatcher<Metadata>> M) {
  343. return std::shared_ptr<EntityMatcher<Metadata>>(
  344. new SavingMatcher<Metadata>(V, M));
  345. }
  346. inline std::shared_ptr<EntityMatcher<Metadata>> MMString(const char *Name) {
  347. return std::shared_ptr<EntityMatcher<Metadata>>(new NameMetaMatcher(Name));
  348. }
  349. template<typename... T>
  350. std::shared_ptr<EntityMatcher<Metadata>> MMTuple(T... Args) {
  351. auto Res = new MTupleMatcher();
  352. Res->push(Args...);
  353. return std::shared_ptr<EntityMatcher<Metadata>>(Res);
  354. }
  355. /// Looks for the instruction that satisfies condition of the specified
  356. /// matcher inside the given basic block.
  357. /// \returns Pointer to the found instruction or nullptr if such instruction
  358. /// was not found.
  359. ///
  360. inline const Instruction *match(const BasicBlock *BB,
  361. std::shared_ptr<Matcher> M) {
  362. MatcherContext MC;
  363. for (const auto &I : *BB) {
  364. MC.push(&I);
  365. if (M->match(MC))
  366. return &I;
  367. MC.pop();
  368. }
  369. assert(MC.size() == 0);
  370. return nullptr;
  371. }
  372. /// Looks for the instruction that satisfies condition of the specified
  373. /// matcher starting from the specified instruction inside the same basic block.
  374. ///
  375. /// The given instruction is not checked.
  376. ///
  377. inline const Instruction *matchNext(const Instruction *I, std::shared_ptr<Matcher> M) {
  378. if (!I)
  379. return nullptr;
  380. MatcherContext MC;
  381. const BasicBlock *BB = I->getParent();
  382. if (!BB)
  383. return nullptr;
  384. for (auto P = ++BasicBlock::const_iterator(I), E = BB->end(); P != E; ++P) {
  385. MC.push(&*P);
  386. if (M->match(MC))
  387. return &*P;
  388. MC.pop();
  389. }
  390. assert(MC.size() == 0);
  391. return nullptr;
  392. }
  393. }
  394. #endif