blob: e28d08fb9a894a65e964f8a7d6880fd8c0109637 [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/HALDialect.h"
#include "iree/compiler/Dialect/HAL/Analysis/DeviceAnalysis.h"
#include "iree/compiler/Dialect/HAL/Conversion/HALToVM/Patterns.h"
#include "iree/compiler/Dialect/HAL/IR/HALOps.h"
#include "iree/compiler/Dialect/HAL/IR/HALTypes.h"
#include "iree/compiler/Dialect/HAL/hal.imports.h"
#include "iree/compiler/Dialect/Stream/IR/StreamInterfaces.h"
#include "iree/compiler/Dialect/Util/IR/UtilDialect.h"
#include "iree/compiler/Dialect/VM/Conversion/ConversionDialectInterface.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/LogicalResult.h"
#include "llvm/Support/SourceMgr.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlow.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/Parser/Parser.h"
#include "mlir/Transforms/InliningUtils.h"
namespace mlir::iree_compiler::IREE::HAL {
namespace {
// Used for custom printing support.
struct HALOpAsmInterface : public OpAsmDialectInterface {
using OpAsmDialectInterface::OpAsmDialectInterface;
/// Hooks for getting an alias identifier alias for a given symbol, that is
/// not necessarily a part of this dialect. The identifier is used in place of
/// the symbol when printing textual IR. These aliases must not contain `.` or
/// end with a numeric digit([0-9]+). Returns success if an alias was
/// provided, failure otherwise.
AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
if (auto targetAttr = llvm::dyn_cast<DeviceTargetAttr>(attr)) {
os << "device_target_" << targetAttr.getSymbolNameFragment();
return AliasResult::OverridableAlias;
} else if (auto targetAttr = llvm::dyn_cast<ExecutableTargetAttr>(attr)) {
os << "executable_target_" << targetAttr.getSymbolNameFragment();
return AliasResult::OverridableAlias;
} else if (auto layoutAttr = llvm::dyn_cast<PipelineLayoutAttr>(attr)) {
os << "pipeline_layout";
return AliasResult::OverridableAlias;
}
return AliasResult::NoAlias;
}
};
// Used to control inlining behavior.
struct HALInlinerInterface : public DialectInlinerInterface {
using DialectInlinerInterface::DialectInlinerInterface;
bool isLegalToInline(Operation *call, Operation *callable,
bool wouldBeCloned) const final {
// Sure!
return true;
}
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
IRMapping &valueMapping) const final {
// Sure!
return true;
}
bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
IRMapping &valueMapping) const final {
// Sure!
return true;
}
};
class HALToVMConversionInterface : public VMConversionDialectInterface {
public:
using VMConversionDialectInterface::VMConversionDialectInterface;
OwningOpRef<mlir::ModuleOp> parseVMImportModule() const override {
return mlir::parseSourceString<mlir::ModuleOp>(
StringRef(iree_hal_imports_create()->data,
iree_hal_imports_create()->size),
getDialect()->getContext());
}
void
populateVMConversionPatterns(SymbolTable &importSymbols,
RewritePatternSet &patterns,
ConversionTarget &conversionTarget,
TypeConverter &typeConverter) const override {
populateHALToVMPatterns(getDialect()->getContext(), importSymbols, patterns,
typeConverter);
}
LogicalResult walkAttributeStorage(
Attribute attr,
const function_ref<void(Attribute elementAttr)> &fn) const override {
MLIRContext *context = attr.getContext();
// TODO(benvanik): remove this interface or make it an attr interface.
if (auto bindingAttr =
llvm::dyn_cast<IREE::HAL::PipelineBindingAttr>(attr)) {
fn(IREE::HAL::DescriptorTypeAttr::get(context, bindingAttr.getType()));
fn(IREE::HAL::DescriptorFlagsAttr::get(context, bindingAttr.getFlags()));
return success();
}
if (auto dtAttr = llvm::dyn_cast<IREE::HAL::DescriptorTypeAttr>(attr)) {
// Repack as a normal integer attribute.
fn(IntegerAttr::get(IntegerType::get(context, 32),
APInt(32, static_cast<uint32_t>(dtAttr.getValue()))));
return success();
}
return failure();
}
};
class HALAffinityAnalysisDialectInterface
: public IREE::Stream::AffinityAnalysisDialectInterface {
public:
using AffinityAnalysisDialectInterface::AffinityAnalysisDialectInterface;
IREE::Stream::ResolveLayoutAttrFn
makeLayoutAttrResolver(ModuleOp moduleOp) const {
return [=](IREE::Stream::AffinityAttr affinityAttr, Operation *op,
SetVector<Attribute> &layoutAttrs) -> LogicalResult {
// This needs to be in the lambda because the moduleOp could be modified..
IREE::HAL::DeviceAnalysis deviceAnalysis(moduleOp);
if (failed(deviceAnalysis.run())) {
return op->emitError("failed to run DeviceAnalysis");
}
SetVector<IREE::HAL::ExecutableTargetAttr> resultSet;
deviceAnalysis.gatherRequiredExecutableTargets(affinityAttr, op,
resultSet);
// TODO(hanchung): Populate the EncodingLayoutAttr when it is ready.
layoutAttrs.insert(resultSet.begin(), resultSet.end());
return success();
};
};
};
} // namespace
HALDialect::HALDialect(MLIRContext *context)
: Dialect(getDialectNamespace(), context, TypeID::get<HALDialect>()) {
context->loadDialect<mlir::cf::ControlFlowDialect>();
context->loadDialect<mlir::scf::SCFDialect>();
context->loadDialect<IREE::Util::UtilDialect>();
registerAttributes();
registerTypes();
#define GET_OP_LIST
addOperations<
#include "iree/compiler/Dialect/HAL/IR/HALOps.cpp.inc"
>();
addInterfaces<HALInlinerInterface, HALOpAsmInterface,
HALAffinityAnalysisDialectInterface,
HALToVMConversionInterface>();
}
//===----------------------------------------------------------------------===//
// Dialect hooks
//===----------------------------------------------------------------------===//
Operation *HALDialect::materializeConstant(OpBuilder &builder, Attribute value,
Type type, Location loc) {
if (llvm::isa<IndexType>(type)) {
// Some folders materialize raw index types, which just become std
// constants.
return builder.create<mlir::arith::ConstantIndexOp>(
loc, llvm::cast<IntegerAttr>(value).getValue().getSExtValue());
}
return nullptr;
}
} // namespace mlir::iree_compiler::IREE::HAL