blob: ffe8055dbe53e0a503b9e41be4fd19ad00ce58de [file]
// Copyright 2023 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 <utility>
#include "iree/compiler/Dialect/VM/IR/VMDialect.h"
#include "iree/compiler/Dialect/VM/IR/VMOps.h"
#include "iree/compiler/Dialect/VM/IR/VMTypes.h"
#include "iree/compiler/Dialect/VM/Transforms/Passes.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/Pass/Pass.h"
namespace mlir::iree_compiler::IREE::VM {
// Replaces a vm.rodata.table.inline op with two vm.rodata.inline ops, one for
// the indexing table, and the second for the padded data.
template <typename IntTy>
static void reifyRodataTable(RewriterBase &rewriter,
IREE::VM::RodataTableInlineOp tableOp) {
SmallVector<IntTy> table;
SmallVector<Attribute> dataAttrs;
size_t dataSize = 0;
size_t dataAlignment =
tableOp.getDataAlignment() ? *tableOp.getDataAlignment() : 1;
for (auto value : tableOp.getDataArray().getValue()) {
auto serializableAttr =
llvm::cast<IREE::Util::SerializableAttrInterface>(value);
size_t storageSize = serializableAttr.getStorageSize();
dataAttrs.push_back(value);
// Pad to the (byte) data alignment.
size_t padding =
(dataAlignment - storageSize % dataAlignment) % dataAlignment;
if (padding) {
SmallVector<int8_t> zeros(padding, 0);
VectorType paddingType = VectorType::get({static_cast<int64_t>(padding)},
rewriter.getIntegerType(8));
dataAttrs.push_back(rewriter.getZeroAttr(paddingType));
}
// The running data size is the offset of the current value.
table.push_back(dataSize);
// The table specifies the (unpadded) storage size for this element.
table.push_back(storageSize);
// Increment the total storage size by the (padded) storage size.
dataSize += storageSize + padding;
}
auto refType =
IREE::VM::RefType::get(rewriter.getType<IREE::VM::BufferType>());
IREE::VM::RodataInlineOp tableRodata;
if constexpr (std::is_same<IntTy, int32_t>()) {
tableRodata = rewriter.create<IREE::VM::RodataInlineOp>(
tableOp.getLoc(), refType, rewriter.getI32VectorAttr(table));
} else {
tableRodata = rewriter.create<IREE::VM::RodataInlineOp>(
tableOp.getLoc(), refType, rewriter.getI64VectorAttr(table));
}
if (auto tableNameAttr = tableOp.getTableNameAttr()) {
tableRodata.setNameAttr(tableNameAttr);
}
auto dataRodata = rewriter.create<IREE::VM::RodataInlineOp>(
tableOp.getLoc(), refType,
IREE::Util::CompositeAttr::get(rewriter.getContext(), dataAttrs));
if (auto dataNameAttr = tableOp.getDataNameAttr()) {
dataRodata.setNameAttr(dataNameAttr);
}
if (auto alignmentAttr = tableOp.getAlignmentAttr()) {
tableRodata.setAlignmentAttr(alignmentAttr);
dataRodata.setAlignmentAttr(alignmentAttr);
}
if (auto mimeTypeAttr = tableOp.getMimeTypeAttr()) {
tableRodata.setMimeTypeAttr(mimeTypeAttr);
dataRodata.setMimeTypeAttr(mimeTypeAttr);
}
rewriter.replaceOp(tableOp, {tableRodata, dataRodata});
}
class ReifyRodataTablesPass
: public PassWrapper<ReifyRodataTablesPass,
OperationPass<IREE::VM::ModuleOp>> {
public:
void getDependentDialects(DialectRegistry &registry) const override {
registry.insert<IREE::VM::VMDialect>();
}
StringRef getArgument() const override {
return "iree-vm-reify-rodata-tables";
}
StringRef getDescription() const override {
return "Converts vm.rodata.table.inline into two rodata, one for the flat "
"data and"
"the other for a newly constructed table for the element subviews.";
}
void runOnOperation() override {
auto moduleOp = getOperation();
// Walk all of the rodata table ops and convert to rodata.inline
IRRewriter rewriter(moduleOp.getContext());
moduleOp.walk([&](IREE::VM::RodataTableInlineOp tableOp) {
rewriter.setInsertionPoint(tableOp);
size_t tableBitwidth = tableOp.getTableType().getIntOrFloatBitWidth();
if (tableBitwidth == 32) {
reifyRodataTable<int32_t>(rewriter, tableOp);
} else if (tableBitwidth == 64) {
reifyRodataTable<int64_t>(rewriter, tableOp);
} else {
llvm_unreachable("Invalid table bit width");
}
});
}
};
std::unique_ptr<OperationPass<IREE::VM::ModuleOp>>
createReifyRodataTablesPass() {
return std::make_unique<ReifyRodataTablesPass>();
}
static PassRegistration<ReifyRodataTablesPass> pass;
} // namespace mlir::iree_compiler::IREE::VM