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"
30#define DEBUG_TYPE "acc-data-runtime"
36 ConversionPatternRewriter &rewriter) {
37 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
39 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
43 if (isa<PointerLikeType>(value.
getType()))
46 Value one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
48 LLVM::AllocaOp::create(rewriter, loc, ptrTy, value.
getType(), one);
49 LLVM::StoreOp::create(rewriter, loc, value, storage);
56 ConversionPatternRewriter &rewriter) {
57 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
58 Value one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
60 LLVM::AllocaOp::create(rewriter, loc, ptrTy, value.
getType(), one);
61 LLVM::StoreOp::create(rewriter, loc, value, storage);
69 Value count = LLVM::ConstantOp::create(rewriter, loc, i32Ty, values.size());
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,
76 LLVM::StoreOp::create(rewriter, loc, value, element);
98 LLVM::ConstantOp::create(rewriter, loc, i32Ty, objects.size());
105 runtimeArgs.
argMappers = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
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) ||
130 ConversionPatternRewriter &rewriter) {
135 else if (bitEnumContainsAny(mapFlags, MapFlags::ptr_and_obj))
143 Region &globalSymbolRegion,
145 ConversionPatternRewriter &rewriter) {
153 return LLVM::ZeroOp::create(
154 rewriter, loc, LLVM::LLVMPointerType::get(rewriter.getContext()));
157 globalSymbolRegion, symbolTable);
161 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapOp))
162 return mapInfo.getMapFlags();
163 if (isa<ACC_DATA_ENTRY_OPS>(mapOp))
171 ConversionPatternRewriter &rewriter) {
172 Operation *scope = rewriter.getInsertionBlock()->getParentOp();
173 auto module = dyn_cast<ModuleOp>(scope);
175 module = scope->getParentOfType<ModuleOp>();
179 if (bitEnumContainsAny(mapFlags, MapFlags::literal) && converted) {
180 auto sizeAndAlignment =
182 if (!sizeAndAlignment) {
184 llvm::raw_string_ostream os(message);
185 os <<
"unhandled type size computation for type: " << converted.
getType();
189 return constantI64(loc, sizeAndAlignment->first.getFixedValue(), rewriter);
205 if (isa<MemRefType>(var.
getType()) || isa<MemRefType>(varType))
215 return constantI64(loc, std::max<int64_t>(size, 0), rewriter);
219 ConversionPatternRewriter &rewriter) {
226 if (
auto shaped = dyn_cast<ShapedType>(type))
227 type = shaped.getElementType();
230 if (
auto sizeAndAlignment =
232 return constantI64(loc, sizeAndAlignment->first.getFixedValue(), rewriter);
237 ConversionPatternRewriter &rewriter) {
244 Type baseDescriptorType, uint32_t version,
246 ConversionPatternRewriter &rewriter) {
248 Type i8Ty = rewriter.getI8Type();
249 Type i32Ty = rewriter.getI32Type();
250 Type i64Ty = rewriter.getI64Type();
251 Type ptrTy = LLVM::LLVMPointerType::get(context);
253 Value versionValue = LLVM::ConstantOp::create(
254 rewriter, loc, i32Ty,
255 version |
static_cast<uint32_t
>(
257 baseDescriptor = LLVM::InsertValueOp::create(
258 rewriter, loc, baseDescriptorType, baseDescriptor, versionValue,
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());
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));
278 bound.getSourceExtent() ? bound.getSourceExtent() : bound.getExtent();
281 if (!bound.getStrideInBytes())
283 LLVM::MulOp::create(rewriter, bound.getLoc(), stride, elementSize);
284 strides.push_back(stride);
286 getBoundValue(bound.getStartIdx(), bound.getLoc(), rewriter));
289 Value lowerBoundsArray =
291 Value upperBoundsArray =
297 using Field = AccDataDescOpenACCField;
298 auto insert = [&](
Value value, Field field) {
299 descriptor = LLVM::InsertValueOp::create(
300 rewriter, loc, descriptorType, descriptor, value,
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);
312 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
314 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
315 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
321 ValueRange bounds,
Value elementSize, ConversionPatternRewriter &rewriter) {
323 Type i8Ty = rewriter.getI8Type();
324 Type i32Ty = rewriter.getI32Type();
325 Type ptrTy = LLVM::LLVMPointerType::get(context);
326 using Field = AccDataDescMemRefField;
327 Type descriptorType =
329 auto version =
static_cast<uint32_t
>(
331 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
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,
339 insert(rank, Field::Rank);
340 insert(elementSize, Field::ElementSize);
341 insert(
getPointer(loc, convertedMemref, rewriter), Field::MemRefDescriptor);
344 bounds, elementSize, rewriter);
346 insert(LLVM::ConstantOp::create(rewriter, loc, i32Ty, version),
348 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
350 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
351 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
356 Value convertedOperand,
358 ConversionPatternRewriter &rewriter) {
361 Type i32Ty = rewriter.getI32Type();
362 Type ptrTy = LLVM::LLVMPointerType::get(context);
368 auto elementSize = [&] {
373 if (var && isa<MemRefType>(var.
getType())) {
374 auto memrefType = cast<MemRefType>(var.
getType());
376 loc, memrefType, convertedOperand, bounds, elementSize(), rewriter);
379 if (bitEnumContainsAny(descKind, DataDescKind::cfi)) {
380 using Field = AccDataDescCFIField;
381 Type descriptorType =
383 auto version =
static_cast<uint32_t
>(
385 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
387 if (!descriptorStorage)
388 descriptorStorage = convertedOperand;
389 descriptor = LLVM::InsertValueOp::create(
390 rewriter, loc, descriptorType, descriptor,
395 bounds, elementSize(), rewriter);
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);
404 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
405 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
409 if (!bounds.empty()) {
410 Type descriptorType =
412 auto version =
static_cast<uint32_t
>(
414 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
416 bounds, elementSize(), rewriter);
418 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
428 ConversionPatternRewriter &rewriter,
Region &globalSymbolRegion,
432 if (mappingOperands.size() != convertedOperands.size())
437 globalSymbolRegion, config, symbolTable);
441 runtimeArgs.
argMappers = LLVM::ZeroOp::create(
442 rewriter, loc, LLVM::LLVMPointerType::get(rewriter.getContext()));
448 struct MappedObject {
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(
463 LLVM::ExtractValueOp::create(rewriter, loc, converted, field),
467 mappedObjects.push_back({operand, converted,
true});
472 runtimeArgs.
argNum = LLVM::ConstantOp::create(
473 rewriter, loc, rewriter.getI32Type(), mappedObjects.size());
475 constexpr unsigned noSlot = ~0u;
479 for (
auto [slot,
object] : llvm::enumerate(mappedObjects)) {
480 auto [operand, converted, firstField] = object;
488 LLVM_DEBUG(llvm::dbgs() <<
"mapping " << *mapOp <<
"\n as "
494 *mapFlags, rewriter);
498 bitEnumContainsAny(*mapFlags, MapFlags::device_resident)
506 bitEnumContainsAny(*mapFlags, MapFlags::device_resident)) {
509 !isa_and_nonnull<AddressOfGlobalOpInterface>(var.
getDefiningOp()))
510 *mapFlags = *mapFlags | MapFlags::delete_;
514 for (
auto [
index, returned] :
515 llvm::enumerate(
options.returnAddressOperands)) {
516 if (returned != operand)
518 *mapFlags = *mapFlags | MapFlags::return_param;
525 mapLoc, operand, converted, *mapFlags, accSupport, rewriter);
531 mapLoc, operand, accSupport, globalSymbolRegion, symbolTable, rewriter);
534 objects.push_back(args);
545 ValueRange convertedOperands, ConversionPatternRewriter &rewriter,
550 if (mappingOperands.empty())
551 return returnedAddresses;
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");
562 arguments.append(trailingArguments.begin(), trailingArguments.end());
564 fn, config, arguments)))
567 Type i32Ty = rewriter.getI32Type();
568 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
570 Value index = LLVM::ConstantOp::create(rewriter, loc, i32Ty, slot);
572 LLVM::GEPOp::create(rewriter, loc, ptrTy, ptrTy,
574 returnedAddresses.push_back(
575 LLVM::LoadOp::create(rewriter, loc, ptrTy, element));
577 return returnedAddresses;
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...
static llvm::ManagedStatic< PassManagerOptions > options
MLIRContext * getContext() const
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
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...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
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.
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.
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.
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.
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.
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.