blob: 339e80d8c2b93243ee1c4d78d4c6d2492f63b36f [file] [log] [blame] [edit]
// 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 "iree/compiler/Dialect/Util/IR/UtilOps.h"
#include "iree/compiler/Dialect/Util/IR/UtilTypes.h"
#include "iree/compiler/Dialect/VM/Conversion/TypeConverter.h"
#include "iree/compiler/Dialect/VM/IR/VMOps.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Transforms/DialectConversion.h"
namespace mlir::iree_compiler {
namespace {
//===----------------------------------------------------------------------===//
// util.align
//===----------------------------------------------------------------------===//
template <typename CONST_OP, typename SUB_OP, typename ADD_OP, typename NOT_OP,
typename AND_OP>
void insertAlignOps(IREE::Util::AlignOp srcOp,
ConversionPatternRewriter &rewriter,
IREE::Util::AlignOpAdaptor adaptor,
IntegerType integerType) {
// Aligns |value| up to the given power-of-two |alignment| if required.
// (value + (alignment - 1)) & ~(alignment - 1)
// https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding
auto oneConstant = rewriter.createOrFold<CONST_OP>(srcOp.getLoc(), 1);
// (alignment - 1)
auto alignmentValue = rewriter.createOrFold<SUB_OP>(
srcOp.getLoc(), integerType, adaptor.getAlignment(), oneConstant);
// value + (alignment - 1)
auto valueAddedValue = rewriter.createOrFold<ADD_OP>(
srcOp.getLoc(), integerType, adaptor.getValue(), alignmentValue);
// ~(alignment - 1)
auto notAlignmentValue = rewriter.createOrFold<NOT_OP>(
srcOp.getLoc(), integerType, alignmentValue);
// (value + (alignment - 1)) & ~(alignment - 1)
auto andValue = rewriter.createOrFold<AND_OP>(
srcOp.getLoc(), integerType, valueAddedValue, notAlignmentValue);
rewriter.replaceOp(srcOp, andValue);
}
struct AlignOpConversion : public OpConversionPattern<IREE::Util::AlignOp> {
using Base::Base;
LogicalResult
matchAndRewrite(IREE::Util::AlignOp srcOp, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Type valueType = adaptor.getValue().getType();
if (valueType.isInteger(32)) {
insertAlignOps<IREE::VM::ConstI32Op, IREE::VM::SubI32Op,
IREE::VM::AddI32Op, IREE::VM::NotI32Op,
IREE::VM::AndI32Op>(srcOp, rewriter, adaptor,
rewriter.getI32Type());
} else if (valueType.isInteger(64)) {
insertAlignOps<IREE::VM::ConstI64Op, IREE::VM::SubI64Op,
IREE::VM::AddI64Op, IREE::VM::NotI64Op,
IREE::VM::AndI64Op>(srcOp, rewriter, adaptor,
rewriter.getI64Type());
} else {
return srcOp.emitError()
<< "unsupported value type for util.align: " << valueType;
}
return success();
}
};
//===----------------------------------------------------------------------===//
// util.sizeof
//===----------------------------------------------------------------------===//
/// For a `sizeof index` operation, invokes the type converter to derive the
/// concrete type for index and rewrites to that. This allows us to do late
/// resolution of the size of the index type at the point of conversion to VM
/// where it is known.
struct FixateIndexSizeofConversion
: public OpConversionPattern<IREE::Util::SizeOfOp> {
using Base::Base;
LogicalResult
matchAndRewrite(IREE::Util::SizeOfOp sizeofOp, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Type sizedType = sizeofOp.getSizedType();
if (isa<IndexType>(sizedType)) {
Type converted = getTypeConverter()->convertType(sizedType);
if (converted) {
Value newSizeof = rewriter.createOrFold<IREE::Util::SizeOfOp>(
sizeofOp.getLoc(), converted);
rewriter.replaceOp(sizeofOp, newSizeof);
return success();
}
}
return failure();
}
};
} // namespace
void populateUtilAlignmentToVMPatterns(MLIRContext *context,
ConversionTarget &conversionTarget,
TypeConverter &typeConverter,
RewritePatternSet &patterns) {
conversionTarget.addIllegalOp<IREE::Util::AlignOp>();
conversionTarget.addIllegalOp<IREE::Util::SizeOfOp>();
patterns.insert<AlignOpConversion, FixateIndexSizeofConversion>(typeConverter,
context);
}
} // namespace mlir::iree_compiler