//===- CheckUses.cpp - Expensive transform value validity checks ----------===// // // 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 // //===----------------------------------------------------------------------===// // // This file defines a pass that performs expensive opt-in checks for Transform // dialect values being potentially used after they have been consumed. // //===----------------------------------------------------------------------===// #include "mlir/Dialect/Transform/Transforms/Passes.h" #include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Pass/Pass.h" #include "llvm/ADT/SetOperations.h" namespace mlir { namespace transform { #define GEN_PASS_DEF_CHECKUSESPASS #include "mlir/Dialect/Transform/Transforms/Passes.h.inc" } // namespace transform } // namespace mlir usingnamespacemlir; namespace { /// Returns a reference to a cached set of blocks that are reachable from the /// given block via edges computed by the `getNextNodes` function. For example, /// if `getNextNodes` returns successors of a block, this will return the set of /// reachable blocks; if it returns predecessors of a block, this will return /// the set of blocks from which the given block can be reached. The block is /// considered reachable form itself only if there is a cycle. template <typename FnTy> const llvm::SmallPtrSet<Block *, 4> & getReachableImpl(Block *block, FnTy getNextNodes, DenseMap<Block *, llvm::SmallPtrSet<Block *, 4>> &cache) { … } /// An analysis that identifies whether a value allocated by a Transform op may /// be used by another such op after it may have been freed by a third op on /// some control flow path. This is conceptually similar to a data flow /// analysis, but relies on side effects related to particular values that /// currently cannot be modeled by the MLIR data flow analysis framework (also, /// the lattice element would be rather expensive as it would need to include /// live and/or freed values for each operation). /// /// This analysis is conservatively pessimisic: it will consider that a value /// may be freed if it is freed on any possible control flow path between its /// allocation and a relevant use, even if the control never actually flows /// through the operation that frees the value. It also does not differentiate /// between may- (freed on at least one control flow path) and must-free (freed /// on all possible control flow paths) because it would require expensive graph /// algorithms. /// /// It is intended as an additional non-blocking verification or debugging aid /// for ops in the Transform dialect. It leverages the requirement for Transform /// dialect ops to implement the MemoryEffectsOpInterface, and expects the /// values in the Transform IR to have an allocation effect on the /// TransformMappingResource when defined. class TransformOpMemFreeAnalysis { … }; //// A simple pass that warns about any use of a value by a transform operation // that may be using the value after it has been freed. class CheckUsesPass : public transform::impl::CheckUsesPassBase<CheckUsesPass> { … }; } // namespace