MLIR  22.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"
22 #include "mlir/IR/BuiltinTypes.h"
24 #include "mlir/IR/MLIRContext.h"
25 #include "mlir/IR/Operation.h"
27 #include "llvm/ADT/TypeSwitch.h"
28 
29 using namespace mlir;
30 using 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`
41 ParseResult RawBufferLoadOp::parse(OpAsmParser &parser,
42  OperationState &result) {
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 
57  p << " " << getOperands() << " : " << getRes().getType();
58 }
59 
60 // <operation> ::=
61 // `llvm.amdgcn.raw.buffer.store.* %vdata, %rsrc, %offset,
62 // %soffset, %aux : result_type`
63 ParseResult RawBufferStoreOp::parse(OpAsmParser &parser,
64  OperationState &result) {
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 
81  p << " " << getOperands() << " : " << getVdata().getType();
82 }
83 
84 // <operation> ::=
85 // `llvm.amdgcn.raw.buffer.atomic.fadd.* %vdata, %rsrc, %offset,
86 // %soffset, %aux : result_type`
87 ParseResult RawBufferAtomicFAddOp::parse(OpAsmParser &parser,
88  OperationState &result) {
90  Type type;
91  if (parser.parseOperandList(ops, 5) || parser.parseColonType(type))
92  return failure();
93 
94  auto bldr = parser.getBuilder();
95  auto int32Ty = bldr.getI32Type();
96  auto i32x4Ty = VectorType::get({4}, int32Ty);
97 
98  if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
99  parser.getNameLoc(), result.operands))
100  return failure();
101  return success();
102 }
103 
105  p << " " << getOperands() << " : " << getVdata().getType();
106 }
107 
108 // <operation> ::=
109 // `llvm.amdgcn.raw.buffer.atomic.fmax.* %vdata, %rsrc, %offset,
110 // %soffset, %aux : result_type`
111 ParseResult RawBufferAtomicFMaxOp::parse(OpAsmParser &parser,
112  OperationState &result) {
114  Type type;
115  if (parser.parseOperandList(ops, 5) || parser.parseColonType(type))
116  return failure();
117 
118  auto bldr = parser.getBuilder();
119  auto int32Ty = bldr.getI32Type();
120  auto i32x4Ty = VectorType::get({4}, int32Ty);
121 
122  if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
123  parser.getNameLoc(), result.operands))
124  return failure();
125  return success();
126 }
127 
129  p << " " << getOperands() << " : " << getVdata().getType();
130 }
131 
132 // <operation> ::=
133 // `llvm.amdgcn.raw.buffer.atomic.smax.* %vdata, %rsrc, %offset,
134 // %soffset, %aux : result_type`
135 ParseResult RawBufferAtomicSMaxOp::parse(OpAsmParser &parser,
136  OperationState &result) {
138  Type type;
139  if (parser.parseOperandList(ops, 5) || parser.parseColonType(type))
140  return failure();
141 
142  auto bldr = parser.getBuilder();
143  auto int32Ty = bldr.getI32Type();
144  auto i32x4Ty = VectorType::get({4}, int32Ty);
145 
146  if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
147  parser.getNameLoc(), result.operands))
148  return failure();
149  return success();
150 }
151 
153  p << " " << getOperands() << " : " << getVdata().getType();
154 }
155 
156 // <operation> ::=
157 // `llvm.amdgcn.raw.buffer.atomic.umin.* %vdata, %rsrc, %offset,
158 // %soffset, %aux : result_type`
159 ParseResult RawBufferAtomicUMinOp::parse(OpAsmParser &parser,
160  OperationState &result) {
162  Type type;
163  if (parser.parseOperandList(ops, 5) || parser.parseColonType(type))
164  return failure();
165 
166  auto bldr = parser.getBuilder();
167  auto int32Ty = bldr.getI32Type();
168  auto i32x4Ty = VectorType::get({4}, int32Ty);
169 
170  if (parser.resolveOperands(ops, {type, i32x4Ty, int32Ty, int32Ty, int32Ty},
171  parser.getNameLoc(), result.operands))
172  return failure();
173  return success();
174 }
175 
177  p << " " << getOperands() << " : " << getVdata().getType();
178 }
179 
180 //===----------------------------------------------------------------------===//
181 // ROCDLDialect initialization, type parsing, and registration.
182 //===----------------------------------------------------------------------===//
183 
184 namespace {
185 struct ROCDLInlinerInterface final : DialectInlinerInterface {
187  bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
188  return true;
189  }
190 };
191 } // namespace
192 
193 // TODO: This should be the llvm.rocdl dialect once this is supported.
194 void ROCDLDialect::initialize() {
195  addOperations<
196 #define GET_OP_LIST
197 #include "mlir/Dialect/LLVMIR/ROCDLOps.cpp.inc"
198  >();
199 
200  addAttributes<
201 #define GET_ATTRDEF_LIST
202 #include "mlir/Dialect/LLVMIR/ROCDLOpsAttributes.cpp.inc"
203  >();
204 
205  // Support unknown operations because not all ROCDL operations are registered.
206  allowUnknownOperations();
207  addInterfaces<ROCDLInlinerInterface>();
208  declarePromisedInterface<gpu::TargetAttrInterface, ROCDLTargetAttr>();
209 }
210 
211 LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op,
212  NamedAttribute attr) {
213  // Kernel function attribute should be attached to functions.
214  if (kernelAttrName.getName() == attr.getName()) {
215  if (!isa<LLVM::LLVMFuncOp>(op)) {
216  return op->emitError() << "'" << kernelAttrName.getName()
217  << "' attribute attached to unexpected op";
218  }
219  }
220  return success();
221 }
222 
223 //===----------------------------------------------------------------------===//
224 // ROCDL target attribute.
225 //===----------------------------------------------------------------------===//
226 LogicalResult
228  int optLevel, StringRef triple, StringRef chip,
229  StringRef features, StringRef abiVersion,
230  DictionaryAttr flags, ArrayAttr files) {
231  if (optLevel < 0 || optLevel > 3) {
232  emitError() << "The optimization level must be a number between 0 and 3.";
233  return failure();
234  }
235  if (triple.empty()) {
236  emitError() << "The target triple cannot be empty.";
237  return failure();
238  }
239  if (chip.empty()) {
240  emitError() << "The target chip cannot be empty.";
241  return failure();
242  }
243  if (abiVersion != "400" && abiVersion != "500" && abiVersion != "600") {
244  emitError() << "Invalid ABI version, it must be `400`, `500` or '600'.";
245  return failure();
246  }
247  if (files && !llvm::all_of(files, [](::mlir::Attribute attr) {
248  return attr && mlir::isa<StringAttr>(attr);
249  })) {
250  emitError() << "All the elements in the `link` array must be strings.";
251  return failure();
252  }
253  return success();
254 }
255 
256 #define GET_OP_CLASSES
257 #include "mlir/Dialect/LLVMIR/ROCDLOps.cpp.inc"
258 
259 #define GET_ATTRDEF_CLASSES
260 #include "mlir/Dialect/LLVMIR/ROCDLOpsAttributes.cpp.inc"
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.
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
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.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
IntegerType getI32Type()
Definition: Builders.cpp:63
This is the interface that must be implemented by the dialects of operations to be inlined.
Definition: InliningUtils.h:44
DialectInlinerInterface(Dialect *dialect)
Definition: InliningUtils.h:46
This is a utility class for mapping one set of IR entities to another.
Definition: IRMapping.h:26
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:316
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:55
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:88
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:268
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:21
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:423
This represents an operation in an abstracted form, suitable for use with the builder APIs.
SmallVector< Value, 4 > operands
SmallVector< Type, 4 > types
Types of the results of this operation.