MLIR  22.0.0git
NestedMatcher.cpp
Go to the documentation of this file.
1 //===- NestedMatcher.cpp - NestedMatcher Impl ----------------------------===//
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 
9 #include <utility>
10 
13 
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/Support/Allocator.h"
16 
17 using namespace mlir;
18 using namespace mlir::affine;
19 
20 llvm::BumpPtrAllocator *&NestedMatch::allocator() {
21  thread_local llvm::BumpPtrAllocator *allocator = nullptr;
22  return allocator;
23 }
24 
26  ArrayRef<NestedMatch> nestedMatches) {
27  auto *result = allocator()->Allocate<NestedMatch>();
28  auto *children = allocator()->Allocate<NestedMatch>(nestedMatches.size());
29  llvm::uninitialized_copy(nestedMatches, children);
30  new (result) NestedMatch();
31  result->matchedOperation = operation;
32  result->matchedChildren =
33  ArrayRef<NestedMatch>(children, nestedMatches.size());
34  return *result;
35 }
36 
37 llvm::BumpPtrAllocator *&NestedPattern::allocator() {
38  thread_local llvm::BumpPtrAllocator *allocator = nullptr;
39  return allocator;
40 }
41 
42 void NestedPattern::copyNestedToThis(ArrayRef<NestedPattern> nested) {
43  if (nested.empty())
44  return;
45 
46  auto *newNested = allocator()->Allocate<NestedPattern>(nested.size());
47  llvm::uninitialized_copy(nested, newNested);
48  nestedPatterns = ArrayRef<NestedPattern>(newNested, nested.size());
49 }
50 
51 void NestedPattern::freeNested() {
52  for (const auto &p : nestedPatterns)
53  p.~NestedPattern();
54 }
55 
57  FilterFunctionType filter)
58  : filter(std::move(filter)), skip(nullptr) {
59  copyNestedToThis(nested);
60 }
61 
63  : filter(other.filter), skip(other.skip) {
64  copyNestedToThis(other.nestedPatterns);
65 }
66 
68  freeNested();
69  filter = other.filter;
70  skip = other.skip;
71  copyNestedToThis(other.nestedPatterns);
72  return *this;
73 }
74 
75 unsigned NestedPattern::getDepth() const {
76  if (nestedPatterns.empty()) {
77  return 1;
78  }
79  unsigned depth = 0;
80  for (auto &c : nestedPatterns) {
81  depth = std::max(depth, c.getDepth());
82  }
83  return depth + 1;
84 }
85 
86 /// Matches a single operation in the following way:
87 /// 1. checks the kind of operation against the matcher, if different then
88 /// there is no match;
89 /// 2. calls the customizable filter function to refine the single operation
90 /// match with extra semantic constraints;
91 /// 3. if all is good, recursively matches the nested patterns;
92 /// 4. if all nested match then the single operation matches too and is
93 /// appended to the list of matches;
94 /// 5. TODO: Optionally applies actions (lambda), in which case we will want
95 /// to traverse in post-order DFS to avoid invalidating iterators.
96 void NestedPattern::matchOne(Operation *op,
98  if (skip == op) {
99  return;
100  }
101  // Local custom filter function
102  if (!filter(*op)) {
103  return;
104  }
105 
106  if (nestedPatterns.empty()) {
107  SmallVector<NestedMatch, 8> nestedMatches;
108  matches->push_back(NestedMatch::build(op, nestedMatches));
109  return;
110  }
111  // Take a copy of each nested pattern so we can match it.
112  for (auto nestedPattern : nestedPatterns) {
113  SmallVector<NestedMatch, 8> nestedMatches;
114  // Skip elem in the walk immediately following. Without this we would
115  // essentially need to reimplement walk here.
116  nestedPattern.skip = op;
117  nestedPattern.match(op, &nestedMatches);
118  // If we could not match even one of the specified nestedPattern, early exit
119  // as this whole branch is not a match.
120  if (nestedMatches.empty()) {
121  return;
122  }
123  matches->push_back(NestedMatch::build(op, nestedMatches));
124  }
125 }
126 
127 static bool isAffineForOp(Operation &op) { return isa<AffineForOp>(op); }
128 
129 static bool isAffineIfOp(Operation &op) { return isa<AffineIfOp>(op); }
130 
131 namespace mlir {
132 namespace affine {
133 namespace matcher {
134 
136  return NestedPattern({}, std::move(filter));
137 }
138 
140  return NestedPattern(child, isAffineIfOp);
141 }
142 NestedPattern If(const FilterFunctionType &filter, const NestedPattern &child) {
143  return NestedPattern(child, [filter](Operation &op) {
144  return isAffineIfOp(op) && filter(op);
145  });
146 }
148  return NestedPattern(nested, isAffineIfOp);
149 }
151  ArrayRef<NestedPattern> nested) {
152  return NestedPattern(nested, [filter](Operation &op) {
153  return isAffineIfOp(op) && filter(op);
154  });
155 }
156 
158  return NestedPattern(child, isAffineForOp);
159 }
161  const NestedPattern &child) {
162  return NestedPattern(
163  child, [=](Operation &op) { return isAffineForOp(op) && filter(op); });
164 }
166  return NestedPattern(nested, isAffineForOp);
167 }
169  ArrayRef<NestedPattern> nested) {
170  return NestedPattern(
171  nested, [=](Operation &op) { return isAffineForOp(op) && filter(op); });
172 }
173 
175  return isa<AffineLoadOp, AffineStoreOp>(op);
176 }
177 
178 } // namespace matcher
179 } // namespace affine
180 } // namespace mlir
static bool isAffineForOp(Operation &op)
static bool isAffineIfOp(Operation &op)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
An NestedPattern captures nested patterns in the IR.
Definition: NestedMatcher.h:47
static NestedMatch build(Operation *operation, ArrayRef< NestedMatch > nestedMatches)
unsigned getDepth() const
Returns the depth of the pattern.
NestedPattern & operator=(const NestedPattern &other)
NestedPattern(ArrayRef< NestedPattern > nested, FilterFunctionType filter=defaultFilterFunction)
NestedPattern If(const NestedPattern &child)
NestedPattern For(const NestedPattern &child)
bool isLoadOrStore(Operation &op)
NestedPattern Op(FilterFunctionType filter=defaultFilterFunction)
std::function< bool(Operation &)> FilterFunctionType
A NestedPattern is a nested operation walker that:
Definition: NestedMatcher.h:91
Include the generated interface declarations.