//===- NestedMacher.h - Nested matcher for Function -------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef MLIR_DIALECT_AFFINE_ANALYSIS_NESTEDMATCHER_H #define MLIR_DIALECT_AFFINE_ANALYSIS_NESTEDMATCHER_H #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Operation.h" #include "llvm/Support/Allocator.h" namespace mlir { class Operation; namespace affine { class NestedPattern; /// An NestedPattern captures nested patterns in the IR. /// It is used in conjunction with a scoped NestedPatternContext which is an /// llvm::BumpPtrAllocator that handles memory allocations efficiently and /// avoids ownership issues. /// /// In order to use NestedPatterns, first create a scoped context. /// When the context goes out of scope, everything is freed. /// This design simplifies the API by avoiding references to the context and /// makes it clear that references to matchers must not escape. /// /// Example: /// { /// NestedPatternContext context; /// auto gemmLike = Doall(Doall(Red(LoadStores()))); /// auto matches = gemmLike.match(f); /// // do work on matches /// } // everything is freed /// /// /// Nested abstraction for matching results. /// Provides access to the nested Operation* captured by a Matcher. /// /// A NestedMatch contains an Operation* and the children NestedMatch and is /// thus cheap to copy. NestedMatch is stored in a scoped bumper allocator whose /// lifetime is managed by an RAII NestedPatternContext. class NestedMatch { … }; /// A NestedPattern is a nested operation walker that: /// 1. recursively matches a substructure in the tree; /// 2. uses a filter function to refine matches with extra semantic /// constraints (passed via a lambda of type FilterFunctionType); /// 3. TODO: optionally applies actions (lambda). /// /// Nested patterns are meant to capture imperfectly nested loops while matching /// properties over the whole loop nest. For instance, in vectorization we are /// interested in capturing all the imperfectly nested loops of a certain type /// and such that all the load and stores have certain access patterns along the /// loops' induction variables). Such NestedMatches are first captured using the /// `match` function and are later processed to analyze properties and apply /// transformations in a non-greedy way. /// /// The NestedMatches captured in the IR can grow large, especially after /// aggressive unrolling. As experience has shown, it is generally better to use /// a plain walk over operations to match flat patterns but the current /// implementation is competitive nonetheless. FilterFunctionType; inline bool defaultFilterFunction(Operation &) { … } class NestedPattern { … }; /// RAII structure to transparently manage the bump allocator for /// NestedPattern and NestedMatch classes. This avoids passing a context to /// all the API functions. class NestedPatternContext { … }; namespace matcher { // Syntactic sugar NestedPattern builder functions. NestedPattern Op(FilterFunctionType filter = defaultFilterFunction); NestedPattern If(const NestedPattern &child); NestedPattern If(const FilterFunctionType &filter, const NestedPattern &child); NestedPattern If(ArrayRef<NestedPattern> nested = {}); NestedPattern If(const FilterFunctionType &filter, ArrayRef<NestedPattern> nested = {}); NestedPattern For(const NestedPattern &child); NestedPattern For(const FilterFunctionType &filter, const NestedPattern &child); NestedPattern For(ArrayRef<NestedPattern> nested = {}); NestedPattern For(const FilterFunctionType &filter, ArrayRef<NestedPattern> nested = {}); bool isParallelLoop(Operation &op); bool isReductionLoop(Operation &op); bool isLoadOrStore(Operation &op); } // namespace matcher } // namespace affine } // namespace mlir #endif // MLIR_DIALECT_AFFINE_ANALYSIS_NESTEDMATCHER_H