blob: 37a3002e982e2c78c02b5635c0650a1480090204 [file]
// Copyright 2019 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/HAL/IR/HALOps.h"
#include "iree/compiler/Dialect/VM/Conversion/ImportUtils.h"
#include "mlir/Transforms/DialectConversion.h"
namespace mlir {
namespace iree_compiler {
// Rewrites a hal.device.query of an i1 value to a hal.device.query of i32 with
// a truncation on the result.
class DeviceQueryIntCastOpConversion
: public OpConversionPattern<IREE::HAL::DeviceQueryOp> {
public:
DeviceQueryIntCastOpConversion(MLIRContext *context,
TypeConverter &typeConverter)
: OpConversionPattern(typeConverter, context) {}
LogicalResult matchAndRewrite(
IREE::HAL::DeviceQueryOp op, llvm::ArrayRef<Value> operands,
ConversionPatternRewriter &rewriter) const override {
// We only deal with in-dialect conversions to i32 in this pattern.
auto targetType = op.value().getType();
if (targetType.isInteger(32)) return failure();
if (!targetType.isIntOrIndex()) return failure();
// Query as I32.
// Note that due to type conversion we need to handle the default logic
// ourselves instead of allowing the i32 do the same. We could let it handle
// things but then we are generating more IR that may prevent other
// canonicalizations (a select of i1 to i1 is easier to handle).
IREE::HAL::DeviceQueryOp::Adaptor adaptor(operands);
auto queryOp = rewriter.create<IREE::HAL::DeviceQueryOp>(
op.getLoc(), rewriter.getI1Type(), rewriter.getI32Type(),
adaptor.device(), op.categoryAttr(), op.keyAttr(), Attribute{});
auto ok = queryOp.ok();
auto value = queryOp.value();
// Truncate or extend based on the target type.
if (targetType.isIndex()) {
// i32 -> index cast.
value = rewriter.createOrFold<arith::IndexCastOp>(op.getLoc(), targetType,
value);
} else if (targetType.isa<IntegerType>()) {
// i32 -> {integer} cast.
if (targetType.getIntOrFloatBitWidth() <
value.getType().getIntOrFloatBitWidth()) {
// i32 -> narrowing cast.
value = rewriter.createOrFold<arith::TruncIOp>(op.getLoc(), targetType,
value);
} else {
// i32 -> widening cast.
value = rewriter.createOrFold<arith::ExtUIOp>(op.getLoc(), targetType,
value);
}
}
if (op.default_value().hasValue()) {
// Select the default value based on the converted type as that's the type
// of the attribute we have is in. 'ok' result is set to true as we've
// already handled the error case.
value = rewriter.createOrFold<SelectOp>(
op.getLoc(), ok, value,
rewriter.createOrFold<arith::ConstantOp>(op.getLoc(),
op.default_valueAttr()));
ok = rewriter.createOrFold<IREE::VM::ConstI32Op>(op.getLoc(), 1);
}
rewriter.replaceOp(op, {ok, value});
return success();
}
};
class DeviceQueryI32OpConversion
: public OpConversionPattern<IREE::HAL::DeviceQueryOp> {
public:
DeviceQueryI32OpConversion(MLIRContext *context, SymbolTable &importSymbols,
TypeConverter &typeConverter, StringRef importName)
: OpConversionPattern(typeConverter, context) {
importOp = importSymbols.lookup<IREE::VM::ImportOp>(importName);
assert(importOp);
}
LogicalResult matchAndRewrite(
IREE::HAL::DeviceQueryOp op, llvm::ArrayRef<Value> operands,
ConversionPatternRewriter &rewriter) const override {
if (!op.value().getType().isInteger(32)) return failure();
IREE::HAL::DeviceQueryOp::Adaptor adaptor(operands);
auto results =
rewriteToCall(op, adaptor, importOp, *getTypeConverter(), rewriter);
if (!results.hasValue()) return failure();
auto ok = results->front();
auto value = results->back();
if (op.default_value().hasValue()) {
value = rewriter.createOrFold<SelectOp>(
op.getLoc(), ok, value,
rewriter.createOrFold<IREE::VM::ConstI32Op>(op.getLoc(),
op.default_valueAttr()));
ok = rewriter.createOrFold<IREE::VM::ConstI32Op>(op.getLoc(), 1);
}
rewriter.replaceOp(op, {ok, value});
return success();
}
private:
mutable IREE::VM::ImportOp importOp;
};
void populateHALDeviceToVMPatterns(MLIRContext *context,
SymbolTable &importSymbols,
TypeConverter &typeConverter,
OwningRewritePatternList &patterns) {
patterns.insert<VMImportOpConversion<IREE::HAL::DeviceAllocatorOp>>(
context, importSymbols, typeConverter, "hal.device.allocator");
patterns.insert<DeviceQueryIntCastOpConversion>(context, typeConverter);
patterns.insert<DeviceQueryI32OpConversion>(
context, importSymbols, typeConverter, "hal.device.query.i32");
}
} // namespace iree_compiler
} // namespace mlir