blob: 2af05c3b6fc8e9ac0d6ad166044ba591f17f1cc2 [file]
// 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 &registry) 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