MLIR 24.0.0git
ACCDataRuntime.cpp
Go to the documentation of this file.
1//===- ACCDataRuntime.cpp - Emit OpenACC data runtime arguments -*- 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// Builds the mapping argument arrays used by OpenACC data runtime entry points.
10//
11//===----------------------------------------------------------------------===//
12
15
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SmallVectorExtras.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/raw_ostream.h"
27
28#include <algorithm>
29
30#define DEBUG_TYPE "acc-data-runtime"
31
32using namespace mlir;
33using namespace mlir::acc;
34
35static Value getPointer(Location loc, Value value,
36 ConversionPatternRewriter &rewriter) {
37 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
38 if (!value)
39 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
40 if (value.getType() == ptrTy)
41 return value;
42
43 if (isa<PointerLikeType>(value.getType()))
44 return castPointerLikeTypeIfNeeded(rewriter, loc, value, ptrTy);
45
46 Value one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
47 Value storage =
48 LLVM::AllocaOp::create(rewriter, loc, ptrTy, value.getType(), one);
49 LLVM::StoreOp::create(rewriter, loc, value, storage);
50 return storage;
51}
52
53/// Returns the address of a slot holding \p value, so that the runtime reads
54/// the value from memory rather than receiving it directly.
56 ConversionPatternRewriter &rewriter) {
57 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
58 Value one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
59 Value storage =
60 LLVM::AllocaOp::create(rewriter, loc, ptrTy, value.getType(), one);
61 LLVM::StoreOp::create(rewriter, loc, value, storage);
62 return storage;
63}
64
66 ArrayRef<Value> values, RewriterBase &rewriter) {
67 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
68 Type i32Ty = rewriter.getI32Type();
69 Value count = LLVM::ConstantOp::create(rewriter, loc, i32Ty, values.size());
70 Value array =
71 LLVM::AllocaOp::create(rewriter, loc, ptrTy, elementType, count);
72 for (auto [index, value] : llvm::enumerate(values)) {
73 Value indexValue = LLVM::ConstantOp::create(rewriter, loc, i32Ty, index);
74 Value element = LLVM::GEPOp::create(rewriter, loc, ptrTy, elementType,
75 array, ValueRange{indexValue});
76 LLVM::StoreOp::create(rewriter, loc, value, element);
77 }
78 return array;
79}
80
83 ACCDataRuntimeArgs &runtimeArgs,
84 RewriterBase &rewriter) {
85 Type i32Ty = rewriter.getI32Type();
86 Type i64Ty = rewriter.getI64Type();
87 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
88 auto createArray = [&](Type elementType, Value ACCMappedObjectArgs::*field) {
89 SmallVector<Value> values =
90 llvm::map_to_vector(objects, [&](const ACCMappedObjectArgs &object) {
91 return object.*field;
92 });
93 return createACCDataArray(loc, elementType, values, rewriter);
94 };
95 // The data-call emitter states the count before the object values.
96 if (!runtimeArgs.argNum)
97 runtimeArgs.argNum =
98 LLVM::ConstantOp::create(rewriter, loc, i32Ty, objects.size());
99 runtimeArgs.argBasePtrs = createArray(ptrTy, &ACCMappedObjectArgs::base);
100 runtimeArgs.argPtrs = createArray(ptrTy, &ACCMappedObjectArgs::pointer);
101 runtimeArgs.argSizes = createArray(i64Ty, &ACCMappedObjectArgs::size);
102 runtimeArgs.argTypes = createArray(i64Ty, &ACCMappedObjectArgs::type);
103 runtimeArgs.argNames = createArray(ptrTy, &ACCMappedObjectArgs::name);
104 if (!runtimeArgs.argMappers)
105 runtimeArgs.argMappers = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
106 runtimeArgs.argDescs = createArray(ptrTy, &ACCMappedObjectArgs::descriptor);
107}
108
109/// Privatized storage only ever exists on the device, so there is no host
110/// address to give. A device address names storage the runtime must not look
111/// up, and an object mapped by value has no address at all, so both are handed
112/// over in a slot the runtime reads them from. A pointer that no clause maps
113/// but the device can already access is a device address as well.
115 Value converted, MapFlags mapFlags,
116 ConversionPatternRewriter &rewriter) {
117 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
118 if (isa<PrivateType>(operand.getType()))
119 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
120 if (converted && converted.getType() == ptrTy &&
121 (bitEnumContainsAny(mapFlags, MapFlags::devptr) ||
122 (!isDataEntryOp(operand.getDefiningOp()) &&
123 isDeviceAccessibleValue(operand))))
124 return getIndirectPointer(loc, converted, rewriter);
125 return getPointer(loc, converted, rewriter);
126}
127
129 MapFlags mapFlags,
130 ConversionPatternRewriter &rewriter) {
131 Value base;
132 if (mapOp) {
133 if (Value attach = acc::getVarPtrPtr(mapOp))
134 base = remapOrSelf(attach, rewriter);
135 else if (bitEnumContainsAny(mapFlags, MapFlags::ptr_and_obj))
136 base = remapOrSelf(acc::getDesc(mapOp), rewriter);
137 }
138 return getPointer(loc, base, rewriter);
139}
140
142 OpenACCSupport &accSupport,
143 Region &globalSymbolRegion,
144 SymbolTable *symbolTable,
145 ConversionPatternRewriter &rewriter) {
146 // The runtime resolves an object that lives on the device against the
147 // symbols of the binary by this name, so it is the name the object is
148 // emitted under rather than the one the source spells.
149 VariableNameConfig nameConfig;
150 nameConfig.preferDemangledName = false;
151 std::string name = accSupport.getVariableName(operand, nameConfig);
152 if (name.empty())
153 return LLVM::ZeroOp::create(
154 rewriter, loc, LLVM::LLVMPointerType::get(rewriter.getContext()));
155 return getOrCreateGlobalString(loc, rewriter,
156 getInternalGlobalName("var_name", name), name,
157 globalSymbolRegion, symbolTable);
158}
159
160static std::optional<MapFlags> computePackedMapFlags(Operation *mapOp) {
161 if (auto mapInfo = dyn_cast<MapInfoOp>(mapOp))
162 return mapInfo.getMapFlags();
163 if (isa<ACC_DATA_ENTRY_OPS>(mapOp))
164 return computeDataClauseMapFlags(mapOp, hasAttachPoint(mapOp));
165 return std::nullopt;
166}
167
168FailureOr<Value>
170 MapFlags mapFlags, OpenACCSupport &accSupport,
171 ConversionPatternRewriter &rewriter) {
172 Operation *scope = rewriter.getInsertionBlock()->getParentOp();
173 auto module = dyn_cast<ModuleOp>(scope);
174 if (!module)
175 module = scope->getParentOfType<ModuleOp>();
176 // An object mapped by value is passed as the argument itself, so its size is
177 // the size of what is passed and not of the object it was read from. The two
178 // differ when the argument holds one field of a decomposed aggregate.
179 if (bitEnumContainsAny(mapFlags, MapFlags::literal) && converted) {
180 auto sizeAndAlignment =
181 acc::getTypeSizeAndAlignment(converted.getType(), module, &accSupport);
182 if (!sizeAndAlignment) {
183 std::string message;
184 llvm::raw_string_ostream os(message);
185 os << "unhandled type size computation for type: " << converted.getType();
186 (void)accSupport.emitNYI(loc, message);
187 return failure();
188 }
189 return constantI64(loc, sizeAndAlignment->first.getFixedValue(), rewriter);
190 }
191 Operation *mapOp = operand.getDefiningOp();
192 if (!isDataEntryOp(mapOp))
193 return constantI64(loc, 0, rewriter);
194 if (Value size = acc::getMapSize(mapOp))
195 return castToI64(loc, remapOrSelf(size, rewriter), rewriter);
196
197 Value var = acc::getVar(mapOp);
198 if (!var)
199 return constantI64(loc, 0, rewriter);
200 Type varType = acc::getVarType(mapOp);
201 if (!varType)
202 varType = var.getType();
203 // A memref is handed over with a descriptor stating its extents and element
204 // size, which is what states the size of such a mapping.
205 if (isa<MemRefType>(var.getType()) || isa<MemRefType>(varType))
206 return constantI64(loc, 0, rewriter);
207
208 // A data clause operation that was not turned into an `acc.map_info` has no
209 // size of its own, so it is sized the way that operation would have been.
210 // A size that is not statically known is left to the runtime, as an unsized
211 // mapping is.
212 int64_t size =
214 acc::getBounds(mapOp), &accSupport);
215 return constantI64(loc, std::max<int64_t>(size, 0), rewriter);
216}
217
218static Value getElementSize(Operation *mapOp, OpenACCSupport &accSupport,
219 ConversionPatternRewriter &rewriter) {
220 Location loc = mapOp->getLoc();
221 ModuleOp module = mapOp->getParentOfType<ModuleOp>();
222 if (std::optional<int64_t> size = acc::getMapElementSize(mapOp))
223 return constantI64(loc, *size, rewriter);
224
225 Type type = acc::getVarType(mapOp);
226 if (auto shaped = dyn_cast<ShapedType>(type))
227 type = shaped.getElementType();
228 if (!type)
229 return constantI64(loc, 0, rewriter);
230 if (auto sizeAndAlignment =
231 acc::getTypeSizeAndAlignment(type, module, &accSupport))
232 return constantI64(loc, sizeAndAlignment->first.getFixedValue(), rewriter);
233 return constantI64(loc, 0, rewriter);
234}
235
237 ConversionPatternRewriter &rewriter) {
238 if (!value)
239 return constantI64(loc, 0, rewriter);
240 return castToI64(loc, remapOrSelf(value, rewriter), rewriter);
241}
242
244 Type baseDescriptorType, uint32_t version,
245 ValueRange bounds, Value elementSize,
246 ConversionPatternRewriter &rewriter) {
247 MLIRContext *context = rewriter.getContext();
248 Type i8Ty = rewriter.getI8Type();
249 Type i32Ty = rewriter.getI32Type();
250 Type i64Ty = rewriter.getI64Type();
251 Type ptrTy = LLVM::LLVMPointerType::get(context);
252
253 Value versionValue = LLVM::ConstantOp::create(
254 rewriter, loc, i32Ty,
255 version | static_cast<uint32_t>(
256 getDataDescriptorKind(DataDescriptor::AccDataDescOpenACC)));
257 baseDescriptor = LLVM::InsertValueOp::create(
258 rewriter, loc, baseDescriptorType, baseDescriptor, versionValue,
260
261 Type descriptorType = getDataDescriptorType(
262 context, DataDescriptor::AccDataDescOpenACC, baseDescriptorType);
263 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
264 Value rank = LLVM::ConstantOp::create(rewriter, loc, i8Ty, bounds.size());
265
266 SmallVector<Value> lowerBounds;
267 SmallVector<Value> upperBounds;
268 SmallVector<Value> extents;
269 SmallVector<Value> strides;
270 SmallVector<Value> starts;
271 for (Value boundValue : bounds) {
272 auto bound = cast<DataBoundsOp>(boundValue.getDefiningOp());
273 lowerBounds.push_back(
274 getBoundValue(bound.getLowerbound(), bound.getLoc(), rewriter));
275 upperBounds.push_back(
276 getBoundValue(bound.getUpperbound(), bound.getLoc(), rewriter));
277 Value sourceExtent =
278 bound.getSourceExtent() ? bound.getSourceExtent() : bound.getExtent();
279 extents.push_back(getBoundValue(sourceExtent, bound.getLoc(), rewriter));
280 Value stride = getBoundValue(bound.getStride(), bound.getLoc(), rewriter);
281 if (!bound.getStrideInBytes())
282 stride =
283 LLVM::MulOp::create(rewriter, bound.getLoc(), stride, elementSize);
284 strides.push_back(stride);
285 starts.push_back(
286 getBoundValue(bound.getStartIdx(), bound.getLoc(), rewriter));
287 }
288
289 Value lowerBoundsArray =
290 createACCDataArray(loc, i64Ty, lowerBounds, rewriter);
291 Value upperBoundsArray =
292 createACCDataArray(loc, i64Ty, upperBounds, rewriter);
293 Value extentsArray = createACCDataArray(loc, i64Ty, extents, rewriter);
294 Value stridesArray = createACCDataArray(loc, i64Ty, strides, rewriter);
295 Value startsArray = createACCDataArray(loc, i64Ty, starts, rewriter);
296
297 using Field = AccDataDescOpenACCField;
298 auto insert = [&](Value value, Field field) {
299 descriptor = LLVM::InsertValueOp::create(
300 rewriter, loc, descriptorType, descriptor, value,
302 };
303 insert(baseDescriptor, Field::Base);
304 insert(rank, Field::Rank);
305 insert(elementSize, Field::ElementSize);
306 insert(lowerBoundsArray, Field::LowerBounds);
307 insert(upperBoundsArray, Field::UpperBounds);
308 insert(extentsArray, Field::Extents);
309 insert(stridesArray, Field::StridesInBytes);
310 insert(startsArray, Field::StartIndices);
311
312 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
313 Value storage =
314 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
315 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
316 return storage;
317}
318
320 Location loc, MemRefType memrefType, Value convertedMemref,
321 ValueRange bounds, Value elementSize, ConversionPatternRewriter &rewriter) {
322 MLIRContext *context = rewriter.getContext();
323 Type i8Ty = rewriter.getI8Type();
324 Type i32Ty = rewriter.getI32Type();
325 Type ptrTy = LLVM::LLVMPointerType::get(context);
326 using Field = AccDataDescMemRefField;
327 Type descriptorType =
328 getDataDescriptorType(context, DataDescriptor::AccDataDescMemRef);
329 auto version = static_cast<uint32_t>(
330 getDataDescriptorKind(DataDescriptor::AccDataDescMemRef));
331 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
332 Value rank =
333 LLVM::ConstantOp::create(rewriter, loc, i8Ty, memrefType.getRank());
334 auto insert = [&](Value value, Field field) {
335 descriptor = LLVM::InsertValueOp::create(
336 rewriter, loc, descriptorType, descriptor, value,
338 };
339 insert(rank, Field::Rank);
340 insert(elementSize, Field::ElementSize);
341 insert(getPointer(loc, convertedMemref, rewriter), Field::MemRefDescriptor);
342 if (!bounds.empty())
343 return createACCDataDescriptor(loc, descriptor, descriptorType, version,
344 bounds, elementSize, rewriter);
345
346 insert(LLVM::ConstantOp::create(rewriter, loc, i32Ty, version),
347 Field::Version);
348 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
349 Value storage =
350 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
351 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
352 return storage;
353}
354
356 Value convertedOperand,
357 OpenACCSupport &accSupport,
358 ConversionPatternRewriter &rewriter) {
359 Location loc = mapOp->getLoc();
360 MLIRContext *context = rewriter.getContext();
361 Type i32Ty = rewriter.getI32Type();
362 Type ptrTy = LLVM::LLVMPointerType::get(context);
363 SmallVector<Value> bounds = acc::getBounds(mapOp);
364 DataDescKind descKind = acc::getDataDescKind(mapOp);
365 // Only a descriptor stating bounds reads the element size, so it is
366 // materialized where it is used, leaving no constant behind for a mapping
367 // that needs no descriptor at all.
368 auto elementSize = [&] {
369 return getElementSize(mapOp, accSupport, rewriter);
370 };
371
372 Value var = acc::getVar(mapOp);
373 if (var && isa<MemRefType>(var.getType())) {
374 auto memrefType = cast<MemRefType>(var.getType());
376 loc, memrefType, convertedOperand, bounds, elementSize(), rewriter);
377 }
378
379 if (bitEnumContainsAny(descKind, DataDescKind::cfi)) {
380 using Field = AccDataDescCFIField;
381 Type descriptorType =
382 getDataDescriptorType(context, DataDescriptor::AccDataDescCFI);
383 auto version = static_cast<uint32_t>(
384 getDataDescriptorKind(DataDescriptor::AccDataDescCFI));
385 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
386 Value descriptorStorage = remapOrSelf(acc::getDesc(mapOp), rewriter);
387 if (!descriptorStorage)
388 descriptorStorage = convertedOperand;
389 descriptor = LLVM::InsertValueOp::create(
390 rewriter, loc, descriptorType, descriptor,
391 getPointer(loc, descriptorStorage, rewriter),
392 ArrayRef<int64_t>{getDataDescriptorFieldIndex(Field::CFIDescriptor)});
393 if (!bounds.empty())
394 return createACCDataDescriptor(loc, descriptor, descriptorType, version,
395 bounds, elementSize(), rewriter);
396
397 Value versionValue =
398 LLVM::ConstantOp::create(rewriter, loc, i32Ty, version);
399 descriptor = LLVM::InsertValueOp::create(
400 rewriter, loc, descriptorType, descriptor, versionValue,
402 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
403 Value storage =
404 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
405 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
406 return storage;
407 }
408
409 if (!bounds.empty()) {
410 Type descriptorType =
411 getDataDescriptorType(context, DataDescriptor::AccDataDescGeneric);
412 auto version = static_cast<uint32_t>(
413 getDataDescriptorKind(DataDescriptor::AccDataDescGeneric));
414 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
415 return createACCDataDescriptor(loc, descriptor, descriptorType, version,
416 bounds, elementSize(), rewriter);
417 }
418 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
419}
420
425
427 Location loc, ValueRange mappingOperands, ValueRange convertedOperands,
428 ConversionPatternRewriter &rewriter, Region &globalSymbolRegion,
429 acc::OpenACCSupport &accSupport, const acc::ACCRuntimeCallConfig &config,
430 ACCDataRuntimeArgs &runtimeArgs, const ACCDataCallOptions &options,
431 SymbolTable *symbolTable) {
432 if (mappingOperands.size() != convertedOperands.size())
433 return failure();
434
435 runtimeArgs.ident =
436 createIdent(loc, getParentFunctionName(mappingOperands), rewriter,
437 globalSymbolRegion, config, symbolTable);
438 runtimeArgs.flags = constantI64(loc, options.flags, rewriter);
439 runtimeArgs.deviceType = constantI64(
440 loc, config.getDeviceTypeRuntimeValue(DeviceType::None), rewriter);
441 runtimeArgs.argMappers = LLVM::ZeroOp::create(
442 rewriter, loc, LLVM::LLVMPointerType::get(rewriter.getContext()));
443
444 // An aggregate passed by value is decomposed into one argument per field by
445 // the target ABI, so the runtime is told about one object per field as well.
446 // Each of them keeps the map entry of the aggregate it came from. The device
447 // address of an aggregate is returned in the slot of its first field.
448 struct MappedObject {
449 Value operand;
450 Value converted;
451 bool firstField;
452 };
453 SmallVector<MappedObject> mappedObjects;
454 for (auto [operand, converted] :
455 llvm::zip_equal(mappingOperands, convertedOperands)) {
456 auto structType = dyn_cast<LLVM::LLVMStructType>(converted.getType());
457 if (structType && !structType.isIdentified() &&
458 structType.getBody().size() > 1) {
459 for (unsigned field = 0, fields = structType.getBody().size();
460 field != fields; ++field)
461 mappedObjects.push_back(
462 {operand,
463 LLVM::ExtractValueOp::create(rewriter, loc, converted, field),
464 field == 0});
465 continue;
466 }
467 mappedObjects.push_back({operand, converted, true});
468 }
469
470 // The count precedes the values of the objects, which is where a decomposed
471 // aggregate states how many fields it became.
472 runtimeArgs.argNum = LLVM::ConstantOp::create(
473 rewriter, loc, rewriter.getI32Type(), mappedObjects.size());
474
475 constexpr unsigned noSlot = ~0u;
476 runtimeArgs.returnAddressSlots.assign(options.returnAddressOperands.size(),
477 noSlot);
479 for (auto [slot, object] : llvm::enumerate(mappedObjects)) {
480 auto [operand, converted, firstField] = object;
481 Operation *mapOp = operand.getDefiningOp();
482 if (!isDataEntryOp(mapOp))
483 return failure();
484 std::optional<MapFlags> mapFlags = computePackedMapFlags(mapOp);
485 if (!mapFlags)
486 return failure();
487 *mapFlags = config.postProcessMapFlags(mapOp, *mapFlags);
488 LLVM_DEBUG(llvm::dbgs() << "mapping " << *mapOp << "\n as "
489 << config.formatMapFlags(*mapFlags) << "\n");
490
491 Location mapLoc = mapOp->getLoc();
493 args.pointer = createACCMappedObjectPointer(mapLoc, operand, converted,
494 *mapFlags, rewriter);
495 // An object that only lives on the device has no host address to state as
496 // its base.
497 args.base =
498 bitEnumContainsAny(*mapFlags, MapFlags::device_resident)
499 ? getPointer(mapLoc, Value(), rewriter)
500 : createACCMappedObjectBase(mapLoc, mapOp, *mapFlags, rewriter);
501
502 // A local object that lives on the device is torn down when the region
503 // that declared it ends, which the runtime only does for a mapping that
504 // states it is deleted.
505 if (options.callKind == ACCDataCallKind::DataExit &&
506 bitEnumContainsAny(*mapFlags, MapFlags::device_resident)) {
507 Value var = acc::getVar(mapOp);
508 if (var &&
509 !isa_and_nonnull<AddressOfGlobalOpInterface>(var.getDefiningOp()))
510 *mapFlags = *mapFlags | MapFlags::delete_;
511 }
512
513 if (firstField) {
514 for (auto [index, returned] :
515 llvm::enumerate(options.returnAddressOperands)) {
516 if (returned != operand)
517 continue;
518 *mapFlags = *mapFlags | MapFlags::return_param;
519 runtimeArgs.returnAddressSlots[index] = slot;
520 }
521 }
522 int64_t mapType = config.getMapFlagsRuntimeValue(*mapFlags);
523
524 FailureOr<Value> size = createACCMappedObjectSize(
525 mapLoc, operand, converted, *mapFlags, accSupport, rewriter);
526 if (failed(size))
527 return failure();
528 args.size = *size;
529 args.type = constantI64(mapLoc, mapType, rewriter);
531 mapLoc, operand, accSupport, globalSymbolRegion, symbolTable, rewriter);
532 args.descriptor =
533 createACCArgumentDescriptor(mapOp, converted, accSupport, rewriter);
534 objects.push_back(args);
535 }
536 if (llvm::is_contained(runtimeArgs.returnAddressSlots, noSlot))
537 return failure();
538
539 createACCMappedObjectArrays(loc, objects, runtimeArgs, rewriter);
540 return success();
541}
542
543FailureOr<SmallVector<Value>> mlir::emitACCDataRuntimeCall(
544 Location loc, RuntimeFunction fn, ValueRange mappingOperands,
545 ValueRange convertedOperands, ConversionPatternRewriter &rewriter,
546 OpenACCSupport &accSupport, Region &globalSymbolRegion,
547 SymbolTable &symbolTable, const ACCRuntimeCallConfig &config,
548 ArrayRef<Value> trailingArguments, const ACCDataCallOptions &options) {
549 SmallVector<Value> returnedAddresses;
550 if (mappingOperands.empty())
551 return returnedAddresses;
552
553 ACCDataRuntimeArgs runtimeArgs;
554 if (failed(emitACCDataRuntimeArgs(
555 loc, mappingOperands, convertedOperands, rewriter, globalSymbolRegion,
556 accSupport, config, runtimeArgs, options, &symbolTable)))
557 return rewriter.notifyMatchFailure(
558 mappingOperands.front().getDefiningOp(),
559 "unsupported OpenACC data-clause operand");
560
561 SmallVector<Value> arguments = runtimeArgs.getCallArgs();
562 arguments.append(trailingArguments.begin(), trailingArguments.end());
563 if (failed(createRuntimeCall(loc, rewriter, globalSymbolRegion, symbolTable,
564 fn, config, arguments)))
565 return failure();
566
567 Type i32Ty = rewriter.getI32Type();
568 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
569 for (unsigned slot : runtimeArgs.returnAddressSlots) {
570 Value index = LLVM::ConstantOp::create(rewriter, loc, i32Ty, slot);
571 Value element =
572 LLVM::GEPOp::create(rewriter, loc, ptrTy, ptrTy,
573 runtimeArgs.argBasePtrs, ValueRange{index});
574 returnedAddresses.push_back(
575 LLVM::LoadOp::create(rewriter, loc, ptrTy, element));
576 }
577 return returnedAddresses;
578}
static std::optional< MapFlags > computePackedMapFlags(Operation *mapOp)
static Value getBoundValue(Value value, Location loc, ConversionPatternRewriter &rewriter)
static Value getElementSize(Operation *mapOp, OpenACCSupport &accSupport, ConversionPatternRewriter &rewriter)
static Value getPointer(Location loc, Value value, ConversionPatternRewriter &rewriter)
static Value getIndirectPointer(Location loc, Value value, ConversionPatternRewriter &rewriter)
Returns the address of a slot holding value, so that the runtime reads the value from memory rather t...
return success()
static llvm::ManagedStatic< PassManagerOptions > options
IntegerType getI64Type()
Definition Builders.cpp:73
IntegerType getI32Type()
Definition Builders.cpp:71
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
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
Location getLoc()
The source location the operation was defined or derived from.
Definition Operation.h:240
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition Operation.h:255
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Definition SymbolTable.h:25
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
Location getLoc() const
Return the location of this value.
Definition Value.cpp:24
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.
std::string formatMapFlags(MapFlags flags) const
Renders flags for a diagnostic as the names of the set bits and the decimal and hexadecimal encoding ...
int64_t getDeviceTypeRuntimeValue(DeviceType type) const
int64_t getMapFlagsRuntimeValue(MapFlags flags) const
MapFlags postProcessMapFlags(Operation *mapOp, MapFlags flags) const
std::string getVariableName(Value v, VariableNameConfig config={})
Get the variable name for a given value.
InFlightDiagnostic emitNYI(Location loc, const Twine &message)
Report a case that is not yet supported by the implementation.
std::optional< int64_t > getMapElementSize(Operation *mapEntryOp)
Returns element size in bytes from acc.map_info, if present.
mlir::Value getVar(mlir::Operation *accDataClauseOp)
Used to obtain the var from a data clause operation.
Definition OpenACC.cpp:5403
MapFlags computeDataClauseMapFlags(Operation *entryOp, bool ptrAndObj)
Fold enter (+ paired exit) data-clause semantics into offload map flags.
mlir::SmallVector< mlir::Value > getBounds(mlir::Operation *accDataClauseOp)
Used to obtain bounds from an acc data clause operation.
Definition OpenACC.cpp:5454
LLVM::LLVMStructType getDataDescriptorType(MLIRContext *ctx, DataDescriptor desc, Type baseType={})
Builds the LLVM type of desc in ctx.
Value getMapSize(Operation *mapEntryOp)
Returns the optional size operand from acc.map_info, or null.
DataDescKind getDataDescriptorKind(DataDescriptor desc)
Returns the descriptor kind the runtime reads from the version field of desc.
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
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.
Value castPointerLikeTypeIfNeeded(OpBuilder &builder, Location loc, Value value, Type resultType)
Cast value to resultType via PointerLikeType::genCast when needed.
DataDescKind getDataDescKind(Operation *mapEntryOp)
Returns descriptor kind from acc.map_info, or none for other ops.
Value remapOrSelf(Value value, ConversionPatternRewriter &rewriter)
Returns the value value was converted to, or value itself when the conversion left it as it was.
RuntimeFunction
IDs for OpenACC compiler-to-runtime entry points (__tgt_acc_*).
Value getDesc(Operation *mapEntryOp)
Returns descriptor value from acc.map_info.
Value constantI64(Location loc, int64_t value, OpBuilder &builder)
Creates an i64 constant.
mlir::Value getVarPtrPtr(mlir::Operation *accDataClauseOp)
Used to obtain the varPtrPtr from a data clause operation.
Definition OpenACC.cpp:5444
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.
bool isDeviceAccessibleValue(mlir::Value val)
Check if a value represents device data.
int64_t getDataDescriptorFieldIndex(FieldEnum field)
The index an insert or extract of field addresses.
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...
mlir::Type getVarType(mlir::Operation *accDataClauseOp)
Used to obtains the varType from a data clause operation which records the type of variable.
Definition OpenACC.cpp:5411
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.
int64_t computeMapInfoSizeBytes(Value var, Type varType, DataDescKind descKind, ValueRange bounds, const DataLayout &dataLayout, OpenACCSupport *support=nullptr)
Compute total mapped byte size for acc.map_info.
bool hasAttachPoint(Operation *mapEntryOp)
Returns true when mapEntryOp carries an attach point (varPtrPtr).
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.
Include the generated interface declarations.
Value createACCDataArray(Location loc, Type elementType, ArrayRef< Value > values, RewriterBase &rewriter)
Materialize values as a stack-allocated LLVM array.
Value createACCDataDescriptor(Location loc, Value baseDescriptor, Type baseDescriptorType, uint32_t version, ValueRange bounds, Value elementSize, ConversionPatternRewriter &rewriter)
Wrap baseDescriptor in the OpenACC overlay that carries bounds.
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.
LogicalResult emitACCDataRuntimeArgs(Location loc, ValueRange mappingOperands, ValueRange convertedOperands, ConversionPatternRewriter &rewriter, Region &globalSymbolRegion, acc::OpenACCSupport &accSupport, const acc::ACCRuntimeCallConfig &config, ACCDataRuntimeArgs &runtimeArgs, const ACCDataCallOptions &options={}, SymbolTable *symbolTable=nullptr)
Emit the OpenACC data runtime arguments for data-clause operands.
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...
Value createACCMemRefDescriptorWrapperArg(Location loc, MemRefType memrefType, Value convertedMemref, ValueRange bounds, Value elementSize, ConversionPatternRewriter &rewriter)
Build the runtime argument descriptor wrapping an already converted memref.
What a data runtime call is asked for besides mapping its operands.
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 deviceType
Device type the directive applies to, in the runtime encoding.
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 ident
Source position and enclosing function name of the directive.
Value argTypes
Array of map-type flags, in the runtime encoding of acc::MapFlags.
SmallVector< Value > getCallArgs() const
Returns the fields above in the order the entry points take them, so that a caller only appends the a...
SmallVector< unsigned > returnAddressSlots
The argBasePtrs slot the entry point writes the device address of each requested operand into,...
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 flags
Region flags, in the encoding of ACCDataRegionFlags.
Value argPtrs
Array of addresses of the mapped objects themselves.
The values that describe one object to the runtime, one for each argument array.
How the name of a variable is to be rendered.
bool preferDemangledName
Render the name the source language spells, which is the name a message to the user states.