[mlir][gpu] Add target attribute to GPU modules.
**For an explanation of these patches see D154153.** Commit message: Adds support for Target attributes in GPU modules. This change enables attaching an optional non empty array of GPU target attributes to the module. Depends on D154104 Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D154113
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
include "mlir/Dialect/DLTI/DLTIBase.td"
|
||||
include "mlir/Dialect/GPU/IR/GPUBase.td"
|
||||
include "mlir/Dialect/GPU/IR/CompilationAttrInterfaces.td"
|
||||
include "mlir/Dialect/GPU/IR/ParallelLoopMapperAttr.td"
|
||||
include "mlir/Dialect/GPU/TransformOps/GPUDeviceMappingAttr.td"
|
||||
include "mlir/IR/EnumAttr.td"
|
||||
@@ -998,10 +999,9 @@ def GPU_BarrierOp : GPU_Op<"barrier"> {
|
||||
}
|
||||
|
||||
def GPU_GPUModuleOp : GPU_Op<"module", [
|
||||
DataLayoutOpInterface, HasDefaultDLTIDataLayout, IsolatedFromAbove,
|
||||
SymbolTable, Symbol,
|
||||
SingleBlockImplicitTerminator<"ModuleEndOp">
|
||||
]> {
|
||||
DataLayoutOpInterface, HasDefaultDLTIDataLayout, IsolatedFromAbove,
|
||||
SymbolTable, Symbol, SingleBlockImplicitTerminator<"ModuleEndOp">
|
||||
]>, Arguments<(ins OptionalAttr<GPUNonEmptyTargetArrayAttr>:$targets)> {
|
||||
let summary = "A top level compilation unit containing code to be run on a GPU.";
|
||||
let description = [{
|
||||
GPU module contains code that is intended to be run on a GPU. A host device
|
||||
@@ -1018,22 +1018,41 @@ def GPU_GPUModuleOp : GPU_Op<"module", [
|
||||
allows filtering of code regions to execute passes on only code intended to
|
||||
or not intended to be run on the separate device.
|
||||
|
||||
Modules can contain zero or more target attributes. These attributes encode
|
||||
how to transform modules into binary strings and are used by the
|
||||
`gpu-module-to-binary` pass to transform modules into GPU binaries.
|
||||
|
||||
```
|
||||
gpu.module @symbol_name {
|
||||
gpu.module @symbol_name {
|
||||
gpu.func {}
|
||||
...
|
||||
gpu.module_end
|
||||
}
|
||||
gpu.module @symbol_name2 [#nvvm.target, #rocdl.target<chip = "gfx90a">] {
|
||||
gpu.func {}
|
||||
...
|
||||
gpu.module_end
|
||||
}
|
||||
|
||||
```
|
||||
}];
|
||||
let builders = [OpBuilder<(ins "StringRef":$name)>];
|
||||
let builders = [
|
||||
OpBuilder<(ins "StringRef":$name, CArg<"ArrayAttr", "{}">:$targets)>,
|
||||
OpBuilder<(ins "StringRef":$name, "ArrayRef<Attribute>":$targets)>
|
||||
];
|
||||
let regions = (region SizedRegion<1>:$bodyRegion);
|
||||
let hasCustomAssemblyFormat = 1;
|
||||
|
||||
// We need to ensure the block inside the region is properly terminated;
|
||||
// the auto-generated builders do not guarantee that.
|
||||
let skipDefaultBuilders = 1;
|
||||
|
||||
let extraClassDeclaration = [{
|
||||
/// Checks if `target` is in the `targets` list.
|
||||
bool hasTarget(Attribute target);
|
||||
|
||||
/// Sets the targets of the module.
|
||||
void setTargets(ArrayRef<TargetAttrInterface> targets);
|
||||
}];
|
||||
}
|
||||
|
||||
def GPU_ModuleEndOp : GPU_Op<"module_end", [
|
||||
|
||||
@@ -1508,18 +1508,41 @@ LogicalResult gpu::ReturnOp::verify() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void GPUModuleOp::build(OpBuilder &builder, OperationState &result,
|
||||
StringRef name) {
|
||||
StringRef name, ArrayAttr targets) {
|
||||
ensureTerminator(*result.addRegion(), builder, result.location);
|
||||
result.attributes.push_back(builder.getNamedAttr(
|
||||
::mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(name)));
|
||||
|
||||
if (targets)
|
||||
result.getOrAddProperties<Properties>().targets = targets;
|
||||
}
|
||||
|
||||
void GPUModuleOp::build(OpBuilder &builder, OperationState &result,
|
||||
StringRef name, ArrayRef<Attribute> targets) {
|
||||
build(builder, result, name,
|
||||
targets.size() > 0 ? builder.getArrayAttr(targets) : ArrayAttr());
|
||||
}
|
||||
|
||||
ParseResult GPUModuleOp::parse(OpAsmParser &parser, OperationState &result) {
|
||||
StringAttr nameAttr;
|
||||
ArrayAttr targetsAttr;
|
||||
|
||||
if (parser.parseSymbolName(nameAttr, mlir::SymbolTable::getSymbolAttrName(),
|
||||
result.attributes) ||
|
||||
// If module attributes are present, parse them.
|
||||
parser.parseOptionalAttrDictWithKeyword(result.attributes))
|
||||
result.attributes))
|
||||
return failure();
|
||||
|
||||
// Parse the optional array of target attributes.
|
||||
OptionalParseResult targetsAttrResult =
|
||||
parser.parseOptionalAttribute(targetsAttr, Type{});
|
||||
if (targetsAttrResult.has_value()) {
|
||||
if (failed(*targetsAttrResult)) {
|
||||
return failure();
|
||||
}
|
||||
result.getOrAddProperties<Properties>().targets = targetsAttr;
|
||||
}
|
||||
|
||||
// If module attributes are present, parse them.
|
||||
if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
|
||||
return failure();
|
||||
|
||||
// Parse the module body.
|
||||
@@ -1535,13 +1558,33 @@ ParseResult GPUModuleOp::parse(OpAsmParser &parser, OperationState &result) {
|
||||
void GPUModuleOp::print(OpAsmPrinter &p) {
|
||||
p << ' ';
|
||||
p.printSymbolName(getName());
|
||||
p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
|
||||
{mlir::SymbolTable::getSymbolAttrName()});
|
||||
|
||||
if (Attribute attr = getTargetsAttr()) {
|
||||
p << ' ';
|
||||
p.printAttribute(attr);
|
||||
p << ' ';
|
||||
}
|
||||
|
||||
p.printOptionalAttrDictWithKeyword(
|
||||
(*this)->getAttrs(),
|
||||
{mlir::SymbolTable::getSymbolAttrName(), getTargetsAttrName()});
|
||||
p << ' ';
|
||||
p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
|
||||
/*printBlockTerminators=*/false);
|
||||
}
|
||||
|
||||
bool GPUModuleOp::hasTarget(Attribute target) {
|
||||
if (ArrayAttr targets = getTargetsAttr())
|
||||
return llvm::count(targets.getValue(), target);
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPUModuleOp::setTargets(ArrayRef<TargetAttrInterface> targets) {
|
||||
ArrayAttr &targetsAttr = getProperties().targets;
|
||||
SmallVector<Attribute> targetsVector(targets);
|
||||
targetsAttr = ArrayAttr::get(getContext(), targetsVector);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GPUMemcpyOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -610,3 +610,19 @@ module attributes {gpu.container_module} {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
module {
|
||||
// expected-error @+1 {{'gpu.module' op attribute 'targets' failed to satisfy constraint: array of GPU target attributes with at least 1 elements}}
|
||||
gpu.module @gpu_funcs [] {
|
||||
}
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
module {
|
||||
// expected-error @+1 {{'gpu.module' op attribute 'targets' failed to satisfy constraint: array of GPU target attributes with at least 1 elements}}
|
||||
gpu.module @gpu_funcs [1] {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user