| // 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/Conversion/TypeConverter.h" |
| |
| #include "iree/compiler/Dialect/HAL/IR/HALOps.h" |
| #include "iree/compiler/Dialect/HAL/IR/HALTypes.h" |
| #include "iree/compiler/Dialect/Util/IR/UtilTypes.h" |
| |
| namespace mlir::iree_compiler { |
| |
| HALTypeConverter::HALTypeConverter( |
| ArrayRef<const HALConversionDialectInterface *> conversionInterfaces) |
| : conversionInterfaces(conversionInterfaces.vec()) { |
| // Custom conversion interfaces for external dialects. |
| addConversion([this](Type type, SmallVectorImpl<Type> &results) { |
| for (auto *conversionInterface : this->conversionInterfaces) { |
| if (succeeded(conversionInterface->convertType(type, results))) { |
| return success(); |
| } |
| } |
| results.push_back(type); |
| return success(); |
| }); |
| |
| // Tensors become buffers by default. |
| // Shapes and types are carried independently or folded away entirely - all |
| // we need at the HAL level is a blob of bytes. |
| addConversion([=](TensorType type) -> std::optional<Type> { |
| // HAL only should be concerned with numeric values. |
| if (HALTypeConverter::shouldConvertToBufferView(type)) { |
| return IREE::HAL::BufferViewType::get(type.getContext()); |
| } |
| return std::nullopt; |
| }); |
| |
| addTargetMaterialization([](OpBuilder &builder, IREE::HAL::BufferType type, |
| ValueRange inputs, Location loc) -> Value { |
| assert(inputs.size() == 1); |
| if (llvm::isa<TensorType>(inputs[0].getType())) { |
| return builder.create<IREE::HAL::TensorExportOp>(loc, type, inputs[0]); |
| } else if (llvm::isa<IREE::HAL::BufferViewType>(inputs[0].getType())) { |
| return builder.create<IREE::HAL::BufferViewBufferOp>(loc, type, |
| inputs[0]); |
| } else { |
| emitError(loc) << "unsupported HAL target materialization: " |
| << inputs[0].getType(); |
| return nullptr; |
| } |
| }); |
| addTargetMaterialization([](OpBuilder &builder, |
| IREE::HAL::BufferViewType type, ValueRange inputs, |
| Location loc) -> Value { |
| assert(inputs.size() == 1); |
| auto inputValue = inputs[0]; |
| auto inputType = inputValue.getType(); |
| if (llvm::isa<TensorType>(inputType)) { |
| return builder.create<IREE::HAL::TensorExportOp>(loc, type, inputValue); |
| } else if (llvm::isa<IREE::HAL::BufferType>(inputType)) { |
| // Look for the buffer view this buffer came from, if any. |
| // If we don't have the origin buffer view then we can't know the shape |
| // and can't materialize one here - it's too late. |
| if (auto bvbOp = dyn_cast_or_null<IREE::HAL::BufferViewBufferOp>( |
| inputValue.getDefiningOp())) { |
| return bvbOp.getBufferView(); |
| } |
| return nullptr; |
| } else { |
| return nullptr; |
| } |
| }); |
| |
| // Recursively handle pointer target types (we want to convert |
| // ptr<tensor<...>> to ptr<!hal.buffer<...>>, for example). |
| addConversion([this](IREE::Util::PtrType type) -> Type { |
| auto targetType = convertType(type.getTargetType()); |
| if (!targetType) { |
| return Type(); |
| } |
| return IREE::Util::PtrType::get(targetType); |
| }); |
| } |
| |
| } // namespace mlir::iree_compiler |