//===- NormalizeMemRefs.cpp -----------------------------------------------===// // // 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 implements an interprocedural pass to normalize memrefs to have // identity layout maps. // //===----------------------------------------------------------------------===// #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Affine/Utils.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/MemRef/Transforms/Passes.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Debug.h" namespace mlir { namespace memref { #define GEN_PASS_DEF_NORMALIZEMEMREFS #include "mlir/Dialect/MemRef/Transforms/Passes.h.inc" } // namespace memref } // namespace mlir #define DEBUG_TYPE … usingnamespacemlir; usingnamespacemlir::affine; namespace { /// All memrefs passed across functions with non-trivial layout maps are /// converted to ones with trivial identity layout ones. /// If all the memref types/uses in a function are normalizable, we treat /// such functions as normalizable. Also, if a normalizable function is known /// to call a non-normalizable function, we treat that function as /// non-normalizable as well. We assume external functions to be normalizable. struct NormalizeMemRefs : public memref::impl::NormalizeMemRefsBase<NormalizeMemRefs> { … }; } // namespace std::unique_ptr<OperationPass<ModuleOp>> mlir::memref::createNormalizeMemRefsPass() { … } void NormalizeMemRefs::runOnOperation() { … } /// Check whether all the uses of oldMemRef are either dereferencing uses or the /// op is of type : DeallocOp, CallOp or ReturnOp. Only if these constraints /// are satisfied will the value become a candidate for replacement. /// TODO: Extend this for DimOps. static bool isMemRefNormalizable(Value::user_range opUsers) { … } /// Set all the calling functions and the callees of the function as not /// normalizable. void NormalizeMemRefs::setCalleesAndCallersNonNormalizable( func::FuncOp funcOp, ModuleOp moduleOp, DenseSet<func::FuncOp> &normalizableFuncs) { … } /// Check whether all the uses of AllocOps, CallOps and function arguments of a /// function are either of dereferencing type or are uses in: DeallocOp, CallOp /// or ReturnOp. Only if these constraints are satisfied will the function /// become a candidate for normalization. When the uses of a memref are /// non-normalizable and the memref map layout is trivial (identity), we can /// still label the entire function as normalizable. We assume external /// functions to be normalizable. bool NormalizeMemRefs::areMemRefsNormalizable(func::FuncOp funcOp) { … } /// Fetch the updated argument list and result of the function and update the /// function signature. This updates the function's return type at the caller /// site and in case the return type is a normalized memref then it updates /// the calling function's signature. /// TODO: An update to the calling function signature is required only if the /// returned value is in turn used in ReturnOp of the calling function. void NormalizeMemRefs::updateFunctionSignature(func::FuncOp funcOp, ModuleOp moduleOp) { … } /// Normalizes the memrefs within a function which includes those arising as a /// result of AllocOps, CallOps and function's argument. The ModuleOp argument /// is used to help update function's signature after normalization. void NormalizeMemRefs::normalizeFuncOpMemRefs(func::FuncOp funcOp, ModuleOp moduleOp) { … } /// Create an operation containing normalized memrefs in the operation results. /// When the results of `oldOp` have memrefs with affine map, the memrefs are /// normalized, and new operation containing them in the operation results is /// returned. If all of the results of `oldOp` have no memrefs or memrefs /// without affine map, `oldOp` is returned without modification. Operation *NormalizeMemRefs::createOpResultsNormalized(func::FuncOp funcOp, Operation *oldOp) { … }