| // Copyright 2021 The IREE Authors |
| // |
| // Licensed 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 |
| |
| #include <algorithm> |
| #include <iterator> |
| |
| #include "iree/compiler/Dialect/Util/IR/UtilDialect.h" |
| #include "iree/compiler/Dialect/Util/IR/UtilOps.h" |
| #include "iree/compiler/Dialect/Util/IR/UtilTraits.h" |
| #include "iree/compiler/Dialect/Util/Transforms/Passes.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/Support/Debug.h" |
| #include "mlir/IR/IRMapping.h" |
| #include "mlir/IR/Matchers.h" |
| #include "mlir/IR/PatternMatch.h" |
| #include "mlir/Pass/Pass.h" |
| #include "mlir/Pass/PassRegistry.h" |
| #include "mlir/Transforms/InliningUtils.h" |
| |
| #define DEBUG_TYPE "iree-util-combine-initializers" |
| |
| namespace mlir::iree_compiler::IREE::Util { |
| |
| #define GEN_PASS_DEF_COMBINEINITIALIZERSPASS |
| #include "iree/compiler/Dialect/Util/Transforms/Passes.h.inc" |
| |
| namespace { |
| |
| class CombineInitializersPass |
| : public impl::CombineInitializersPassBase<CombineInitializersPass> { |
| public: |
| void getDependentDialects(DialectRegistry ®istry) const override { |
| registry.insert<IREE::Util::UtilDialect>(); |
| } |
| |
| void runOnOperation() override { |
| auto moduleOp = getOperation(); |
| |
| // Gather all of the initializers in the module. |
| // Build a fused loc from all initializers we are combining. |
| SmallVector<IREE::Util::InitializerOp> initializerOps; |
| SmallVector<Location> locs; |
| for (auto initializerOp : moduleOp.getOps<IREE::Util::InitializerOp>()) { |
| initializerOps.push_back(initializerOp); |
| locs.push_back(initializerOp.getLoc()); |
| } |
| if (initializerOps.size() <= 1) |
| return; |
| auto fusedLoc = FusedLoc::get(&getContext(), locs); |
| |
| // Make the new initializer op in the same location as the first initializer |
| // we are combining - this ensures that module initialization order is |
| // preserved. |
| OpBuilder builder(initializerOps.front()); |
| auto newOp = builder.create<IREE::Util::InitializerOp>(fusedLoc); |
| builder.setInsertionPointToStart(newOp.addEntryBlock()); |
| InlinerInterface inlinerInterface(&getContext()); |
| for (auto initializerOp : initializerOps) { |
| if (failed(mlir::inlineRegion( |
| inlinerInterface, &initializerOp.getBody(), |
| builder.getInsertionBlock(), builder.getInsertionPoint(), |
| /*inlinedOperands=*/ValueRange{}, |
| /*resultsToReplace=*/ValueRange{}, /*inlineLoc=*/std::nullopt, |
| /*shouldCloneInlinedRegion=*/false))) { |
| initializerOp.emitOpError() |
| << "failed to inline into combined initializer"; |
| return signalPassFailure(); |
| } |
| builder.setInsertionPointToEnd(&newOp.back()); |
| initializerOp.erase(); |
| } |
| builder.create<IREE::Util::ReturnOp>(fusedLoc); |
| } |
| }; |
| |
| } // namespace |
| |
| } // namespace mlir::iree_compiler::IREE::Util |