22#include "llvm/ADT/STLExtras.h"
23#include "llvm/Support/Debug.h"
27#define DEBUG_TYPE "acc-data-runtime"
35 if (
Value converted = rewriter.getRemappedValue(value))
41 ConversionPatternRewriter &rewriter) {
42 return LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), value);
46 ConversionPatternRewriter &rewriter) {
47 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
49 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
53 if (isa<PointerLikeType>(value.
getType()))
56 Value one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
58 LLVM::AllocaOp::create(rewriter, loc, ptrTy, value.
getType(), one);
59 LLVM::StoreOp::create(rewriter, loc, value, storage);
66 ConversionPatternRewriter &rewriter) {
67 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
68 Value one = LLVM::ConstantOp::create(rewriter, loc, rewriter.getI32Type(), 1);
70 LLVM::AllocaOp::create(rewriter, loc, ptrTy, value.
getType(), one);
71 LLVM::StoreOp::create(rewriter, loc, value, storage);
79 Value count = LLVM::ConstantOp::create(rewriter, loc, i32Ty, values.size());
81 LLVM::AllocaOp::create(rewriter, loc, ptrTy, elementType, count);
82 for (
auto [
index, value] : llvm::enumerate(values)) {
83 Value indexValue = LLVM::ConstantOp::create(rewriter, loc, i32Ty,
index);
84 Value element = LLVM::GEPOp::create(rewriter, loc, ptrTy, elementType,
86 LLVM::StoreOp::create(rewriter, loc, value, element);
97 Value converted, MapFlags mapFlags,
98 ConversionPatternRewriter &rewriter) {
99 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
100 if (isa<PrivateType>(operand.
getType()))
101 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
102 if (converted && converted.
getType() == ptrTy &&
103 bitEnumContainsAny(mapFlags, MapFlags::devptr))
109 if (
auto mapInfo = dyn_cast<MapInfoOp>(mapOp))
110 return mapInfo.getMapFlags();
111 if (isa<ACC_DATA_ENTRY_OPS>(mapOp))
118 ConversionPatternRewriter &rewriter) {
124 if (bitEnumContainsAny(mapFlags, MapFlags::literal) && converted) {
126 converted.
getType(), module, &accSupport))
127 return constantI64(loc, sizeAndAlignment->first.getFixedValue(),
141 if (isa<MemRefType>(var.
getType()) || isa<MemRefType>(varType))
151 return constantI64(loc, std::max<int64_t>(size, 0), rewriter);
155 ConversionPatternRewriter &rewriter) {
162 if (
auto shaped = dyn_cast<ShapedType>(type))
163 type = shaped.getElementType();
166 if (
auto sizeAndAlignment =
168 return constantI64(loc, sizeAndAlignment->first.getFixedValue(), rewriter);
173 ConversionPatternRewriter &rewriter) {
180 Type baseDescriptorType, uint32_t version,
182 ConversionPatternRewriter &rewriter) {
184 Type i8Ty = rewriter.getI8Type();
185 Type i32Ty = rewriter.getI32Type();
186 Type i64Ty = rewriter.getI64Type();
187 Type ptrTy = LLVM::LLVMPointerType::get(context);
189 Value versionValue = LLVM::ConstantOp::create(
190 rewriter, loc, i32Ty,
191 version |
static_cast<uint32_t
>(
193 baseDescriptor = LLVM::InsertValueOp::create(
194 rewriter, loc, baseDescriptorType, baseDescriptor, versionValue,
198 context, DataDescriptor::AccDataDescOpenACC, baseDescriptorType);
199 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
200 Value rank = LLVM::ConstantOp::create(rewriter, loc, i8Ty, bounds.size());
207 for (
Value boundValue : bounds) {
208 auto bound = cast<DataBoundsOp>(boundValue.getDefiningOp());
209 lowerBounds.push_back(
210 getBoundValue(bound.getLowerbound(), bound.getLoc(), rewriter));
211 upperBounds.push_back(
212 getBoundValue(bound.getUpperbound(), bound.getLoc(), rewriter));
214 bound.getSourceExtent() ? bound.getSourceExtent() : bound.getExtent();
217 if (!bound.getStrideInBytes())
219 LLVM::MulOp::create(rewriter, bound.getLoc(), stride, elementSize);
220 strides.push_back(stride);
222 getBoundValue(bound.getStartIdx(), bound.getLoc(), rewriter));
225 Value lowerBoundsArray =
227 Value upperBoundsArray =
233 using Field = AccDataDescOpenACCField;
234 auto insert = [&](
Value value, Field field) {
235 descriptor = LLVM::InsertValueOp::create(
236 rewriter, loc, descriptorType, descriptor, value,
239 insert(baseDescriptor, Field::Base);
240 insert(rank, Field::Rank);
241 insert(elementSize, Field::ElementSize);
242 insert(lowerBoundsArray, Field::LowerBounds);
243 insert(upperBoundsArray, Field::UpperBounds);
244 insert(extentsArray, Field::Extents);
245 insert(stridesArray, Field::StridesInBytes);
246 insert(startsArray, Field::StartIndices);
248 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
250 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
251 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
257 ValueRange bounds,
Value elementSize, ConversionPatternRewriter &rewriter) {
259 Type i8Ty = rewriter.getI8Type();
260 Type i32Ty = rewriter.getI32Type();
261 Type ptrTy = LLVM::LLVMPointerType::get(context);
262 using Field = AccDataDescMemRefField;
263 Type descriptorType =
265 auto version =
static_cast<uint32_t
>(
267 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
269 LLVM::ConstantOp::create(rewriter, loc, i8Ty, memrefType.getRank());
270 auto insert = [&](
Value value, Field field) {
271 descriptor = LLVM::InsertValueOp::create(
272 rewriter, loc, descriptorType, descriptor, value,
275 insert(rank, Field::Rank);
276 insert(elementSize, Field::ElementSize);
277 insert(
getPointer(loc, convertedMemref, rewriter), Field::MemRefDescriptor);
280 bounds, elementSize, rewriter);
282 insert(LLVM::ConstantOp::create(rewriter, loc, i32Ty, version),
284 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
286 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
287 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
292 Value convertedOperand,
294 ConversionPatternRewriter &rewriter) {
297 Type i32Ty = rewriter.getI32Type();
298 Type ptrTy = LLVM::LLVMPointerType::get(context);
304 auto elementSize = [&] {
309 if (var && isa<MemRefType>(var.
getType())) {
310 auto memrefType = cast<MemRefType>(var.
getType());
312 loc, memrefType, convertedOperand, bounds, elementSize(), rewriter);
315 if (bitEnumContainsAny(descKind, DataDescKind::cfi)) {
316 using Field = AccDataDescCFIField;
317 Type descriptorType =
319 auto version =
static_cast<uint32_t
>(
321 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
323 if (!descriptorStorage)
324 descriptorStorage = convertedOperand;
325 descriptor = LLVM::InsertValueOp::create(
326 rewriter, loc, descriptorType, descriptor,
331 bounds, elementSize(), rewriter);
334 LLVM::ConstantOp::create(rewriter, loc, i32Ty, version);
335 descriptor = LLVM::InsertValueOp::create(
336 rewriter, loc, descriptorType, descriptor, versionValue,
338 Value one = LLVM::ConstantOp::create(rewriter, loc, i32Ty, 1);
340 LLVM::AllocaOp::create(rewriter, loc, ptrTy, descriptorType, one);
341 LLVM::StoreOp::create(rewriter, loc, descriptor, storage);
345 if (!bounds.empty()) {
346 Type descriptorType =
348 auto version =
static_cast<uint32_t
>(
350 Value descriptor = LLVM::ZeroOp::create(rewriter, loc, descriptorType);
352 bounds, elementSize(), rewriter);
354 return LLVM::ZeroOp::create(rewriter, loc, ptrTy);
364 ConversionPatternRewriter &rewriter,
Region &globalSymbolRegion,
368 if (mappingOperands.size() != convertedOperands.size())
371 Type i32Ty = rewriter.getI32Type();
372 Type i64Ty = rewriter.getI64Type();
373 Type ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
377 globalSymbolRegion, config, symbolTable);
381 runtimeArgs.
argMappers = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
387 for (
auto [operand, converted] :
388 llvm::zip_equal(mappingOperands, convertedOperands)) {
389 auto structType = dyn_cast<LLVM::LLVMStructType>(converted.getType());
390 if (structType && !structType.isIdentified() &&
391 structType.getBody().size() > 1) {
392 for (
unsigned field = 0, fields = structType.getBody().size();
393 field != fields; ++field)
394 mappedObjects.emplace_back(
396 LLVM::ExtractValueOp::create(rewriter, loc, converted, field));
399 mappedObjects.emplace_back(operand, converted);
403 LLVM::ConstantOp::create(rewriter, loc, i32Ty, mappedObjects.size());
411 for (
auto [operand, converted] : mappedObjects) {
412 Operation *mapOp = operand.getDefiningOp();
413 if (!mapOp || !isa<MapInfoOp, ACC_DATA_ENTRY_OPS>(mapOp))
419 LLVM_DEBUG(llvm::dbgs() <<
"mapping " << *mapOp <<
"\n as "
424 *mapFlags, rewriter));
428 base =
remap(attach, rewriter);
429 else if (bitEnumContainsAny(*mapFlags, MapFlags::ptr_and_obj))
433 if (bitEnumContainsAny(*mapFlags, MapFlags::device_resident))
435 bases.push_back(
getPointer(mapLoc, base, rewriter));
441 bitEnumContainsAny(*mapFlags, MapFlags::device_resident)) {
444 !isa_and_nonnull<AddressOfGlobalOpInterface>(var.
getDefiningOp()))
445 *mapFlags = *mapFlags | MapFlags::delete_;
449 getMapSize(mapOp, converted, *mapFlags, accSupport, rewriter));
460 names.push_back(LLVM::ZeroOp::create(rewriter, mapLoc, ptrTy));
464 globalSymbolRegion, symbolTable));
466 descriptors.push_back(
static std::optional< MapFlags > computePackedMapFlags(Operation *mapOp)
static Value getMappedObjectPointer(Location loc, Value operand, Value converted, MapFlags mapFlags, ConversionPatternRewriter &rewriter)
The address of the mapped object, as the runtime expects to receive it.
static Value getBoundValue(Value value, Location loc, ConversionPatternRewriter &rewriter)
static Value getElementSize(Operation *mapOp, OpenACCSupport &accSupport, ConversionPatternRewriter &rewriter)
static Value remap(Value value, ConversionPatternRewriter &rewriter)
static Value getPointer(Location loc, Value value, ConversionPatternRewriter &rewriter)
static Value constantI64(Location loc, int64_t 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...
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.
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.
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 getDesc(Operation *mapEntryOp)
Returns descriptor value from acc.map_info.
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.
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).
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.
ACCDataCallKind
Identifies how data runtime arguments will be consumed.
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...
LogicalResult emitACCDataRuntimeArgs(Location loc, ValueRange mappingOperands, ValueRange convertedOperands, ConversionPatternRewriter &rewriter, Region &globalSymbolRegion, acc::OpenACCSupport &accSupport, const acc::ACCRuntimeCallConfig &config, ACCDataRuntimeArgs &runtimeArgs, ACCDataCallKind callKind=ACCDataCallKind::DataEnter, SymbolTable *symbolTable=nullptr)
Emit the OpenACC data runtime arguments for data-clause operands.
Value createACCMemRefDescriptorWrapperArg(Location loc, MemRefType memrefType, Value convertedMemref, ValueRange bounds, Value elementSize, ConversionPatternRewriter &rewriter)
Build the runtime argument descriptor wrapping an already converted memref.
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...
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
Reserved for per-call runtime flags; no flag is defined yet.
Value argPtrs
Array of addresses of the mapped objects themselves.
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.