MLIR 24.0.0git
OpenACCRuntimeUtils.cpp
Go to the documentation of this file.
1//===- OpenACCRuntimeUtils.cpp - OpenACC runtime call utilities -*- C++ -*-===//
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
10
11#include "mlir/IR/SymbolTable.h"
12#include "llvm/Support/ErrorHandling.h"
13
14#include <cassert>
15#include <optional>
16
17using namespace mlir;
18using namespace mlir::acc;
19
24
26 switch (fn) {
27#define ACC_RTL(Enum, Str, ...) \
28 case RuntimeFunction::Enum: \
29 return Str;
30#include "mlir/Dialect/OpenACC/OpenACCRuntimeFunctions.def"
31 }
32 llvm_unreachable("unknown ACC runtime function");
33}
34
35LLVM::LLVMFunctionType acc::getRuntimeFunctionType(MLIRContext *ctx,
36 RuntimeFunction fn) {
37 Type Void = LLVM::LLVMVoidType::get(ctx);
38 Type Ptr = LLVM::LLVMPointerType::get(ctx);
39 Type Int32 = IntegerType::get(ctx, 32);
40 Type Int64 = IntegerType::get(ctx, 64);
41
42 switch (fn) {
43#define ACC_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
44 case RuntimeFunction::Enum: \
45 return LLVM::LLVMFunctionType::get(ReturnType, \
46 ArrayRef<Type>{__VA_ARGS__}, IsVarArg);
47#include "mlir/Dialect/OpenACC/OpenACCRuntimeFunctions.def"
48 }
49 llvm_unreachable("unknown ACC runtime function");
50}
51
53 switch (desc) {
54#define ACC_DESC_BEGIN(Enum, NameStr, DescKind) \
55 case DataDescriptor::Enum: \
56 return NameStr;
57#include "mlir/Dialect/OpenACC/OpenACCRuntimeDescriptors.def"
58 }
59 llvm_unreachable("unknown ACC data descriptor");
60}
61
63 switch (desc) {
64#define ACC_DESC_BEGIN(Enum, NameStr, DescKind) \
65 case DataDescriptor::Enum: \
66 return DescKind;
67#include "mlir/Dialect/OpenACC/OpenACCRuntimeDescriptors.def"
68 }
69 llvm_unreachable("unknown ACC data descriptor");
70}
71
72LLVM::LLVMStructType acc::getDataDescriptorType(MLIRContext *ctx,
73 DataDescriptor desc,
74 Type baseType) {
75 Type Int8 = IntegerType::get(ctx, 8);
76 Type Int32 = IntegerType::get(ctx, 32);
77 Type Int64 = IntegerType::get(ctx, 64);
78 Type Ptr = LLVM::LLVMPointerType::get(ctx);
79 Type Base = baseType;
80
81 switch (desc) {
82#define ACC_DESC_BEGIN(Enum, NameStr, DescKind) \
83 case DataDescriptor::Enum: { \
84 SmallVector<Type> fields;
85#define ACC_DESC_FIELD(Enum, Field, TypeToken) \
86 assert(TypeToken && "no type for descriptor field " #Field); \
87 fields.push_back(TypeToken);
88#define ACC_DESC_END(Enum) \
89 return LLVM::LLVMStructType::getLiteral(ctx, fields); \
90 }
91#include "mlir/Dialect/OpenACC/OpenACCRuntimeDescriptors.def"
92 }
93 llvm_unreachable("unknown ACC data descriptor");
94}
95
96LLVM::LLVMStructType acc::getKernelArgumentType(MLIRContext *ctx) {
97 Type Int32 = IntegerType::get(ctx, 32);
98 Type Int64 = IntegerType::get(ctx, 64);
99 Type Ptr = LLVM::LLVMPointerType::get(ctx);
100 Type Int64x3 = LLVM::LLVMArrayType::get(Int64, 3);
101 SmallVector<Type> fields;
102#define ACC_KERNEL_ARG_FIELD(Field, TypeToken) fields.push_back(TypeToken);
103#include "mlir/Dialect/OpenACC/OpenACCRuntimeKernelArgs.def"
104 return LLVM::LLVMStructType::getLiteral(ctx, fields);
105}
106
108 overrides[fn] = name.str();
109}
110
112 if (auto it = overrides.find(fn); it != overrides.end())
113 return it->second;
114 return getRuntimeFunctionName(fn);
115}
116
118 functionDisplayNameFn = std::move(fn);
119}
120
121std::string
122ACCRuntimeCallConfig::getFunctionDisplayName(StringRef mangledOrSymbol) const {
123 if (functionDisplayNameFn)
124 return functionDisplayNameFn(mangledOrSymbol);
125 return mangledOrSymbol.str();
126}
127
129 int64_t runtimeValue) {
130 deviceTypeRuntimeValues[type] = runtimeValue;
131}
132
134 if (auto it = deviceTypeRuntimeValues.find(type);
135 it != deviceTypeRuntimeValues.end())
136 return it->second;
137 llvm::report_fatal_error(
138 llvm::Twine("missing OpenACC runtime device-type mapping for ") +
139 stringifyDeviceType(type));
140}
141
143 int64_t runtimeValue) {
144 mapFlagRuntimeValues[flag] = runtimeValue;
145}
146
148 int64_t runtimeValue = 0;
149 for (unsigned bit = 0; bit != 32; ++bit) {
150 auto flag = static_cast<MapFlags>(1u << bit);
151 if (!bitEnumContainsAny(flags, flag))
152 continue;
153 auto it = mapFlagRuntimeValues.find(flag);
154 if (it == mapFlagRuntimeValues.end())
155 llvm::report_fatal_error(
156 llvm::Twine("missing OpenACC runtime map-flag mapping for ") +
157 stringifyMapFlags(flag));
158 runtimeValue |= it->second;
159 }
160 return runtimeValue;
161}
162
164 mapFlagsPostProcessFn = std::move(fn);
165}
166
168 MapFlags flags) const {
169 if (mapFlagsPostProcessFn)
170 return mapFlagsPostProcessFn(mapOp, flags);
171 return flags;
172}
173
174std::string ACCRuntimeCallConfig::formatMapFlags(MapFlags flags) const {
175 int64_t runtimeValue = getMapFlagsRuntimeValue(flags);
176 std::string rendered = stringifyMapFlags(flags);
177 rendered += " (";
178 rendered += std::to_string(runtimeValue);
179 rendered += " / 0x";
180 rendered += llvm::Twine::utohexstr(runtimeValue).str();
181 rendered += ")";
182 return rendered;
183}
184
186 asyncSyncRuntimeValue = runtimeValue;
187}
188
190 return asyncSyncRuntimeValue;
191}
192
194 asyncNoValueRuntimeValue = runtimeValue;
195}
196
198 return asyncNoValueRuntimeValue;
199}
200
203 declareBinaryDescriptorFn = std::move(fn);
204}
205
207 Location loc, OpBuilder &builder) const {
208 if (declareBinaryDescriptorFn)
209 return declareBinaryDescriptorFn(loc, builder);
210 return LLVM::ZeroOp::create(builder, loc,
211 LLVM::LLVMPointerType::get(builder.getContext()));
212}
213
216 kernelBinaryDescriptorFn = std::move(fn);
217}
218
220 Location loc, OpBuilder &builder) const {
221 if (kernelBinaryDescriptorFn)
222 return kernelBinaryDescriptorFn(loc, builder);
223 return LLVM::ZeroOp::create(builder, loc,
224 LLVM::LLVMPointerType::get(builder.getContext()));
225}
226
228 ACCRuntimeCallConfig &config) {
229 for (uint32_t value = 0; value <= getMaxEnumValForDeviceType(); ++value)
230 if (std::optional<DeviceType> type = symbolizeDeviceType(value))
231 config.setDeviceTypeRuntimeValue(*type, value);
232}
233
235 for (unsigned bit = 0; bit != 32; ++bit) {
236 uint32_t value = 1u << bit;
237 if (std::optional<MapFlags> flag = symbolizeMapFlags(value))
238 config.setMapFlagRuntimeValue(*flag, value);
239 }
240}
241
242FailureOr<LLVM::CallOp>
244 Region &globalSymbolRegion, SymbolTable &symbolTable,
245 RuntimeFunction fn, const ACCRuntimeCallConfig &config,
246 ArrayRef<Value> arguments) {
247 MLIRContext *ctx = builder.getContext();
248 LLVM::LLVMFunctionType fnTy = getRuntimeFunctionType(ctx, fn);
249 StringRef symbolName = config.getName(fn);
250
251 auto func = symbolTable.lookup<LLVM::LLVMFuncOp>(symbolName);
252 if (func) {
253 // An existing declaration with a different signature cannot be called with
254 // the arguments expected by the runtime entry point.
255 if (func.getFunctionType() != fnTy)
256 return emitError(loc) << "OpenACC runtime function '" << symbolName
257 << "' is already declared with signature "
258 << func.getFunctionType() << ", expected " << fnTy;
259 } else {
260 OpBuilder moduleBuilder =
261 OpBuilder::atBlockEnd(&globalSymbolRegion.front());
262 func = LLVM::LLVMFuncOp::create(moduleBuilder, loc, symbolName, fnTy);
263 symbolTable.insert(func);
264 }
265
266 return LLVM::CallOp::create(builder, loc, func, arguments);
267}
MLIRContext * getContext() const
Definition Builders.h:56
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:64
This class helps build Operations.
Definition Builders.h:210
static OpBuilder atBlockEnd(Block *block, Listener *listener=nullptr)
Create a builder and set the insertion point to after the last operation in the block but still insid...
Definition Builders.h:249
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Block & front()
Definition Region.h:65
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Definition SymbolTable.h:25
Operation * lookup(StringRef name) const
Look up a symbol with the specified name, returning null if no such name exists.
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Configuration for OpenACC to LLVM runtime lowering.
StringRef getName(RuntimeFunction fn) const
std::string formatMapFlags(MapFlags flags) const
Renders flags for a diagnostic as the names of the set bits and the decimal and hexadecimal encoding ...
std::string getFunctionDisplayName(StringRef mangledOrSymbol) const
std::function< Value(Location, OpBuilder &)> KernelBinaryDescriptorFn
Materialize the target-specific binary descriptor passed to __tgt_acc_kernel.
void setKernelBinaryDescriptorFn(KernelBinaryDescriptorFn fn)
void setName(RuntimeFunction fn, StringRef name)
Value createDeclareBinaryDescriptor(Location loc, OpBuilder &builder) const
void setAsyncSyncRuntimeValue(int64_t runtimeValue)
Runtime encoding of acc_async_sync, used when an operation carries no async clause.
void setDeviceTypeRuntimeValue(DeviceType type, int64_t runtimeValue)
Map an OpenACC dialect DeviceType to the integer encoding expected by the target runtime.
void setMapFlagRuntimeValue(MapFlags flag, int64_t runtimeValue)
Map a single OpenACC dialect MapFlags bit to the bit the target runtime gives the same meaning.
int64_t getDeviceTypeRuntimeValue(DeviceType type) const
std::function< MapFlags(Operation *mapOp, MapFlags flags)> MapFlagsPostProcessFn
Adjust the flags of a mapping before they are encoded.
void setFunctionDisplayNameFn(FunctionDisplayNameFn fn)
std::function< std::string(StringRef)> FunctionDisplayNameFn
int64_t getMapFlagsRuntimeValue(MapFlags flags) const
std::function< Value(Location, OpBuilder &)> DeclareBinaryDescriptorFn
Materialize the target-specific binary descriptor passed to __tgt_acc_declare.
MapFlags postProcessMapFlags(Operation *mapOp, MapFlags flags) const
void setMapFlagsPostProcessFn(MapFlagsPostProcessFn fn)
Value createKernelBinaryDescriptor(Location loc, OpBuilder &builder) const
void setDeclareBinaryDescriptorFn(DeclareBinaryDescriptorFn fn)
void setAsyncNoValueRuntimeValue(int64_t runtimeValue)
Runtime encoding of acc_async_noval, used for an async clause without an argument.
LLVM::LLVMFunctionType getRuntimeFunctionType(MLIRContext *ctx, RuntimeFunction fn)
Builds the LLVM function type for fn in ctx.
void populateDialectIdentityDeviceTypeMapping(ACCRuntimeCallConfig &config)
Install a device-type mapping that uses OpenACC dialect enum ordinals as the runtime encoding.
StringRef getRuntimeFunctionName(RuntimeFunction fn)
Returns the default runtime symbol name for fn.
LLVM::LLVMStructType getDataDescriptorType(MLIRContext *ctx, DataDescriptor desc, Type baseType={})
Builds the LLVM type of desc in ctx.
DataDescKind getDataDescriptorKind(DataDescriptor desc)
Returns the descriptor kind the runtime reads from the version field of desc.
LLVM::LLVMStructType getKernelArgumentType(MLIRContext *ctx)
The LLVM type of the argument struct passed to __tgt_acc_kernel.
StringRef getDataDescriptorName(DataDescriptor desc)
Returns the name of the runtime type desc materializes.
DataDescriptor
IDs for the argument descriptors of the OpenACC data entry points, declared in OpenACCRuntimeDescript...
RuntimeFunction
IDs for OpenACC compiler-to-runtime entry points (__tgt_acc_*).
void populateDialectIdentityMapFlagsMapping(ACCRuntimeCallConfig &config)
Install a map-flag mapping that uses the OpenACC dialect bit positions as the runtime encoding,...
FailureOr< LLVM::CallOp > createRuntimeCall(Location loc, OpBuilder &builder, Region &globalSymbolRegion, SymbolTable &symbolTable, RuntimeFunction fn, const ACCRuntimeCallConfig &config, ArrayRef< Value > arguments)
Declares (if needed) and returns a call to the runtime function identified by fn using the name from ...
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.