1 //=== unittests/CodeGen/IRMatchers.h - Match on the LLVM IR -----*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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:
14 /// const BasicBlock *BB = ...
15 /// const Instruction *I = match(BB,
16 /// MInstruction(Instruction::Store,
20 /// MMString("omnipotent char"),
22 /// MMString("Simple C/C++ TBAA")),
23 /// MConstInt(0, 64)),
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
31 //===----------------------------------------------------------------------===//
33 #ifndef CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
34 #define CLANG_UNITTESTS_CODEGEN_IRMATCHERS_H
36 #include "llvm/ADT/PointerUnion.h"
37 #include "llvm/IR/BasicBlock.h"
38 #include "llvm/IR/Constants.h"
39 #include "llvm/IR/Instruction.h"
40 #include "llvm/IR/Metadata.h"
41 #include "llvm/IR/Value.h"
45 /// Keeps information about pending match queries.
47 /// This class stores state of all unfinished match actions. It allows to
48 /// use queries like "this operand is the same as n-th operand", which are
49 /// hard to implement otherwise.
51 class MatcherContext
{
54 /// Describes pending match query.
56 /// The query is represented by the current entity being investigated (type,
57 /// value or metadata). If the entity is a member of a list (like arguments),
58 /// the query also keeps the entity number in that list.
61 PointerUnion
<const Value
*, const Metadata
*, const Type
*> Entity
;
65 Query(const Value
*V
, unsigned N
) : Entity(V
), OperandNo(N
) {}
66 Query(const Metadata
*M
, unsigned N
) : Entity(M
), OperandNo(N
) {}
67 Query(const Type
*T
, unsigned N
) : Entity(T
), OperandNo(N
) {}
70 const T
*get() const {
71 return Entity
.dyn_cast
<const T
*>();
74 unsigned getOperandNo() const { return OperandNo
; }
78 void push(const T
*V
, unsigned N
= ~0) {
79 MatchStack
.push_back(Query(V
, N
));
82 void pop() { MatchStack
.pop_back(); }
85 const T
*top() const { return MatchStack
.back().get
<T
>(); }
87 size_t size() const { return MatchStack
.size(); }
89 unsigned getOperandNo() const { return MatchStack
.back().getOperandNo(); }
91 /// Returns match query at the given offset from the top of queries.
93 /// Offset 0 corresponds to the topmost query.
95 const Query
&getQuery(unsigned Offset
) const {
96 assert(MatchStack
.size() > Offset
);
97 return MatchStack
[MatchStack
.size() - 1 - Offset
];
101 SmallVector
<Query
, 8> MatchStack
;
105 /// Base of all matcher classes.
109 virtual ~Matcher() {}
111 /// Returns true if the entity on the top of the specified context satisfies
112 /// the matcher condition.
114 virtual bool match(MatcherContext
&MC
) = 0;
118 /// Base class of matchers that test particular entity.
121 class EntityMatcher
: public Matcher
{
123 bool match(MatcherContext
&MC
) override
{
124 if (auto V
= MC
.top
<T
>())
125 return matchEntity(*V
, MC
);
128 virtual bool matchEntity(const T
&M
, MatcherContext
&C
) = 0;
132 /// Matcher that matches any entity of the specified kind.
135 class AnyMatcher
: public EntityMatcher
<T
> {
137 bool matchEntity(const T
&M
, MatcherContext
&C
) override
{ return true; }
141 /// Matcher that tests if the current entity satisfies the specified
145 class CondMatcher
: public EntityMatcher
<T
> {
146 std::function
<bool(const T
&)> Condition
;
148 CondMatcher(std::function
<bool(const T
&)> C
) : Condition(C
) {}
149 bool matchEntity(const T
&V
, MatcherContext
&C
) override
{
155 /// Matcher that save pointer to the entity that satisfies condition of the
156 // specified matcher.
159 class SavingMatcher
: public EntityMatcher
<T
> {
161 std::shared_ptr
<Matcher
> Next
;
163 SavingMatcher(const T
*&V
, std::shared_ptr
<Matcher
> N
) : Var(V
), Next(N
) {}
164 bool matchEntity(const T
&V
, MatcherContext
&C
) override
{
165 bool Result
= Next
->match(C
);
173 /// Matcher that checks that the entity is identical to another entity in the
176 class SameAsMatcher
: public Matcher
{
179 SameAsMatcher(unsigned N
) : OpNo(N
) {}
180 bool match(MatcherContext
&C
) override
{
181 if (C
.getOperandNo() != ~0U) {
182 // Handle all known containers here.
183 const MatcherContext::Query
&StackRec
= C
.getQuery(1);
184 if (const Metadata
*MR
= StackRec
.get
<Metadata
>()) {
185 if (const auto *MT
= dyn_cast
<MDTuple
>(MR
)) {
186 if (OpNo
< MT
->getNumOperands())
187 return C
.top
<Metadata
>() == MT
->getOperand(OpNo
).get();
190 llvm_unreachable("Unknown metadata container");
192 if (const Value
*VR
= StackRec
.get
<Value
>()) {
193 if (const auto *Insn
= dyn_cast
<Instruction
>(VR
)) {
194 if (OpNo
< Insn
->getNumOperands())
195 return C
.top
<Value
>() == Insn
->getOperand(OpNo
);
198 llvm_unreachable("Unknown value container");
200 llvm_unreachable("Unknown type container");
207 /// Matcher that tests if the entity is a constant integer.
209 class ConstantIntMatcher
: public Matcher
{
213 ConstantIntMatcher(uint64_t V
, unsigned W
= 0) : IntValue(V
), Width(W
) {}
214 bool match(MatcherContext
&Ctx
) override
{
215 if (const Value
*V
= Ctx
.top
<Value
>()) {
216 if (const auto *CI
= dyn_cast
<ConstantInt
>(V
))
217 return (Width
== 0 || CI
->getBitWidth() == Width
) &&
218 CI
->getLimitedValue() == IntValue
;
220 if (const Metadata
*M
= Ctx
.top
<Metadata
>()) {
221 if (const auto *MT
= dyn_cast
<ValueAsMetadata
>(M
))
222 if (const auto *C
= dyn_cast
<ConstantInt
>(MT
->getValue()))
223 return (Width
== 0 || C
->getBitWidth() == Width
) &&
224 C
->getLimitedValue() == IntValue
;
231 /// Value matcher tuned to test instructions.
233 class InstructionMatcher
: public EntityMatcher
<Value
> {
234 SmallVector
<std::shared_ptr
<Matcher
>, 8> OperandMatchers
;
235 std::shared_ptr
<EntityMatcher
<Metadata
>> MetaMatcher
= nullptr;
238 InstructionMatcher(unsigned C
) : Code(C
) {}
240 void push(std::shared_ptr
<EntityMatcher
<Metadata
>> M
) {
241 assert(!MetaMatcher
&& "Only one metadata matcher may be specified");
244 void push(std::shared_ptr
<Matcher
> V
) { OperandMatchers
.push_back(V
); }
245 template<typename
... Args
>
246 void push(std::shared_ptr
<Matcher
> V
, Args
... A
) {
251 virtual bool matchInstruction(const Instruction
&I
) {
252 return I
.getOpcode() == Code
;
255 bool matchEntity(const Value
&V
, MatcherContext
&C
) override
{
256 if (const auto *I
= dyn_cast
<Instruction
>(&V
)) {
257 if (!matchInstruction(*I
))
259 if (OperandMatchers
.size() > I
->getNumOperands())
261 for (unsigned N
= 0, E
= OperandMatchers
.size(); N
!= E
; ++N
) {
262 C
.push(I
->getOperand(N
), N
);
263 if (!OperandMatchers
[N
]->match(C
)) {
270 SmallVector
<std::pair
<unsigned, MDNode
*>, 8> MDs
;
271 I
->getAllMetadata(MDs
);
273 for (auto Item
: MDs
) {
275 if (MetaMatcher
->match(C
)) {
291 /// Matcher that tests type of the current value using the specified
294 class ValueTypeMatcher
: public EntityMatcher
<Value
> {
295 std::shared_ptr
<EntityMatcher
<Type
>> TyM
;
297 ValueTypeMatcher(std::shared_ptr
<EntityMatcher
<Type
>> T
) : TyM(T
) {}
298 ValueTypeMatcher(const Type
*T
)
299 : TyM(new CondMatcher
<Type
>([T
](const Type
&Ty
) -> bool {
302 bool matchEntity(const Value
&V
, MatcherContext
&Ctx
) override
{
303 Type
*Ty
= V
.getType();
305 bool Res
= TyM
->match(Ctx
);
312 /// Matcher that matches string metadata.
314 class NameMetaMatcher
: public EntityMatcher
<Metadata
> {
317 NameMetaMatcher(StringRef N
) : Name(N
) {}
318 bool matchEntity(const Metadata
&M
, MatcherContext
&C
) override
{
319 if (auto *MDS
= dyn_cast
<MDString
>(&M
))
320 return MDS
->getString() == Name
;
326 /// Matcher that matches metadata tuples.
328 class MTupleMatcher
: public EntityMatcher
<Metadata
> {
329 SmallVector
<std::shared_ptr
<Matcher
>, 4> Operands
;
331 void push(std::shared_ptr
<Matcher
> M
) { Operands
.push_back(M
); }
332 template<typename
... Args
>
333 void push(std::shared_ptr
<Matcher
> M
, Args
... A
) {
337 bool matchEntity(const Metadata
&M
, MatcherContext
&C
) override
{
338 if (const auto *MT
= dyn_cast
<MDTuple
>(&M
)) {
339 if (MT
->getNumOperands() != Operands
.size())
341 for (unsigned I
= 0, E
= MT
->getNumOperands(); I
!= E
; ++I
) {
342 const MDOperand
&Op
= MT
->getOperand(I
);
344 if (!Operands
[I
]->match(C
)) {
357 // Helper function used to construct matchers.
359 inline std::shared_ptr
<Matcher
> MSameAs(unsigned N
) {
360 return std::shared_ptr
<Matcher
>(new SameAsMatcher(N
));
363 template<typename
... T
>
364 std::shared_ptr
<InstructionMatcher
> MInstruction(unsigned C
, T
... Args
) {
365 auto Result
= new InstructionMatcher(C
);
366 Result
->push(Args
...);
367 return std::shared_ptr
<InstructionMatcher
>(Result
);
370 inline std::shared_ptr
<Matcher
> MConstInt(uint64_t V
, unsigned W
= 0) {
371 return std::shared_ptr
<Matcher
>(new ConstantIntMatcher(V
, W
));
374 inline std::shared_ptr
<EntityMatcher
<Value
>>
375 MValType(std::shared_ptr
<EntityMatcher
<Type
>> T
) {
376 return std::shared_ptr
<EntityMatcher
<Value
>>(new ValueTypeMatcher(T
));
379 inline std::shared_ptr
<EntityMatcher
<Value
>> MValType(const Type
*T
) {
380 return std::shared_ptr
<EntityMatcher
<Value
>>(new ValueTypeMatcher(T
));
383 inline std::shared_ptr
<EntityMatcher
<Type
>>
384 MType(std::function
<bool(const Type
&)> C
) {
385 return std::shared_ptr
<EntityMatcher
<Type
>>(new CondMatcher
<Type
>(C
));
388 inline std::shared_ptr
<EntityMatcher
<Metadata
>> MMAny() {
389 return std::shared_ptr
<EntityMatcher
<Metadata
>>(new AnyMatcher
<Metadata
>);
392 inline std::shared_ptr
<EntityMatcher
<Metadata
>>
393 MMSave(const Metadata
*&V
, std::shared_ptr
<EntityMatcher
<Metadata
>> M
) {
394 return std::shared_ptr
<EntityMatcher
<Metadata
>>(
395 new SavingMatcher
<Metadata
>(V
, M
));
398 inline std::shared_ptr
<EntityMatcher
<Metadata
>> MMString(const char *Name
) {
399 return std::shared_ptr
<EntityMatcher
<Metadata
>>(new NameMetaMatcher(Name
));
402 template<typename
... T
>
403 std::shared_ptr
<EntityMatcher
<Metadata
>> MMTuple(T
... Args
) {
404 auto Res
= new MTupleMatcher();
406 return std::shared_ptr
<EntityMatcher
<Metadata
>>(Res
);
410 /// Looks for the instruction that satisfies condition of the specified
411 /// matcher inside the given basic block.
412 /// \returns Pointer to the found instruction or nullptr if such instruction
415 inline const Instruction
*match(const BasicBlock
*BB
,
416 std::shared_ptr
<Matcher
> M
) {
418 for (const auto &I
: *BB
) {
424 assert(MC
.size() == 0);
428 /// Looks for the instruction that satisfies condition of the specified
429 /// matcher starting from the specified instruction inside the same basic block.
431 /// The given instruction is not checked.
433 inline const Instruction
*matchNext(const Instruction
*I
, std::shared_ptr
<Matcher
> M
) {
437 const BasicBlock
*BB
= I
->getParent();
440 for (auto P
= ++BasicBlock::const_iterator(I
), E
= BB
->end(); P
!= E
; ++P
) {
446 assert(MC
.size() == 0);