MLIR 24.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
19#include "IR/ROCDLOps.h"
20
23#include "mlir/IR/Builders.h"
26#include "mlir/IR/MLIRContext.h"
27#include "mlir/IR/Operation.h"
29#include "llvm/ADT/StringExtras.h"
30#include "llvm/ADT/StringRef.h"
31#include "llvm/ADT/TypeSwitch.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/raw_ostream.h"
34
35using namespace mlir;
36using namespace ROCDL;
37
38#include "mlir/Dialect/LLVMIR/ROCDLOpsDialect.cpp.inc"
39#include "mlir/Dialect/LLVMIR/ROCDLOpsEnums.cpp.inc"
40
41//===----------------------------------------------------------------------===//
42// ROCDLDialect initialization, type parsing, and registration.
43//===----------------------------------------------------------------------===//
44
45namespace {
46struct ROCDLInlinerInterface final : DialectInlinerInterface {
47 using DialectInlinerInterface::DialectInlinerInterface;
48 bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
49 return true;
50 }
51};
52} // namespace
53
54// TODO: This should be the llvm.rocdl dialect once this is supported.
55void ROCDLDialect::initialize() {
56 registerROCDLDialectOperations(this);
57
58 addAttributes<
59#define GET_ATTRDEF_LIST
60#include "mlir/Dialect/LLVMIR/ROCDLOpsAttributes.cpp.inc"
61 >();
62
63 // Support unknown operations because not all ROCDL operations are registered.
64 allowUnknownOperations();
65 addInterfaces<ROCDLInlinerInterface>();
66 declarePromisedInterface<gpu::TargetAttrInterface, ROCDLTargetAttr>();
67}
68
69LLVM::ModFlagBehavior
70BufferOOBModeModuleFlagAttr::getModuleFlagBehavior() const {
71 return LLVM::ModFlagBehavior::Max;
72}
73
74StringAttr BufferOOBModeModuleFlagAttr::getModuleFlagKey() const {
75 return StringAttr::get(getContext(),
76 ROCDLDialect::getModuleFlagKeyBufferOOBModeName());
77}
78
79Attribute BufferOOBModeModuleFlagAttr::getModuleFlagValue() const {
80 return BufferOOBModeAttr::get(getContext(), getValue());
81}
82
83LLVM::ModFlagBehavior
84TBufferOOBModeModuleFlagAttr::getModuleFlagBehavior() const {
85 return LLVM::ModFlagBehavior::Max;
86}
87
88StringAttr TBufferOOBModeModuleFlagAttr::getModuleFlagKey() const {
89 return StringAttr::get(getContext(),
90 ROCDLDialect::getModuleFlagKeyTBufferOOBModeName());
91}
92
93Attribute TBufferOOBModeModuleFlagAttr::getModuleFlagValue() const {
94 return BufferOOBModeAttr::get(getContext(), getValue());
95}
96
97LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op,
98 NamedAttribute attr) {
99 // Kernel function attribute should be attached to functions.
100 if (kernelAttrName.getName() == attr.getName()) {
101 if (!isa<LLVM::LLVMFuncOp>(op)) {
102 return op->emitError() << "'" << kernelAttrName.getName()
103 << "' attribute attached to unexpected op";
104 }
105 }
106 // xnack/sramecc describe the whole code object.
107 if (attr.getName() == xnackAttrName.getName() ||
108 attr.getName() == srameccAttrName.getName()) {
110 return op->emitError()
111 << attr.getName() << " is only supported on modules";
112 if (!isa<BoolAttr>(attr.getValue()))
113 return op->emitError() << attr.getName() << " must be a boolean";
114 }
115 return success();
116}
117
118//===----------------------------------------------------------------------===//
119// ROCDL op custom parsers/printers.
120//===----------------------------------------------------------------------===//
121
122template <typename EnumAttrT, typename EnumT>
123static ParseResult parseCachePolicyEnum(OpAsmParser &parser,
124 Attribute &cachePolicy) {
125 if (parser.parseLess())
126 return failure();
127 FailureOr<EnumT> parsed = FieldParser<EnumT>::parse(parser);
128 if (failed(parsed))
129 return failure();
130 if (parser.parseGreater())
131 return failure();
132 cachePolicy = EnumAttrT::get(parser.getContext(), *parsed);
133 return success();
134}
135
137 Attribute &cachePolicy) {
138 uint32_t rawValue;
139 OptionalParseResult rawValueParseResult =
140 parser.parseOptionalInteger(rawValue);
141 if (rawValueParseResult.has_value()) {
142 if (failed(*rawValueParseResult))
143 return failure();
144 cachePolicy =
145 IntegerAttr::get(IntegerType::get(parser.getContext(), 32), rawValue);
146 return success();
147 }
148
149 StringRef policyFamily;
150 auto loc = parser.getCurrentLocation();
151 if (failed(parser.parseOptionalKeyword(
152 &policyFamily, {"pre_gfx12", "gfx942", "gfx12", "gfx12_atomic"}))) {
153 return parser.emitError(loc)
154 << "expected cache policy family 'pre_gfx12', 'gfx942', 'gfx12', "
155 "'gfx12_atomic', or a 32-bit integer";
156 }
157
158 if (policyFamily == "pre_gfx12")
160 parser, cachePolicy);
161 if (policyFamily == "gfx942")
163 parser, cachePolicy);
164 if (policyFamily == "gfx12")
166 parser, cachePolicy);
167 return parseCachePolicyEnum<Gfx12AtomicCachePolicyAttr,
168 Gfx12AtomicCachePolicy>(parser, cachePolicy);
169}
170
171template <typename EnumAttrT>
172static void printCachePolicyEnum(OpAsmPrinter &printer, EnumAttrT cachePolicy,
173 StringRef family) {
174 printer << family << "<" << cachePolicy.getValue() << ">";
175}
176
178 Attribute cachePolicy) {
179 llvm::TypeSwitch<Attribute>(cachePolicy)
180 .Case<IntegerAttr>([&](IntegerAttr rawPolicy) {
181 printer << rawPolicy.getValue().getZExtValue();
182 })
183 .Case<PreGfx12CachePolicyAttr>([&](PreGfx12CachePolicyAttr policy) {
184 printCachePolicyEnum(printer, policy, "pre_gfx12");
185 })
186 .Case<Gfx942CachePolicyAttr>([&](Gfx942CachePolicyAttr policy) {
187 printCachePolicyEnum(printer, policy, "gfx942");
188 })
189 .Case<Gfx12CachePolicyAttr>([&](Gfx12CachePolicyAttr policy) {
190 printCachePolicyEnum(printer, policy, "gfx12");
191 })
192 .Case<Gfx12AtomicCachePolicyAttr>([&](Gfx12AtomicCachePolicyAttr policy) {
193 printCachePolicyEnum(printer, policy, "gfx12_atomic");
194 })
195 .DefaultUnreachable("unknown ROCDL cache policy attribute");
196}
197
198//===----------------------------------------------------------------------===//
199// ROCDL target attribute.
200//===----------------------------------------------------------------------===//
201LogicalResult
202ROCDLTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
203 int optLevel, StringRef triple, StringRef chip,
204 StringRef features, StringRef abiVersion,
205 DictionaryAttr flags, ArrayAttr files) {
206 if (optLevel < 0 || optLevel > 3) {
207 emitError() << "The optimization level must be a number between 0 and 3.";
208 return failure();
209 }
210 if (triple.empty()) {
211 emitError() << "The target triple cannot be empty.";
212 return failure();
213 }
214 if (chip.empty()) {
215 emitError() << "The target chip cannot be empty.";
216 return failure();
217 }
218 if (abiVersion != "400" && abiVersion != "500" && abiVersion != "600") {
219 emitError() << "Invalid ABI version, it must be `400`, `500` or '600'.";
220 return failure();
221 }
222 if (files && !llvm::all_of(files, [](::mlir::Attribute attr) {
223 return mlir::isa_and_nonnull<StringAttr>(attr);
224 })) {
225 emitError() << "All the elements in the `link` array must be strings.";
226 return failure();
227 }
228 return success();
229}
230
231#define GET_ATTRDEF_CLASSES
232#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.
b getContext())
static ParseResult parseCachePolicyEnum(OpAsmParser &parser, Attribute &cachePolicy)
static void printCachePolicyEnum(OpAsmPrinter &printer, EnumAttrT cachePolicy, StringRef family)
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLess()=0
Parse a '<' token.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseGreater()=0
Parse a '>' token.
Attributes are known-constant values of operations.
Definition Attributes.h:25
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.
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
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...
This class implements Optional functionality for ParseResult.
bool has_value() const
Returns true if we contain a valid ParseResult value.
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
ParseResult parseCachePolicy(OpAsmParser &parser, Attribute &cachePolicy)
void printCachePolicy(OpAsmPrinter &printer, Operation *, Attribute cachePolicy)
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
Provide a template class that can be specialized by users to dispatch to parsers.