github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Analysis/NestedMatcher.cpp (about)

     1  //===- NestedMatcher.cpp - NestedMatcher Impl  ----------------------------===//
     2  //
     3  // Copyright 2019 The MLIR Authors.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //   http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  // =============================================================================
    17  
    18  #include "mlir/Analysis/NestedMatcher.h"
    19  #include "mlir/Dialect/AffineOps/AffineOps.h"
    20  #include "mlir/Dialect/StandardOps/Ops.h"
    21  
    22  #include "llvm/ADT/ArrayRef.h"
    23  #include "llvm/ADT/STLExtras.h"
    24  #include "llvm/Support/Allocator.h"
    25  #include "llvm/Support/raw_ostream.h"
    26  
    27  using namespace mlir;
    28  
    29  llvm::BumpPtrAllocator *&NestedMatch::allocator() {
    30    thread_local llvm::BumpPtrAllocator *allocator = nullptr;
    31    return allocator;
    32  }
    33  
    34  NestedMatch NestedMatch::build(Operation *operation,
    35                                 ArrayRef<NestedMatch> nestedMatches) {
    36    auto *result = allocator()->Allocate<NestedMatch>();
    37    auto *children = allocator()->Allocate<NestedMatch>(nestedMatches.size());
    38    std::uninitialized_copy(nestedMatches.begin(), nestedMatches.end(), children);
    39    new (result) NestedMatch();
    40    result->matchedOperation = operation;
    41    result->matchedChildren =
    42        ArrayRef<NestedMatch>(children, nestedMatches.size());
    43    return *result;
    44  }
    45  
    46  llvm::BumpPtrAllocator *&NestedPattern::allocator() {
    47    thread_local llvm::BumpPtrAllocator *allocator = nullptr;
    48    return allocator;
    49  }
    50  
    51  NestedPattern::NestedPattern(ArrayRef<NestedPattern> nested,
    52                               FilterFunctionType filter)
    53      : nestedPatterns(), filter(filter), skip(nullptr) {
    54    if (!nested.empty()) {
    55      auto *newNested = allocator()->Allocate<NestedPattern>(nested.size());
    56      std::uninitialized_copy(nested.begin(), nested.end(), newNested);
    57      nestedPatterns = ArrayRef<NestedPattern>(newNested, nested.size());
    58    }
    59  }
    60  
    61  unsigned NestedPattern::getDepth() const {
    62    if (nestedPatterns.empty()) {
    63      return 1;
    64    }
    65    unsigned depth = 0;
    66    for (auto &c : nestedPatterns) {
    67      depth = std::max(depth, c.getDepth());
    68    }
    69    return depth + 1;
    70  }
    71  
    72  /// Matches a single operation in the following way:
    73  ///   1. checks the kind of operation against the matcher, if different then
    74  ///      there is no match;
    75  ///   2. calls the customizable filter function to refine the single operation
    76  ///      match with extra semantic constraints;
    77  ///   3. if all is good, recursivey matches the nested patterns;
    78  ///   4. if all nested match then the single operation matches too and is
    79  ///      appended to the list of matches;
    80  ///   5. TODO(ntv) Optionally applies actions (lambda), in which case we will
    81  ///      want to traverse in post-order DFS to avoid invalidating iterators.
    82  void NestedPattern::matchOne(Operation *op,
    83                               SmallVectorImpl<NestedMatch> *matches) {
    84    if (skip == op) {
    85      return;
    86    }
    87    // Local custom filter function
    88    if (!filter(*op)) {
    89      return;
    90    }
    91  
    92    if (nestedPatterns.empty()) {
    93      SmallVector<NestedMatch, 8> nestedMatches;
    94      matches->push_back(NestedMatch::build(op, nestedMatches));
    95      return;
    96    }
    97    // Take a copy of each nested pattern so we can match it.
    98    for (auto nestedPattern : nestedPatterns) {
    99      SmallVector<NestedMatch, 8> nestedMatches;
   100      // Skip elem in the walk immediately following. Without this we would
   101      // essentially need to reimplement walk here.
   102      nestedPattern.skip = op;
   103      nestedPattern.match(op, &nestedMatches);
   104      // If we could not match even one of the specified nestedPattern, early exit
   105      // as this whole branch is not a match.
   106      if (nestedMatches.empty()) {
   107        return;
   108      }
   109      matches->push_back(NestedMatch::build(op, nestedMatches));
   110    }
   111  }
   112  
   113  static bool isAffineForOp(Operation &op) { return isa<AffineForOp>(op); }
   114  
   115  static bool isAffineIfOp(Operation &op) { return isa<AffineIfOp>(op); }
   116  
   117  namespace mlir {
   118  namespace matcher {
   119  
   120  NestedPattern Op(FilterFunctionType filter) {
   121    return NestedPattern({}, filter);
   122  }
   123  
   124  NestedPattern If(NestedPattern child) {
   125    return NestedPattern(child, isAffineIfOp);
   126  }
   127  NestedPattern If(FilterFunctionType filter, NestedPattern child) {
   128    return NestedPattern(child, [filter](Operation &op) {
   129      return isAffineIfOp(op) && filter(op);
   130    });
   131  }
   132  NestedPattern If(ArrayRef<NestedPattern> nested) {
   133    return NestedPattern(nested, isAffineIfOp);
   134  }
   135  NestedPattern If(FilterFunctionType filter, ArrayRef<NestedPattern> nested) {
   136    return NestedPattern(nested, [filter](Operation &op) {
   137      return isAffineIfOp(op) && filter(op);
   138    });
   139  }
   140  
   141  NestedPattern For(NestedPattern child) {
   142    return NestedPattern(child, isAffineForOp);
   143  }
   144  NestedPattern For(FilterFunctionType filter, NestedPattern child) {
   145    return NestedPattern(
   146        child, [=](Operation &op) { return isAffineForOp(op) && filter(op); });
   147  }
   148  NestedPattern For(ArrayRef<NestedPattern> nested) {
   149    return NestedPattern(nested, isAffineForOp);
   150  }
   151  NestedPattern For(FilterFunctionType filter, ArrayRef<NestedPattern> nested) {
   152    return NestedPattern(
   153        nested, [=](Operation &op) { return isAffineForOp(op) && filter(op); });
   154  }
   155  
   156  bool isLoadOrStore(Operation &op) {
   157    return isa<AffineLoadOp>(op) || isa<AffineStoreOp>(op);
   158  }
   159  
   160  } // end namespace matcher
   161  } // end namespace mlir