MLIR 24.0.0git
ACCKernelLaunchPatterns.cpp
Go to the documentation of this file.
1//===- ACCKernelLaunchPatterns.cpp - Kernel launch to LLVM ------*- 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//
9// Lower acc.kernel_environment and the gpu.launch_func operations in its body
10// together. The environment establishes one implicit data region. Its entry
11// call returns the device addresses that every contained kernel launch uses.
12//
13//===----------------------------------------------------------------------===//
14
18
27#include "mlir/IR/BuiltinOps.h"
28#include "llvm/ADT/DenseMap.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/Support/raw_ostream.h"
31
32#include <array>
33
34using namespace mlir;
35using namespace mlir::acc;
36
37static bool isDevicePtrMapping(Value operand) {
38 Operation *mapOp = operand.getDefiningOp();
39 if (!mapOp)
40 return false;
41 if (std::optional<MapFlags> flags = getMapFlags(mapOp))
42 return bitEnumContainsAny(*flags, MapFlags::devptr);
43 if (std::optional<DataClause> clause = getDataClause(mapOp))
44 return *clause == DataClause::acc_deviceptr;
45 return false;
46}
47
48static bool isDataEntryInsideEnvironment(KernelEnvironmentOp environment,
49 Value operand) {
50 Operation *mapOp = operand.getDefiningOp();
51 return isDataEntryOp(mapOp) && environment->isAncestor(mapOp);
52}
53
54/// The flags of a data clause operation that maps a kernel argument. A kernel
55/// argument only looks up the mapping its clause established, so the clauses
56/// that establish or tear down something else contribute no flag for it.
57static MapFlags getKernelDataClauseMapFlags(Operation *entryOp) {
58 bool ptrAndObj = hasAttachPoint(entryOp);
59 MapFlags ptrAndObjFlag = ptrAndObj ? MapFlags::ptr_and_obj : MapFlags::none;
60 std::optional<DataClause> clause = getDataClause(entryOp);
61 if (clause == DataClause::acc_declare_device_resident)
62 return MapFlags::present | ptrAndObjFlag;
63 if (clause == DataClause::acc_attach || clause == DataClause::acc_detach)
64 return ptrAndObjFlag;
65 return bitEnumClear(computeDataClauseMapFlags(entryOp, ptrAndObj),
66 MapFlags::device_resident);
67}
68
69/// The flags a kernel argument is passed with. An operand the environment
70/// already mapped is passed as the device address its entry call returned. An
71/// operand that no clause maps is passed by value.
72static MapFlags getKernelArgMapFlags(Value operand, bool alreadyMapped,
73 const ACCRuntimeCallConfig &config) {
74 Operation *mapOp = operand.getDefiningOp();
75 if (!isDataEntryOp(mapOp))
76 return mapOp ? config.postProcessMapFlags(mapOp, MapFlags::literal)
77 : MapFlags::literal;
78
79 MapFlags flags;
80 if (alreadyMapped)
81 flags = MapFlags::devptr | MapFlags::literal;
82 else if (auto mapInfo = dyn_cast<MapInfoOp>(mapOp))
83 flags = mapInfo.getMapFlags();
84 else
85 flags = getKernelDataClauseMapFlags(mapOp);
86 if (getImplicitFlag(mapOp))
87 flags = flags | MapFlags::implicit;
88 return config.postProcessMapFlags(mapOp, flags);
89}
90
91/// The descriptor of a kernel argument. The device address the environment
92/// returned is passed as is, since the runtime would map an address that
93/// carries a descriptor again.
94static FailureOr<Value>
96 bool alreadyMapped, OpenACCSupport &accSupport,
97 ConversionPatternRewriter &rewriter) {
98 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
99 Operation *mapOp = operand.getDefiningOp();
100 if (alreadyMapped)
101 return Value(LLVM::ZeroOp::create(rewriter, loc, ptrTy));
102 if (isDataEntryOp(mapOp))
103 return createACCArgumentDescriptor(mapOp, converted, accSupport, rewriter);
104 if (auto memrefType = dyn_cast<MemRefType>(operand.getType())) {
105 ModuleOp module = rewriter.getInsertionBlock()
106 ->getParentOp()
107 ->getParentOfType<ModuleOp>();
108 auto sizeAndAlignment = acc::getTypeSizeAndAlignment(
109 memrefType.getElementType(), module, &accSupport);
110 if (!sizeAndAlignment) {
111 std::string message;
112 llvm::raw_string_ostream os(message);
113 os << "unhandled type size computation for type: "
114 << memrefType.getElementType();
115 (void)accSupport.emitNYI(loc, message);
116 return failure();
117 }
119 loc, memrefType, converted, /*bounds=*/{},
120 constantI64(loc, sizeAndAlignment->first.getFixedValue(), rewriter),
121 rewriter);
122 }
123 return Value(LLVM::ZeroOp::create(rewriter, loc, ptrTy));
124}
125
126/// Emits the argument arrays of the kernel launched by \p launch, one entry per
127/// kernel operand. Each operand is one parameter of the kernel.
128static FailureOr<ACCDataRuntimeArgs> emitKernelRuntimeArgs(
129 gpu::LaunchFuncOp launch, gpu::LaunchFuncOpAdaptor adaptor,
130 ValueRange alreadyMappedOperands, ConversionPatternRewriter &rewriter,
131 OpenACCSupport &accSupport, Region &globalSymbolRegion,
132 SymbolTable &symbolTable, const ACCRuntimeCallConfig &config) {
133 Location loc = launch.getLoc();
135 for (auto [operand, converted] : llvm::zip_equal(
136 launch.getKernelOperands(), adaptor.getKernelOperands())) {
137 bool alreadyMapped = llvm::is_contained(alreadyMappedOperands, operand);
138 MapFlags mapFlags = getKernelArgMapFlags(operand, alreadyMapped, config);
139 Operation *mapOp = operand.getDefiningOp();
140
142 // A kernel argument states the base of the mapping it looks up, which for
143 // an object the declare directive made resident is that of its entry.
145 loc, isDataEntryOp(mapOp) ? mapOp : nullptr, mapFlags, rewriter);
146 args.pointer = createACCMappedObjectPointer(loc, operand, converted,
147 mapFlags, rewriter);
148 FailureOr<Value> size = createACCMappedObjectSize(
149 loc, operand, converted, mapFlags, accSupport, rewriter);
150 if (failed(size))
151 return failure();
152 args.size = *size;
153 args.type =
154 constantI64(loc, config.getMapFlagsRuntimeValue(mapFlags), rewriter);
156 loc, operand, accSupport, globalSymbolRegion, &symbolTable, rewriter);
157 FailureOr<Value> descriptor = getKernelArgDescriptor(
158 loc, operand, converted, alreadyMapped, accSupport, rewriter);
159 if (failed(descriptor))
160 return failure();
161 args.descriptor = *descriptor;
162 objects.push_back(args);
163 }
164
165 ACCDataRuntimeArgs runtimeArgs;
166 createACCMappedObjectArrays(loc, objects, runtimeArgs, rewriter);
167 return runtimeArgs;
168}
169
170static FailureOr<Value> createKernelArgumentStruct(
171 gpu::LaunchFuncOp launch, gpu::LaunchFuncOpAdaptor adaptor,
172 ValueRange alreadyMappedOperands, ConversionPatternRewriter &rewriter,
173 OpenACCSupport &accSupport, Region &globalSymbolRegion,
174 SymbolTable &symbolTable, const ACCRuntimeCallConfig &config) {
175 FailureOr<ACCDataRuntimeArgs> emitted = emitKernelRuntimeArgs(
176 launch, adaptor, alreadyMappedOperands, rewriter, accSupport,
177 globalSymbolRegion, symbolTable, config);
178 if (failed(emitted))
179 return failure();
180 ACCDataRuntimeArgs runtimeArgs = *emitted;
181
182 Location loc = launch.getLoc();
183 MLIRContext *context = rewriter.getContext();
184 Type i32Ty = rewriter.getI32Type();
185 Type ptrTy = LLVM::LLVMPointerType::get(context);
186 Type argsType = getKernelArgumentType(context);
187 Value args = LLVM::ZeroOp::create(rewriter, loc, argsType);
188 auto insert = [&](Value value, KernelArgumentField field) {
189 args = LLVM::InsertValueOp::create(
190 rewriter, loc, argsType, args, value,
192 };
193 insert(runtimeArgs.argNum, KernelArgumentField::ArgNum);
194 insert(runtimeArgs.argBasePtrs, KernelArgumentField::ArgBasePtrs);
195 insert(runtimeArgs.argPtrs, KernelArgumentField::ArgPtrs);
196 insert(runtimeArgs.argSizes, KernelArgumentField::ArgSizes);
197 insert(runtimeArgs.argTypes, KernelArgumentField::ArgTypes);
198 insert(runtimeArgs.argNames, KernelArgumentField::ArgNames);
199 insert(runtimeArgs.argMappers, KernelArgumentField::ArgMappers);
200 insert(runtimeArgs.argDescs, KernelArgumentField::ArgDescs);
201
202 // The vector length is the first block dimension. The worker count is the
203 // product of the remaining ones.
204 Value blockY = castToI64(loc, adaptor.getBlockSizeY(), rewriter);
205 Value blockZ = castToI64(loc, adaptor.getBlockSizeZ(), rewriter);
206 insert(LLVM::MulOp::create(rewriter, loc, blockY, blockZ),
207 KernelArgumentField::NumWorkers);
208 insert(castToI64(loc, adaptor.getBlockSizeX(), rewriter),
209 KernelArgumentField::VectorLength);
210 Value dynamicSharedMemorySize =
211 adaptor.getDynamicSharedMemorySize()
212 ? castToI64(loc, adaptor.getDynamicSharedMemorySize(), rewriter)
213 : constantI64(loc, 0, rewriter);
214 insert(dynamicSharedMemorySize, KernelArgumentField::SmemSize);
215
216 // The grid sizes are the entries of the array in the NumGangs field.
217 int64_t numGangsField =
218 getKernelArgumentFieldIndex(KernelArgumentField::NumGangs);
219 std::array<Value, 3> gridSizes = {
220 adaptor.getGridSizeX(), adaptor.getGridSizeY(), adaptor.getGridSizeZ()};
221 for (auto [dimension, gridSize] : llvm::enumerate(gridSizes))
222 args = LLVM::InsertValueOp::create(
223 rewriter, loc, argsType, args, castToI64(loc, gridSize, rewriter),
224 ArrayRef<int64_t>{numGangsField, static_cast<int64_t>(dimension)});
225
226 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
227 Value argsPtr = LLVM::AllocaOp::create(rewriter, loc, ptrTy, argsType, one);
228 LLVM::StoreOp::create(rewriter, loc, args, argsPtr);
229 return argsPtr;
230}
231
232static FailureOr<Value> getKernelPointer(gpu::LaunchFuncOp launch,
233 ConversionPatternRewriter &rewriter,
234 Region &globalSymbolRegion,
235 SymbolTable &symbolTable) {
236 Location loc = launch.getLoc();
237 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
238 StringRef kernelName = launch.getKernel().getLeafReference().getValue();
239 if (auto function = symbolTable.lookup<LLVM::LLVMFuncOp>(kernelName))
240 return LLVM::AddressOfOp::create(rewriter, loc, ptrTy, function.getName())
241 .getResult();
242 if (auto function = symbolTable.lookup<func::FuncOp>(kernelName))
243 return LLVM::AddressOfOp::create(rewriter, loc, ptrTy, function.getName())
244 .getResult();
245
247 launch, launch.getKernel());
248 if (!gpuFunction)
249 return failure();
250
251 {
252 OpBuilder::InsertionGuard guard(rewriter);
253 rewriter.setInsertionPointToStart(&globalSymbolRegion.front());
254 auto functionType = LLVM::LLVMFunctionType::get(
255 LLVM::LLVMVoidType::get(rewriter.getContext()), {});
256 auto declaration =
257 LLVM::LLVMFuncOp::create(rewriter, loc, kernelName, functionType);
258 symbolTable.insert(declaration);
259 }
260 return LLVM::AddressOfOp::create(rewriter, loc, ptrTy, kernelName)
261 .getResult();
262}
263
264static void declareLibc(SymbolTable &symbolTable, Region &globalSymbolRegion,
265 Location loc, StringRef name, Type result,
266 ArrayRef<Type> arguments) {
267 if (symbolTable.lookup<LLVM::LLVMFuncOp>(name))
268 return;
269 OpBuilder builder = OpBuilder::atBlockEnd(&globalSymbolRegion.front());
270 auto functionType = LLVM::LLVMFunctionType::get(result, arguments);
271 symbolTable.insert(
272 LLVM::LLVMFuncOp::create(builder, loc, name, functionType));
273}
274
275/// The kernel entry point reports a status other than success when the kernel
276/// could not run on the device. The program is then meant to run the region on
277/// the host, which is not implemented, so the failure is reported and the
278/// program stops.
280 ConversionPatternRewriter &rewriter,
281 Region &globalSymbolRegion,
282 SymbolTable &symbolTable) {
283 MLIRContext *context = rewriter.getContext();
284 Type i32Ty = rewriter.getI32Type();
285 Type ptrTy = LLVM::LLVMPointerType::get(context);
286 Type voidTy = LLVM::LLVMVoidType::get(context);
287
288 Block *preBlock = rewriter.getInsertionBlock();
289 Block *continueBlock =
290 rewriter.splitBlock(preBlock, rewriter.getInsertionPoint());
291 Block *errorBlock =
292 rewriter.createBlock(preBlock->getParent(), continueBlock->getIterator());
293 rewriter.setInsertionPointToEnd(preBlock);
294 Value success = LLVM::ConstantOp::create(
295 rewriter, loc, i32Ty, static_cast<int32_t>(RuntimeResult::Success));
296 Value failed = LLVM::ICmpOp::create(rewriter, loc, LLVM::ICmpPredicate::ne,
297 status, success);
298 LLVM::CondBrOp::create(rewriter, loc, failed, errorBlock, ValueRange{},
299 continueBlock, ValueRange{});
300
301 // TODO: Runtime API should provide a mechanism to report this error.
302 rewriter.setInsertionPointToStart(errorBlock);
303 declareLibc(symbolTable, globalSymbolRegion, loc, "puts", i32Ty, {ptrTy});
304 declareLibc(symbolTable, globalSymbolRegion, loc, "fflush", i32Ty, {ptrTy});
305 declareLibc(symbolTable, globalSymbolRegion, loc, "abort", voidTy, {});
307 loc, rewriter, getInternalGlobalName("message", "host_fallback_nyi"),
308 "host fallback execution is not implemented\n", globalSymbolRegion,
309 &symbolTable);
310 LLVM::CallOp::create(rewriter, loc, TypeRange{i32Ty},
311 SymbolRefAttr::get(context, "puts"),
312 ValueRange{message});
313 Value nullFile = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
314 LLVM::CallOp::create(rewriter, loc, TypeRange{i32Ty},
315 SymbolRefAttr::get(context, "fflush"),
316 ValueRange{nullFile});
317 LLVM::CallOp::create(rewriter, loc, TypeRange{},
318 SymbolRefAttr::get(context, "abort"), ValueRange{});
319 LLVM::UnreachableOp::create(rewriter, loc);
320 rewriter.setInsertionPointToStart(continueBlock);
321}
322
323static LogicalResult
324emitKernelCall(gpu::LaunchFuncOp launch, gpu::LaunchFuncOpAdaptor adaptor,
325 Value asyncQueue, ValueRange alreadyMappedOperands,
326 ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport,
327 Region &globalSymbolRegion, SymbolTable &symbolTable,
328 const ACCRuntimeCallConfig &config) {
329 Location loc = launch.getLoc();
330 FailureOr<Value> kernelPointer =
331 getKernelPointer(launch, rewriter, globalSymbolRegion, symbolTable);
332 if (failed(kernelPointer)) {
333 (void)accSupport.emitNYI(loc, "undefined kernel");
334 return failure();
335 }
336 FailureOr<Value> arguments = createKernelArgumentStruct(
337 launch, adaptor, alreadyMappedOperands, rewriter, accSupport,
338 globalSymbolRegion, symbolTable, config);
339 if (failed(arguments))
340 return failure();
341
342 StringRef kernelName = launch.getKernel().getLeafReference().getValue();
343 Value kernelNamePtr = getOrCreateGlobalString(
344 loc, rewriter, getInternalGlobalName("kernel_name", kernelName),
345 kernelName, globalSymbolRegion, &symbolTable);
346 Value ident = createIdent(loc, getParentFunctionName(launch), rewriter,
347 globalSymbolRegion, config, &symbolTable);
348 // The kernel call uses the explicit data-region flag.
349 Value flags = constantI64(loc, static_cast<int64_t>(ACCDataRegionFlags::None),
350 rewriter);
351 // The launch is made for the default device type, as the data calls of the
352 // environment are.
353 Value deviceType = constantI64(
354 loc, config.getDeviceTypeRuntimeValue(DeviceType::None), rewriter);
355 Value binaryDescriptor = config.createKernelBinaryDescriptor(loc, rewriter);
356 FailureOr<LLVM::CallOp> call =
357 createRuntimeCall(loc, rewriter, globalSymbolRegion, symbolTable,
358 RuntimeFunction::ACCRTL_tgt_acc_kernel, config,
359 {ident, *kernelPointer, flags, deviceType, *arguments,
360 asyncQueue, kernelNamePtr, binaryDescriptor});
361 if (failed(call))
362 return failure();
363 emitHostFallbackNotImplemented(loc, call->getResult(), rewriter,
364 globalSymbolRegion, symbolTable);
365 return success();
366}
367
368namespace {
369struct KernelEnvironmentLowering
370 : public ConvertOpToLLVMPattern<KernelEnvironmentOp> {
371 KernelEnvironmentLowering(const LLVMTypeConverter &converter,
372 OpenACCSupport &accSupport,
373 Region &globalSymbolRegion,
374 SymbolTable &symbolTable,
375 const ACCRuntimeCallConfig &config,
376 DeviceType clauseDeviceType,
377 PatternBenefit benefit = 1)
378 : ConvertOpToLLVMPattern<KernelEnvironmentOp>(converter, benefit),
379 accSupport(accSupport), globalSymbolRegion(globalSymbolRegion),
380 symbolTable(symbolTable), config(config),
381 clauseDeviceType(clauseDeviceType) {}
382
383 LogicalResult
384 matchAndRewrite(KernelEnvironmentOp environment, OpAdaptor adaptor,
385 ConversionPatternRewriter &rewriter) const override {
386 ValueRange mappingOperands = environment.getDataClauseOperands();
387 ValueRange convertedMappingOperands = adaptor.getDataClauseOperands();
388 Location beginLoc = mappingOperands.empty()
389 ? environment.getLoc()
390 : mappingOperands.front().getLoc();
391 Location endLoc = getMappingExitLoc(mappingOperands).value_or(beginLoc);
392 Value asyncQueue =
393 getAsyncQueue(environment, clauseDeviceType, rewriter, config);
394 if (failed(emitWaitClause(environment, clauseDeviceType, asyncQueue,
395 rewriter, accSupport, globalSymbolRegion,
396 symbolTable, config)))
397 return failure();
398
399 SmallVector<Value> alreadyMappedOperands;
400 for (Value operand : mappingOperands)
401 if (!isDevicePtrMapping(operand))
402 alreadyMappedOperands.push_back(operand);
403
404 ACCDataCallOptions beginOptions;
405 beginOptions.flags = static_cast<int64_t>(ACCDataRegionFlags::Implicit);
406 beginOptions.returnAddressOperands = alreadyMappedOperands;
407 FailureOr<SmallVector<Value>> devicePointers = emitACCDataRuntimeCall(
408 beginLoc, RuntimeFunction::ACCRTL_tgt_acc_data_begin, mappingOperands,
409 convertedMappingOperands, rewriter, accSupport, globalSymbolRegion,
410 symbolTable, config, {asyncQueue}, beginOptions);
411 if (failed(devicePointers))
412 return failure();
413
414 llvm::DenseMap<Value, Value> deviceAddress;
415 for (auto [operand, pointer] :
416 llvm::zip_equal(alreadyMappedOperands, *devicePointers))
417 deviceAddress[operand] = pointer;
418
419 SmallVector<gpu::LaunchFuncOp> launches;
420 environment.walk(
421 [&](gpu::LaunchFuncOp launch) { launches.push_back(launch); });
422 for (gpu::LaunchFuncOp launch : launches) {
423 SmallVector<Value> converted;
424 converted.reserve(launch->getNumOperands());
425 for (Value operand : launch->getOperands()) {
426 Value value;
427 // A data entry in the region is mapped by this kernel, so it is passed
428 // as the variable of its clause.
429 if (isDataEntryInsideEnvironment(environment, operand))
430 value = remapOrSelf(getVar(operand.getDefiningOp()), rewriter);
431 else
432 value = deviceAddress.lookup(operand);
433 if (!value)
434 value = rewriter.getRemappedValue(operand);
435 if (!value)
436 return rewriter.notifyMatchFailure(launch,
437 "unconverted kernel operand");
438 converted.push_back(value);
439 }
440
441 gpu::LaunchFuncOpAdaptor launchAdaptor(converted, launch);
442 Value queue = launchAdaptor.getAsyncObject();
443 queue = queue ? castToI64(launch.getLoc(), queue, rewriter) : asyncQueue;
444 rewriter.setInsertionPoint(launch);
445 if (failed(emitKernelCall(launch, launchAdaptor, queue,
446 alreadyMappedOperands, rewriter, accSupport,
447 globalSymbolRegion, symbolTable, config)))
448 return failure();
449 rewriter.eraseOp(launch);
450 }
451
452 rewriter.setInsertionPointAfter(environment);
453 ACCDataCallOptions endOptions;
454 endOptions.callKind = ACCDataCallKind::DataExit;
455 endOptions.flags = static_cast<int64_t>(ACCDataRegionFlags::Implicit);
457 endLoc, RuntimeFunction::ACCRTL_tgt_acc_data_end, mappingOperands,
458 convertedMappingOperands, rewriter, accSupport, globalSymbolRegion,
459 symbolTable, config, {asyncQueue}, endOptions)))
460 return failure();
461
462 spliceConstructRegion(environment, environment.getRegion(), rewriter);
463 rewriter.eraseOp(environment);
464 return success();
465 }
466
467 OpenACCSupport &accSupport;
468 Region &globalSymbolRegion;
469 SymbolTable &symbolTable;
470 ACCRuntimeCallConfig config;
471 DeviceType clauseDeviceType;
472};
473} // namespace
474
477 target.addIllegalOp<KernelEnvironmentOp>();
478}
479
481 RewritePatternSet &patterns,
482 OpenACCSupport &accSupport,
483 Region &globalSymbolRegion,
484 SymbolTable &symbolTable,
485 const ACCRuntimeCallConfig &config,
486 DeviceType clauseDeviceType) {
487 patterns.add<KernelEnvironmentLowering>(converter, accSupport,
488 globalSymbolRegion, symbolTable,
489 config, clauseDeviceType);
490}
static FailureOr< Value > getKernelArgDescriptor(Location loc, Value operand, Value converted, bool alreadyMapped, OpenACCSupport &accSupport, ConversionPatternRewriter &rewriter)
The descriptor of a kernel argument.
static FailureOr< Value > createKernelArgumentStruct(gpu::LaunchFuncOp launch, gpu::LaunchFuncOpAdaptor adaptor, ValueRange alreadyMappedOperands, ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable &symbolTable, const ACCRuntimeCallConfig &config)
static FailureOr< ACCDataRuntimeArgs > emitKernelRuntimeArgs(gpu::LaunchFuncOp launch, gpu::LaunchFuncOpAdaptor adaptor, ValueRange alreadyMappedOperands, ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable &symbolTable, const ACCRuntimeCallConfig &config)
Emits the argument arrays of the kernel launched by launch, one entry per kernel operand.
static void emitHostFallbackNotImplemented(Location loc, Value status, ConversionPatternRewriter &rewriter, Region &globalSymbolRegion, SymbolTable &symbolTable)
The kernel entry point reports a status other than success when the kernel could not run on the devic...
static bool isDevicePtrMapping(Value operand)
static FailureOr< Value > getKernelPointer(gpu::LaunchFuncOp launch, ConversionPatternRewriter &rewriter, Region &globalSymbolRegion, SymbolTable &symbolTable)
static MapFlags getKernelDataClauseMapFlags(Operation *entryOp)
The flags of a data clause operation that maps a kernel argument.
static void declareLibc(SymbolTable &symbolTable, Region &globalSymbolRegion, Location loc, StringRef name, Type result, ArrayRef< Type > arguments)
static bool isDataEntryInsideEnvironment(KernelEnvironmentOp environment, Value operand)
static MapFlags getKernelArgMapFlags(Value operand, bool alreadyMapped, const ACCRuntimeCallConfig &config)
The flags a kernel argument is passed with.
static LogicalResult emitKernelCall(gpu::LaunchFuncOp launch, gpu::LaunchFuncOpAdaptor adaptor, Value asyncQueue, ValueRange alreadyMappedOperands, ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable &symbolTable, const ACCRuntimeCallConfig &config)
return success()
Block represents an ordered list of Operations.
Definition Block.h:34
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Definition Block.cpp:27
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
Definition Pattern.h:233
Conversion from types to the LLVM IR dialect.
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
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:351
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
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
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.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
This class provides an abstraction over the various different ranges of value types.
Definition TypeRange.h:40
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
Configuration for OpenACC to LLVM runtime lowering.
int64_t getDeviceTypeRuntimeValue(DeviceType type) const
int64_t getMapFlagsRuntimeValue(MapFlags flags) const
MapFlags postProcessMapFlags(Operation *mapOp, MapFlags flags) const
Value createKernelBinaryDescriptor(Location loc, OpBuilder &builder) const
InFlightDiagnostic emitNYI(Location loc, const Twine &message)
Report a case that is not yet supported by the implementation.
mlir::Value getVar(mlir::Operation *accDataClauseOp)
Used to obtain the var from a data clause operation.
Definition OpenACC.cpp:5403
std::optional< Location > getMappingExitLoc(ValueRange dataClauseOperands)
Returns where the mappings of dataClauseOperands end, taken from the first of them that says.
std::optional< mlir::acc::DataClause > getDataClause(mlir::Operation *accDataEntryOp)
Used to obtain the dataClause from a data entry operation.
Definition OpenACC.cpp:5522
MapFlags computeDataClauseMapFlags(Operation *entryOp, bool ptrAndObj)
Fold enter (+ paired exit) data-clause semantics into offload map flags.
int64_t getKernelArgumentFieldIndex(KernelArgumentField field)
The index an insert of field addresses.
LLVM::LLVMStructType getKernelArgumentType(MLIRContext *ctx)
The LLVM type of the argument struct passed to __tgt_acc_kernel.
bool isDataEntryOp(mlir::Operation *op)
Used to find out whether op is a data entry operation or an acc.map_info.
Definition OpenACC.cpp:5532
LogicalResult emitWaitClause(OpTy op, DeviceType deviceType, Value asyncQueue, ConversionPatternRewriter &rewriter, OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable &symbolTable, const ACCRuntimeCallConfig &config)
Emits the wait that a wait clause on op asks for before the runtime calls of the construct,...
Value getAsyncQueue(Location loc, Value asyncOperand, bool asyncOnly, OpBuilder &builder, const ACCRuntimeCallConfig &config)
Returns the queue an async clause selects: the value of the clause when it has one,...
Value createIdent(Location loc, StringRef functionName, OpBuilder &builder, Region &globalSymbolRegion, const ACCRuntimeCallConfig &config, SymbolTable *symbolTable=nullptr)
Returns a pointer to a constant global holding an ident_t for OpenACC runtime calls.
bool getImplicitFlag(mlir::Operation *accDataEntryOp)
Used to find out whether data operation is implicit.
Definition OpenACC.cpp:5536
Value remapOrSelf(Value value, ConversionPatternRewriter &rewriter)
Returns the value value was converted to, or value itself when the conversion left it as it was.
Value constantI64(Location loc, int64_t value, OpBuilder &builder)
Creates an i64 constant.
std::string getInternalGlobalName(StringRef kind, StringRef detail)
Returns the name to give a global that the conversion creates to hold detail of kind,...
StringRef getParentFunctionName(Operation *op)
Returns the symbol name of the function op belongs to, or of op itself when it is a function.
Value castToI64(Location loc, Value value, OpBuilder &builder)
Sign-extends or truncates value to the i64 the runtime entry points take for values like queue number...
Value getOrCreateGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Region &globalSymbolRegion, SymbolTable *symbolTable=nullptr)
Creates or reuses a null-terminated string global in globalSymbolRegion.
std::optional< MapFlags > getMapFlags(Operation *mapEntryOp)
Returns offload map-type flags from acc.map_info, if present.
KernelArgumentField
Fields of the argument struct passed to __tgt_acc_kernel, in declaration order.
bool hasAttachPoint(Operation *mapEntryOp)
Returns true when mapEntryOp carries an attach point (varPtrPtr).
void spliceConstructRegion(Operation *op, Region &region, RewriterBase &rewriter)
Splices region, the body of a structured construct, into the block holding op, so that the construct ...
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 ...
std::optional< TypeSizeAndAlignment > getTypeSizeAndAlignment(Type ty, ModuleOp module, const DataLayout &dl, OpenACCSupport *support=nullptr, Value var={})
Returns the size and ABI alignment in bytes.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:734
Include the generated interface declarations.
void configureACCKernelLaunchConversionLegality(ConversionTarget &target)
Configure conversion legality for acc.kernel_environment.
Value createACCMappedObjectName(Location loc, Value operand, acc::OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable *symbolTable, ConversionPatternRewriter &rewriter)
The name of operand for runtime diagnostics, or a null pointer when it has none.
void createACCMappedObjectArrays(Location loc, ArrayRef< ACCMappedObjectArgs > objects, ACCDataRuntimeArgs &runtimeArgs, RewriterBase &rewriter)
Materialize the argument arrays of objects into the argNum through argDescs fields of runtimeArgs.
FailureOr< SmallVector< Value > > emitACCDataRuntimeCall(Location loc, acc::RuntimeFunction fn, ValueRange mappingOperands, ValueRange convertedOperands, ConversionPatternRewriter &rewriter, acc::OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable &symbolTable, const acc::ACCRuntimeCallConfig &config, ArrayRef< Value > trailingArguments, const ACCDataCallOptions &options={})
Emit the call to the mapping entry point fn for mappingOperands, followed by trailingArguments.
FailureOr< Value > createACCMappedObjectSize(Location loc, Value operand, Value converted, acc::MapFlags mapFlags, acc::OpenACCSupport &accSupport, ConversionPatternRewriter &rewriter)
The size in bytes of operand, or zero where its descriptor or bounds state the extent instead.
Value createACCMappedObjectBase(Location loc, Operation *mapOp, acc::MapFlags mapFlags, ConversionPatternRewriter &rewriter)
The host pointer slot the object mapOp maps is attached to, or a null pointer when it is not attached...
Value createACCArgumentDescriptor(Operation *mapOp, Value convertedOperand, acc::OpenACCSupport &accSupport, ConversionPatternRewriter &rewriter)
Build the runtime argument descriptor for mapOp, or a null pointer when the mapping needs no descript...
Value createACCMappedObjectPointer(Location loc, Value operand, Value converted, acc::MapFlags mapFlags, ConversionPatternRewriter &rewriter)
The address of operand as the runtime expects to receive it, given its type converted value converted...
void populateACCKernelLaunchPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns, acc::OpenACCSupport &accSupport, Region &globalSymbolRegion, SymbolTable &symbolTable, const acc::ACCRuntimeCallConfig &config={}, acc::DeviceType clauseDeviceType=acc::DeviceType::None)
Populate patterns that lower an acc.kernel_environment and all gpu.launch_func operations in its body...
Value createACCMemRefDescriptorWrapperArg(Location loc, MemRefType memrefType, Value convertedMemref, ValueRange bounds, Value elementSize, ConversionPatternRewriter &rewriter)
Build the runtime argument descriptor wrapping an already converted memref.
@ None
An explicit data construct.
int64_t flags
Region flags, in the encoding of ACCDataRegionFlags.
ValueRange returnAddressOperands
Mapping operands whose device address the entry point returns.
The arguments every mapping entry point of the OpenACC runtime takes, in the order they are passed.
Value argNames
Array of variable names for runtime diagnostics, null where unknown.
Value argSizes
Array of object sizes in bytes; zero where the descriptor or the bounds state the extent instead.
Value argMappers
Array of user-defined mappers. OpenACC has none, so this is always null.
Value argTypes
Array of map-type flags, in the runtime encoding of acc::MapFlags.
Value argBasePtrs
Array of pointer slots to attach a mapped object to, null when the object is not attached to anything...
Value argNum
Number of mapped objects, that is, the length of each array below.
Value argDescs
Array of descriptors stating layout and bounds, null for whole objects of a known size.
Value argPtrs
Array of addresses of the mapped objects themselves.
The values that describe one object to the runtime, one for each argument array.