//===- RegionUtils.h - Region-related transformation utilities --*- 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_TRANSFORMS_REGIONUTILS_H_ #define MLIR_TRANSFORMS_REGIONUTILS_H_ #include "mlir/IR/Region.h" #include "mlir/IR/Value.h" #include "mlir/IR/ValueRange.h" #include "llvm/ADT/SetVector.h" namespace mlir { class DominanceInfo; class RewriterBase; /// Check if all values in the provided range are defined above the `limit` /// region. That is, if they are defined in a region that is a proper ancestor /// of `limit`. template bool areValuesDefinedAbove(Range values, Region &limit) { for (Value v : values) if (!v.getParentRegion()->isProperAncestor(&limit)) return false; return true; } /// Replace all uses of `orig` within the given region with `replacement`. void replaceAllUsesInRegionWith(Value orig, Value replacement, Region ®ion); /// Calls `callback` for each use of a value within `region` or its descendants /// that was defined at the ancestors of the `limit`. void visitUsedValuesDefinedAbove(Region ®ion, Region &limit, function_ref callback); /// Calls `callback` for each use of a value within any of the regions provided /// that was defined in one of the ancestors. void visitUsedValuesDefinedAbove(MutableArrayRef regions, function_ref callback); /// Fill `values` with a list of values defined at the ancestors of the `limit` /// region and used within `region` or its descendants. void getUsedValuesDefinedAbove(Region ®ion, Region &limit, SetVector &values); /// Fill `values` with a list of values used within any of the regions provided /// but defined in one of the ancestors. void getUsedValuesDefinedAbove(MutableArrayRef regions, SetVector &values); /// Make a region isolated from above /// - Capture the values that are defined above the region and used within it. /// - Append to the entry block arguments that represent the captured values /// (one per captured value). /// - Replace all uses within the region of the captured values with the /// newly added arguments. /// - `cloneOperationIntoRegion` is a callback that allows caller to specify /// if the operation defining an `OpOperand` needs to be cloned into the /// region. Then the operands of this operation become part of the captured /// values set (unless the operations that define the operands themeselves /// are to be cloned). The cloned operations are added to the entry block /// of the region. /// Return the set of captured values for the operation. SmallVector makeRegionIsolatedFromAbove( RewriterBase &rewriter, Region ®ion, llvm::function_ref cloneOperationIntoRegion = [](Operation *) { return false; }); /// Move the operation dependencies (producers) of `op` before `insertionPoint`, /// so that `op` itself can subsequently be moved. This includes transitive /// dependencies. Supports movement within the same block or from nested regions /// to an outer block. /// /// The following conditions cause the move to fail: /// - `insertionPoint` does not dominate `op`. /// - Movement across an isolated-from-above region boundary. /// - A dependency uses a block argument that wouldn't dominate /// `insertionPoint`. /// - `insertionPoint` is itself a dependency of `op` (cycle). /// - Any side-effecting operations in the dependency chain pessimistically /// blocks movement. LogicalResult moveOperationDependencies(RewriterBase &rewriter, Operation *op, Operation *insertionPoint, DominanceInfo &dominance); LogicalResult moveOperationDependencies(RewriterBase &rewriter, Operation *op, Operation *insertionPoint); /// Move definitions of `values` (and their transitive dependencies) before /// `insertionPoint`. Supports movement within the same block or from nested /// regions to an outer block. /// /// This is all-or-nothing: either all definitions are moved, or none are. /// /// The following conditions cause the move to fail: /// - Any value is a block argument (cannot be moved). /// - Any side-effecting operations in the dependency chain. /// - Movement across an isolated-from-above region boundary. /// - A dependency uses a block argument that wouldn't dominate /// `insertionPoint`. /// - `insertionPoint` is itself a dependency (cycle). LogicalResult moveValueDefinitions(RewriterBase &rewriter, ValueRange values, Operation *insertionPoint, DominanceInfo &dominance); LogicalResult moveValueDefinitions(RewriterBase &rewriter, ValueRange values, Operation *insertionPoint); /// Remove trivially dead operations from \p region. An operation is trivially /// dead when it has no users and is side-effect-free. Operand-defining ops are /// re-evaluated after each erasure, so chains of dead ops are eliminated in a /// single pass. When \p includeNestedRegions is true (the default), the pass /// descends into nested regions bottom-up before simplifying \p region itself; /// when false, only ops directly in \p region are considered. Returns true if /// any op was removed. bool eliminateTriviallyDeadOps(RewriterBase &rewriter, Region ®ion, bool includeNestedRegions = true); /// Run a set of structural simplifications over the given regions. This /// includes transformations like unreachable block elimination, dead argument /// elimination, as well as some other DCE. This function returns success if any /// of the regions were simplified, failure otherwise. The provided rewriter is /// used to notify callers of operation and block deletion. /// Structurally similar blocks will be merged if the `mergeBlock` argument is /// true. Note this can lead to merged blocks with extra arguments. LogicalResult simplifyRegions(RewriterBase &rewriter, MutableArrayRef regions, bool mergeBlocks = true); /// Erase the unreachable blocks within the provided regions. If \p recurse is /// true, also visit regions nested under live operations. Returns success if /// any blocks were erased, failure otherwise. LogicalResult eraseUnreachableBlocks(RewriterBase &rewriter, MutableArrayRef regions, bool recurse = true); /// This function returns success if any operations or arguments were deleted, /// failure otherwise. LogicalResult runRegionDCE(RewriterBase &rewriter, MutableArrayRef regions); } // namespace mlir #endif // MLIR_TRANSFORMS_REGIONUTILS_H_