MLIR 23.0.0git
ROCDLDialect.cpp
Go to the documentation of this file.
1//===- ROCDLDialect.cpp - ROCDL IR Ops and Dialect registration -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the types and operation details for the ROCDL IR dialect in
10// MLIR, and the LLVM IR dialect. It also registers the dialect.
11//
12// The ROCDL dialect only contains GPU specific additions on top of the general
13// LLVM dialect.
14//
15//===----------------------------------------------------------------------===//
16
18
21#include "mlir/IR/Builders.h"
24#include "mlir/IR/MLIRContext.h"
25#include "mlir/IR/Operation.h"
27#include "llvm/ADT/TypeSwitch.h"
28
29using namespace mlir;
30using namespace ROCDL;
31
32#include "mlir/Dialect/LLVMIR/ROCDLOpsDialect.cpp.inc"
33
34//===----------------------------------------------------------------------===//
35// Parsing for ROCDL ops
36//===----------------------------------------------------------------------===//
37
38// <operation> ::=
39// `llvm.amdgcn.raw.buffer.load.* %rsrc, %offset, %soffset, %aux
40// : result_type`
41ParseResult RawBufferLoadOp::parse(OpAsmParser &parser,
44 Type type;
45 if (parser.parseOperandList(ops, 4) || parser.parseColonType(type) ||
46 parser.addTypeToList(type, result.types))
47 return failure();
48
49 auto bldr = parser.getBuilder();
50 auto int32Ty = bldr.getI32Type();
51 auto i32x4Ty = VectorType::get({4}, int32Ty);
52 return parser.resolveOperands(ops, {i32x4Ty, int32Ty, int32Ty, int32Ty},
53 parser.getNameLoc(), result.operands);
54}
55
56void RawBufferLoadOp::print(OpAsmPrinter &p) {
57 p << " " << getOperands() << " : " << getRes().getType();
58}
59
60// <operation> ::=
61// `llvm.amdgcn.raw.buffer.store.* %vdata, %rsrc, %offset,
62// %soffset, %aux : result_type`
63ParseResult RawBufferStoreOp::parse(OpAsmParser &parser,
66 Type type;
67 if (parser.parseOperandList(ops, 5) || parser.parseColonType(type))
68 return failure();
69
70 auto bldr = parser.getBuilder();
71 auto int32Ty = bldr.getI32Type();
72 auto i32x4Ty = VectorType::get({4}, int32Ty);
73
74 if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
75 parser.getNameLoc(), result.operands))
76 return failure();
77 return success();
78}
79
80void RawBufferStoreOp::print(OpAsmPrinter &p) {
81 p << " " << getOperands() << " : " << getVdata().getType();
82}
83
84// <operation> ::=
85// `llvm.amdgcn.raw.buffer.atomic.fadd.* %vdata, %rsrc, %offset,
86// %soffset, %aux : result_type`
87ParseResult RawBufferAtomicFAddOp::parse(OpAsmParser &parser,
90 Type type;
91 if (parser.parseOperandList(ops, 5) || parser.parseColonType(type) ||
92 parser.addTypeToList(type, result.types))
93 return failure();
94
95 auto bldr = parser.getBuilder();
96 auto int32Ty = bldr.getI32Type();
97 auto i32x4Ty = VectorType::get({4}, int32Ty);
98
99 if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
100 parser.getNameLoc(), result.operands))
101 return failure();
102 return success();
103}
104
105void RawBufferAtomicFAddOp::print(mlir::OpAsmPrinter &p) {
106 p << " " << getOperands() << " : " << getVdata().getType();
107}
108
109// <operation> ::=
110// `llvm.amdgcn.raw.buffer.atomic.fmax.* %vdata, %rsrc, %offset,
111// %soffset, %aux : result_type`
112ParseResult RawBufferAtomicFMaxOp::parse(OpAsmParser &parser,
115 Type type;
116 if (parser.parseOperandList(ops, 5) || parser.parseColonType(type) ||
117 parser.addTypeToList(type, result.types))
118 return failure();
119
120 auto bldr = parser.getBuilder();
121 auto int32Ty = bldr.getI32Type();
122 auto i32x4Ty = VectorType::get({4}, int32Ty);
123
124 if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
125 parser.getNameLoc(), result.operands))
126 return failure();
127 return success();
128}
129
130void RawBufferAtomicFMaxOp::print(mlir::OpAsmPrinter &p) {
131 p << " " << getOperands() << " : " << getVdata().getType();
132}
133
134// <operation> ::=
135// `llvm.amdgcn.raw.buffer.atomic.smax.* %vdata, %rsrc, %offset,
136// %soffset, %aux : result_type`
137ParseResult RawBufferAtomicSMaxOp::parse(OpAsmParser &parser,
140 Type type;
141 if (parser.parseOperandList(ops, 5) || parser.parseColonType(type) ||
142 parser.addTypeToList(type, result.types))
143 return failure();
144
145 auto bldr = parser.getBuilder();
146 auto int32Ty = bldr.getI32Type();
147 auto i32x4Ty = VectorType::get({4}, int32Ty);
148
149 if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
150 parser.getNameLoc(), result.operands))
151 return failure();
152 return success();
153}
154
155void RawBufferAtomicSMaxOp::print(mlir::OpAsmPrinter &p) {
156 p << " " << getOperands() << " : " << getVdata().getType();
157}
158
159// <operation> ::=
160// `llvm.amdgcn.raw.buffer.atomic.umin.* %vdata, %rsrc, %offset,
161// %soffset, %aux : result_type`
162ParseResult RawBufferAtomicUMinOp::parse(OpAsmParser &parser,
165 Type type;
166 if (parser.parseOperandList(ops, 5) || parser.parseColonType(type) ||
167 parser.addTypeToList(type, result.types))
168 return failure();
169
170 auto bldr = parser.getBuilder();
171 auto int32Ty = bldr.getI32Type();
172 auto i32x4Ty = VectorType::get({4}, int32Ty);
173
174 if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
175 parser.getNameLoc(), result.operands))
176 return failure();
177 return success();
178}
179
180void RawBufferAtomicUMinOp::print(mlir::OpAsmPrinter &p) {
181 p << " " << getOperands() << " : " << getVdata().getType();
182}
183
184//===----------------------------------------------------------------------===//
185// ROCDLDialect initialization, type parsing, and registration.
186//===----------------------------------------------------------------------===//
187
188namespace {
189struct ROCDLInlinerInterface final : DialectInlinerInterface {
190 using DialectInlinerInterface::DialectInlinerInterface;
191 bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
192 return true;
193 }
194};
195} // namespace
196
197// TODO: This should be the llvm.rocdl dialect once this is supported.
198void ROCDLDialect::initialize() {
199 addOperations<
200#define GET_OP_LIST
201#include "mlir/Dialect/LLVMIR/ROCDLOps.cpp.inc"
202 >();
203
204 addAttributes<
205#define GET_ATTRDEF_LIST
206#include "mlir/Dialect/LLVMIR/ROCDLOpsAttributes.cpp.inc"
207 >();
208
209 // Support unknown operations because not all ROCDL operations are registered.
210 allowUnknownOperations();
211 addInterfaces<ROCDLInlinerInterface>();
212 declarePromisedInterface<gpu::TargetAttrInterface, ROCDLTargetAttr>();
213}
214
215LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op,
216 NamedAttribute attr) {
217 // Kernel function attribute should be attached to functions.
218 if (kernelAttrName.getName() == attr.getName()) {
219 if (!isa<LLVM::LLVMFuncOp>(op)) {
220 return op->emitError() << "'" << kernelAttrName.getName()
221 << "' attribute attached to unexpected op";
222 }
223 }
224 return success();
225}
226
227//===----------------------------------------------------------------------===//
228// ROCDL target attribute.
229//===----------------------------------------------------------------------===//
230LogicalResult
231ROCDLTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
232 int optLevel, StringRef triple, StringRef chip,
233 StringRef features, StringRef abiVersion,
234 DictionaryAttr flags, ArrayAttr files) {
235 if (optLevel < 0 || optLevel > 3) {
236 emitError() << "The optimization level must be a number between 0 and 3.";
237 return failure();
238 }
239 if (triple.empty()) {
240 emitError() << "The target triple cannot be empty.";
241 return failure();
242 }
243 if (chip.empty()) {
244 emitError() << "The target chip cannot be empty.";
245 return failure();
246 }
247 if (abiVersion != "400" && abiVersion != "500" && abiVersion != "600") {
248 emitError() << "Invalid ABI version, it must be `400`, `500` or '600'.";
249 return failure();
250 }
251 if (files && !llvm::all_of(files, [](::mlir::Attribute attr) {
252 return attr && mlir::isa<StringAttr>(attr);
253 })) {
254 emitError() << "All the elements in the `link` array must be strings.";
255 return failure();
256 }
257 return success();
258}
259
260#define GET_OP_CLASSES
261#include "mlir/Dialect/LLVMIR/ROCDLOps.cpp.inc"
262
263#define GET_ATTRDEF_CLASSES
264#include "mlir/Dialect/LLVMIR/ROCDLOpsAttributes.cpp.inc"
return success()
static bool isLegalToInline(InlinerInterface &interface, Region *src, Region *insertRegion, bool shouldCloneInlinedRegion, IRMapping &valueMapping)
Utility to check that all of the operations within 'src' can be inlined.
ArrayAttr()
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
IntegerType getI32Type()
Definition Builders.cpp:67
This class represents a diagnostic that is inflight and set to be reported.
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:147
This represents an operation in an abstracted form, suitable for use with the builder APIs.