forked from OSchip/llvm-project
[mlir][openacc] Add OpenACC translation to LLVM IR (enter_data op create/copyin)
This patch begins to translate acc.enter_data operation to call to tgt runtime call. It currently only translate create/copyin operands of memref type. This acts as a basis to add support for FIR types in the Flang/OpenACC support. It follows more or less a similar path than clang with `omp target enter data map` directives. This patch is taking a different approach than D100678 and perform a translation to LLVM IR and make use of the OpenMPIRBuilder instead of doing a conversion to the LLVMIR dialect. OpenACC support in Flang will rely on the current OpenMP runtime where 1:1 lowering can be applied. Some extension will be added where features are not available yet. Big part of this code will be shared for other standalone data operations in the OpenACC dialect such as acc.exit_data and acc.update. It is likely that parts of the lowering can also be shared later with the ops for standalone data directives in the OpenMP dialect when they are introduced. This is an initial translation and it probably needs more work. Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D101504
This commit is contained in:
parent
81f56a2eb3
commit
113b807017
|
@ -19,6 +19,7 @@
|
|||
#include "mlir/Target/LLVMIR/Dialect/ArmSVE/ArmSVEToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
|
||||
#include "mlir/Target/LLVMIR/Dialect/X86Vector/X86VectorToLLVMIRTranslation.h"
|
||||
|
@ -34,6 +35,7 @@ static inline void registerAllToLLVMIRTranslations(DialectRegistry ®istry) {
|
|||
registerArmSVEDialectTranslation(registry);
|
||||
registerLLVMDialectTranslation(registry);
|
||||
registerNVVMDialectTranslation(registry);
|
||||
registerOpenACCDialectTranslation(registry);
|
||||
registerOpenMPDialectTranslation(registry);
|
||||
registerROCDLDialectTranslation(registry);
|
||||
registerX86VectorDialectTranslation(registry);
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
//===- OpenACCToLLVMIRTranslation.h - OpenACC Dialect to LLVM IR -- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This provides registration calls for OpenACC dialect to LLVM IR translation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_TARGET_LLVMIR_DIALECT_OPENACC_OPENACCTOLLVMIRTRANSLATION_H
|
||||
#define MLIR_TARGET_LLVMIR_DIALECT_OPENACC_OPENACCTOLLVMIRTRANSLATION_H
|
||||
|
||||
namespace mlir {
|
||||
|
||||
class DialectRegistry;
|
||||
class MLIRContext;
|
||||
|
||||
/// Register the OpenACC dialect and the translation to the LLVM IR in
|
||||
/// the given registry;
|
||||
void registerOpenACCDialectTranslation(DialectRegistry ®istry);
|
||||
|
||||
/// Register the OpenACC dialect and the translation in the registry
|
||||
/// associated with the given context.
|
||||
void registerOpenACCDialectTranslation(MLIRContext &context);
|
||||
|
||||
} // namespace mlir
|
||||
|
||||
#endif // MLIR_TARGET_LLVMIR_DIALECT_OPENACC_OPENACCTOLLVMIRTRANSLATION_H
|
|
@ -27,6 +27,7 @@ add_mlir_translation_library(MLIRTargetLLVMIRExport
|
|||
|
||||
LINK_LIBS PUBLIC
|
||||
MLIRLLVMIR
|
||||
MLIROpenACC
|
||||
MLIROpenMP
|
||||
MLIRLLVMIRTransforms
|
||||
MLIRTranslation
|
||||
|
@ -42,6 +43,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
|
|||
MLIRX86VectorToLLVMIRTranslation
|
||||
MLIRLLVMToLLVMIRTranslation
|
||||
MLIRNVVMToLLVMIRTranslation
|
||||
MLIROpenACCToLLVMIRTranslation
|
||||
MLIROpenMPToLLVMIRTranslation
|
||||
MLIRROCDLToLLVMIRTranslation
|
||||
)
|
||||
|
|
|
@ -3,6 +3,7 @@ add_subdirectory(ArmSVE)
|
|||
add_subdirectory(AMX)
|
||||
add_subdirectory(LLVMIR)
|
||||
add_subdirectory(NVVM)
|
||||
add_subdirectory(OpenACC)
|
||||
add_subdirectory(OpenMP)
|
||||
add_subdirectory(ROCDL)
|
||||
add_subdirectory(X86Vector)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
add_mlir_translation_library(MLIROpenACCToLLVMIRTranslation
|
||||
OpenACCToLLVMIRTranslation.cpp
|
||||
|
||||
LINK_COMPONENTS
|
||||
Core
|
||||
|
||||
LINK_LIBS PUBLIC
|
||||
MLIRIR
|
||||
MLIRLLVMIR
|
||||
MLIROpenACC
|
||||
MLIROpenACCToLLVM
|
||||
MLIRSupport
|
||||
MLIRTargetLLVMIRExport
|
||||
)
|
|
@ -0,0 +1,304 @@
|
|||
//===- OpenACCToLLVMIRTranslation.cpp -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a translation between the MLIR OpenACC dialect and LLVM
|
||||
// IR.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.h"
|
||||
#include "mlir/Conversion/OpenACCToLLVM/ConvertOpenACCToLLVM.h"
|
||||
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
||||
#include "mlir/Dialect/OpenACC/OpenACC.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
#include "mlir/Support/LLVM.h"
|
||||
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
|
||||
|
||||
#include "llvm/ADT/TypeSwitch.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
|
||||
using namespace mlir;
|
||||
|
||||
using OpenACCIRBuilder = llvm::OpenMPIRBuilder;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// 0 = alloc/create
|
||||
static constexpr uint64_t createFlag = 0;
|
||||
/// 1 = to/copyin
|
||||
static constexpr uint64_t copyinFlag = 1;
|
||||
/// Default value for the device id
|
||||
static constexpr int64_t defaultDevice = -1;
|
||||
|
||||
/// Create a constant string location from the MLIR Location information.
|
||||
static llvm::Constant *createSourceLocStrFromLocation(Location loc,
|
||||
OpenACCIRBuilder &builder,
|
||||
StringRef name) {
|
||||
if (auto fileLoc = loc.dyn_cast<FileLineColLoc>()) {
|
||||
StringRef fileName = fileLoc.getFilename();
|
||||
unsigned lineNo = fileLoc.getLine();
|
||||
unsigned colNo = fileLoc.getColumn();
|
||||
return builder.getOrCreateSrcLocStr(name, fileName, lineNo, colNo);
|
||||
} else {
|
||||
std::string locStr;
|
||||
llvm::raw_string_ostream locOS(locStr);
|
||||
locOS << loc;
|
||||
return builder.getOrCreateSrcLocStr(locOS.str());
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the location struct from the operation location information.
|
||||
static llvm::Value *createSourceLocationInfo(acc::EnterDataOp &op,
|
||||
OpenACCIRBuilder &builder) {
|
||||
auto loc = op.getLoc();
|
||||
auto funcOp = op.getOperation()->getParentOfType<LLVM::LLVMFuncOp>();
|
||||
StringRef funcName = funcOp ? funcOp.getName() : "unknown";
|
||||
llvm::Constant *locStr =
|
||||
createSourceLocStrFromLocation(loc, builder, funcName);
|
||||
return builder.getOrCreateIdent(locStr);
|
||||
}
|
||||
|
||||
/// Create a constant string representing the mapping information extracted from
|
||||
/// the MLIR location information.
|
||||
static llvm::Constant *createMappingInformation(Location loc,
|
||||
OpenACCIRBuilder &builder) {
|
||||
if (auto nameLoc = loc.dyn_cast<NameLoc>()) {
|
||||
StringRef name = nameLoc.getName();
|
||||
return createSourceLocStrFromLocation(nameLoc.getChildLoc(), builder, name);
|
||||
} else {
|
||||
return createSourceLocStrFromLocation(loc, builder, "unknown");
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the runtime function used to lower the given operation.
|
||||
static llvm::Function *getAssociatedFunction(OpenACCIRBuilder &builder,
|
||||
Operation &op) {
|
||||
if (isa<acc::EnterDataOp>(op))
|
||||
return builder.getOrCreateRuntimeFunctionPtr(
|
||||
llvm::omp::OMPRTL___tgt_target_data_begin_mapper);
|
||||
llvm_unreachable("Unknown OpenACC operation");
|
||||
}
|
||||
|
||||
/// Computes the size of type in bytes.
|
||||
static llvm::Value *getSizeInBytes(llvm::IRBuilderBase &builder,
|
||||
llvm::Value *basePtr) {
|
||||
llvm::LLVMContext &ctx = builder.getContext();
|
||||
llvm::Value *null =
|
||||
llvm::Constant::getNullValue(basePtr->getType()->getPointerTo());
|
||||
llvm::Value *sizeGep =
|
||||
builder.CreateGEP(basePtr->getType(), null, builder.getInt32(1));
|
||||
llvm::Value *sizePtrToInt =
|
||||
builder.CreatePtrToInt(sizeGep, llvm::Type::getInt64Ty(ctx));
|
||||
return sizePtrToInt;
|
||||
}
|
||||
|
||||
/// Extract pointer, size and mapping information from operands
|
||||
/// to populate the future functions arguments.
|
||||
static LogicalResult
|
||||
processOperands(llvm::IRBuilderBase &builder,
|
||||
LLVM::ModuleTranslation &moduleTranslation, Operation &op,
|
||||
ValueRange operands, unsigned totalNbOperand,
|
||||
uint64_t operandFlag, SmallVector<uint64_t> &flags,
|
||||
SmallVector<llvm::Constant *> &names, unsigned &index,
|
||||
llvm::AllocaInst *argsBase, llvm::AllocaInst *args,
|
||||
llvm::AllocaInst *argSizes) {
|
||||
OpenACCIRBuilder *accBuilder = moduleTranslation.getOpenMPBuilder();
|
||||
llvm::LLVMContext &ctx = builder.getContext();
|
||||
auto *i8PtrTy = llvm::Type::getInt8PtrTy(ctx);
|
||||
auto *arrI8PtrTy = llvm::ArrayType::get(i8PtrTy, totalNbOperand);
|
||||
auto *i64Ty = llvm::Type::getInt64Ty(ctx);
|
||||
auto *arrI64Ty = llvm::ArrayType::get(i64Ty, totalNbOperand);
|
||||
|
||||
for (Value data : operands) {
|
||||
llvm::Value *dataValue = moduleTranslation.lookupValue(data);
|
||||
|
||||
llvm::Value *dataPtrBase;
|
||||
llvm::Value *dataPtr;
|
||||
llvm::Value *dataSize;
|
||||
|
||||
// Handle operands that were converted to DataDescriptor.
|
||||
if (DataDescriptor::isValid(data)) {
|
||||
dataPtrBase =
|
||||
builder.CreateExtractValue(dataValue, kPtrBasePosInDataDescriptor);
|
||||
dataPtr = builder.CreateExtractValue(dataValue, kPtrPosInDataDescriptor);
|
||||
dataSize =
|
||||
builder.CreateExtractValue(dataValue, kSizePosInDataDescriptor);
|
||||
} else if (data.getType().isa<LLVM::LLVMPointerType>()) {
|
||||
dataPtrBase = dataValue;
|
||||
dataPtr = dataValue;
|
||||
dataSize = getSizeInBytes(builder, dataValue);
|
||||
} else {
|
||||
return op.emitOpError()
|
||||
<< "Data operand must be legalized before translation."
|
||||
<< "Unsupported type: " << data.getType();
|
||||
}
|
||||
|
||||
// Store base pointer extracted from operand into the i-th position of
|
||||
// argBase.
|
||||
llvm::Value *ptrBaseGEP = builder.CreateInBoundsGEP(
|
||||
arrI8PtrTy, argsBase, {builder.getInt32(0), builder.getInt32(index)});
|
||||
llvm::Value *ptrBaseCast = builder.CreateBitCast(
|
||||
ptrBaseGEP, dataPtrBase->getType()->getPointerTo());
|
||||
builder.CreateStore(dataPtrBase, ptrBaseCast);
|
||||
|
||||
// Store pointer extracted from operand into the i-th position of args.
|
||||
llvm::Value *ptrGEP = builder.CreateInBoundsGEP(
|
||||
arrI8PtrTy, args, {builder.getInt32(0), builder.getInt32(index)});
|
||||
llvm::Value *ptrCast =
|
||||
builder.CreateBitCast(ptrGEP, dataPtr->getType()->getPointerTo());
|
||||
builder.CreateStore(dataPtr, ptrCast);
|
||||
|
||||
// Store size extracted from operand into the i-th position of argSizes.
|
||||
llvm::Value *sizeGEP = builder.CreateInBoundsGEP(
|
||||
arrI64Ty, argSizes, {builder.getInt32(0), builder.getInt32(index)});
|
||||
builder.CreateStore(dataSize, sizeGEP);
|
||||
|
||||
flags.push_back(operandFlag);
|
||||
llvm::Constant *mapName =
|
||||
createMappingInformation(data.getLoc(), *accBuilder);
|
||||
names.push_back(mapName);
|
||||
++index;
|
||||
}
|
||||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Conversion functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Converts an OpenACC enter_data operartion into LLVM IR.
|
||||
static LogicalResult
|
||||
convertEnterDataOp(Operation &op, llvm::IRBuilderBase &builder,
|
||||
LLVM::ModuleTranslation &moduleTranslation) {
|
||||
auto enterDataOp = cast<acc::EnterDataOp>(op);
|
||||
auto enclosingFuncOp = op.getParentOfType<LLVM::LLVMFuncOp>();
|
||||
llvm::Function *enclosingFunction =
|
||||
moduleTranslation.lookupFunction(enclosingFuncOp.getName());
|
||||
|
||||
OpenACCIRBuilder *accBuilder = moduleTranslation.getOpenMPBuilder();
|
||||
|
||||
auto *srcLocInfo = createSourceLocationInfo(enterDataOp, *accBuilder);
|
||||
auto *mapperFunc = getAssociatedFunction(*accBuilder, op);
|
||||
|
||||
// Number of arguments in the enter_data operation.
|
||||
// TODO include create_zero and attach operands.
|
||||
unsigned totalNbOperand =
|
||||
enterDataOp.createOperands().size() + enterDataOp.copyinOperands().size();
|
||||
|
||||
// TODO could be moved to OpenXXIRBuilder?
|
||||
llvm::LLVMContext &ctx = builder.getContext();
|
||||
auto *i8PtrTy = llvm::Type::getInt8PtrTy(ctx);
|
||||
auto *arrI8PtrTy = llvm::ArrayType::get(i8PtrTy, totalNbOperand);
|
||||
auto *i64Ty = llvm::Type::getInt64Ty(ctx);
|
||||
auto *arrI64Ty = llvm::ArrayType::get(i64Ty, totalNbOperand);
|
||||
llvm::IRBuilder<>::InsertPoint allocaIP(
|
||||
&enclosingFunction->getEntryBlock(),
|
||||
enclosingFunction->getEntryBlock().getFirstInsertionPt());
|
||||
llvm::IRBuilder<>::InsertPoint currentIP = builder.saveIP();
|
||||
builder.restoreIP(allocaIP);
|
||||
llvm::AllocaInst *argsBase = builder.CreateAlloca(arrI8PtrTy);
|
||||
llvm::AllocaInst *args = builder.CreateAlloca(arrI8PtrTy);
|
||||
llvm::AllocaInst *argSizes = builder.CreateAlloca(arrI64Ty);
|
||||
builder.restoreIP(currentIP);
|
||||
|
||||
SmallVector<uint64_t> flags;
|
||||
SmallVector<llvm::Constant *> names;
|
||||
unsigned index = 0;
|
||||
|
||||
// Create operands are handled as `alloc` call.
|
||||
if (failed(processOperands(builder, moduleTranslation, op,
|
||||
enterDataOp.createOperands(), totalNbOperand,
|
||||
createFlag, flags, names, index, argsBase, args,
|
||||
argSizes)))
|
||||
return failure();
|
||||
|
||||
// Copyin operands are handled as `to` call.
|
||||
if (failed(processOperands(builder, moduleTranslation, op,
|
||||
enterDataOp.copyinOperands(), totalNbOperand,
|
||||
copyinFlag, flags, names, index, argsBase, args,
|
||||
argSizes)))
|
||||
return failure();
|
||||
|
||||
llvm::GlobalVariable *maptypes =
|
||||
accBuilder->createOffloadMaptypes(flags, ".offload_maptypes");
|
||||
llvm::Value *maptypesArg = builder.CreateConstInBoundsGEP2_32(
|
||||
llvm::ArrayType::get(llvm::Type::getInt64Ty(ctx), totalNbOperand),
|
||||
maptypes, /*Idx0=*/0, /*Idx1=*/0);
|
||||
|
||||
llvm::GlobalVariable *mapnames =
|
||||
accBuilder->createOffloadMapnames(names, ".offload_mapnames");
|
||||
llvm::Value *mapnamesArg = builder.CreateConstInBoundsGEP2_32(
|
||||
llvm::ArrayType::get(llvm::Type::getInt8PtrTy(ctx), totalNbOperand),
|
||||
mapnames, /*Idx0=*/0, /*Idx1=*/0);
|
||||
|
||||
llvm::Value *argsBaseGEP = builder.CreateInBoundsGEP(
|
||||
arrI8PtrTy, argsBase, {builder.getInt32(0), builder.getInt32(0)});
|
||||
llvm::Value *argsGEP = builder.CreateInBoundsGEP(
|
||||
arrI8PtrTy, args, {builder.getInt32(0), builder.getInt32(0)});
|
||||
llvm::Value *argSizesGEP = builder.CreateInBoundsGEP(
|
||||
arrI64Ty, argSizes, {builder.getInt32(0), builder.getInt32(0)});
|
||||
llvm::Value *nullPtr = llvm::Constant::getNullValue(
|
||||
llvm::Type::getInt8PtrTy(ctx)->getPointerTo());
|
||||
|
||||
builder.CreateCall(mapperFunc,
|
||||
{srcLocInfo, builder.getInt64(defaultDevice),
|
||||
builder.getInt32(totalNbOperand), argsBaseGEP, argsGEP,
|
||||
argSizesGEP, maptypesArg, mapnamesArg, nullPtr});
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// Implementation of the dialect interface that converts operations belonging
|
||||
/// to the OpenACC dialect to LLVM IR.
|
||||
class OpenACCDialectLLVMIRTranslationInterface
|
||||
: public LLVMTranslationDialectInterface {
|
||||
public:
|
||||
using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
|
||||
|
||||
/// Translates the given operation to LLVM IR using the provided IR builder
|
||||
/// and saving the state in `moduleTranslation`.
|
||||
LogicalResult
|
||||
convertOperation(Operation *op, llvm::IRBuilderBase &builder,
|
||||
LLVM::ModuleTranslation &moduleTranslation) const final;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
/// Given an OpenACC MLIR operation, create the corresponding LLVM IR
|
||||
/// (including OpenACC runtime calls).
|
||||
LogicalResult OpenACCDialectLLVMIRTranslationInterface::convertOperation(
|
||||
Operation *op, llvm::IRBuilderBase &builder,
|
||||
LLVM::ModuleTranslation &moduleTranslation) const {
|
||||
|
||||
return llvm::TypeSwitch<Operation *, LogicalResult>(op)
|
||||
.Case([&](acc::EnterDataOp) {
|
||||
return convertEnterDataOp(*op, builder, moduleTranslation);
|
||||
})
|
||||
.Default([&](Operation *op) {
|
||||
return op->emitError("unsupported OpenACC operation: ")
|
||||
<< op->getName();
|
||||
});
|
||||
}
|
||||
|
||||
void mlir::registerOpenACCDialectTranslation(DialectRegistry ®istry) {
|
||||
registry.insert<acc::OpenACCDialect>();
|
||||
registry.addDialectInterface<acc::OpenACCDialect,
|
||||
OpenACCDialectLLVMIRTranslationInterface>();
|
||||
}
|
||||
|
||||
void mlir::registerOpenACCDialectTranslation(MLIRContext &context) {
|
||||
DialectRegistry registry;
|
||||
registerOpenACCDialectTranslation(registry);
|
||||
context.appendDialectRegistry(registry);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
|
||||
|
||||
llvm.func @testenterdataop(%arg0: !llvm.ptr<f32>, %arg1: !llvm.ptr<f32>, %arg2: i64, %arg3: i64, %arg4: i64, %arg5: !llvm.ptr<f32>) {
|
||||
%0 = llvm.mlir.undef : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%1 = llvm.insertvalue %arg0, %0[0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%2 = llvm.insertvalue %arg1, %1[1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%3 = llvm.insertvalue %arg2, %2[2] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%4 = llvm.insertvalue %arg3, %3[3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%5 = llvm.insertvalue %arg4, %4[4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%6 = llvm.mlir.constant(10 : index) : i64
|
||||
%7 = llvm.mlir.constant(1 : index) : i64
|
||||
%8 = llvm.mlir.null : !llvm.ptr<f32>
|
||||
%9 = llvm.getelementptr %8[%6] : (!llvm.ptr<f32>, i64) -> !llvm.ptr<f32>
|
||||
%10 = llvm.ptrtoint %9 : !llvm.ptr<f32> to i64
|
||||
%11 = llvm.extractvalue %5[1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
|
||||
%12 = llvm.mlir.undef : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
|
||||
%13 = llvm.insertvalue %5, %12[0] : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
|
||||
%14 = llvm.insertvalue %11, %13[1] : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
|
||||
%15 = llvm.insertvalue %10, %14[2] : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>
|
||||
acc.enter_data copyin(%arg5 : !llvm.ptr<f32>) create(%15 : !llvm.struct<"openacc_data", (struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>, ptr<f32>, i64)>)
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK: %struct.ident_t = type { i32, i32, i32, i32, i8* }
|
||||
|
||||
// CHECK: [[LOCSTR:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i8] c";{{.*}};testenterdataop;{{[0-9]*}};{{[0-9]*}};;\00", align 1
|
||||
// CHECK: [[LOCGLOBAL:@.*]] = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([{{[0-9]*}} x i8], [{{[0-9]*}} x i8]* [[LOCSTR]], i32 0, i32 0) }, align 8
|
||||
// CHECK: [[MAPNAME1:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i8] c";{{.*}};unknown;{{[0-9]*}};{{[0-9]*}};;\00", align 1
|
||||
// CHECK: [[MAPNAME2:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i8] c";{{.*}};unknown;{{[0-9]*}};{{[0-9]*}};;\00", align 1
|
||||
// CHECK: [[MAPTYPES:@.*]] = private unnamed_addr constant [{{[0-9]*}} x i64] [i64 0, i64 1]
|
||||
// CHECK: [[MAPNAMES:@.*]] = private constant [{{[0-9]*}} x i8*] [i8* getelementptr inbounds ([{{[0-9]*}} x i8], [{{[0-9]*}} x i8]* [[MAPNAME1]], i32 0, i32 0), i8* getelementptr inbounds ([{{[0-9]*}} x i8], [{{[0-9]*}} x i8]* [[MAPNAME2]], i32 0, i32 0)]
|
||||
|
||||
// CHECK: define void @testenterdataop(float* %{{.*}}, float* %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, float* [[SIMPLEPTR:%.*]])
|
||||
// CHECK: [[ARGBASE_ALLOCA:%.*]] = alloca [{{[0-9]*}} x i8*], align 8
|
||||
// CHECK: [[ARG_ALLOCA:%.*]] = alloca [{{[0-9]*}} x i8*], align 8
|
||||
// CHECK: [[SIZE_ALLOCA:%.*]] = alloca [{{[0-9]*}} x i64], align 8
|
||||
|
||||
// CHECK: [[ARGBASE:%.*]] = extractvalue %openacc_data %{{.*}}, 0
|
||||
// CHECK: [[ARG:%.*]] = extractvalue %openacc_data %{{.*}}, 1
|
||||
// CHECK: [[ARGSIZE:%.*]] = extractvalue %openacc_data %{{.*}}, 2
|
||||
// CHECK: [[ARGBASEGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARGBASE_ALLOCA]], i32 0, i32 0
|
||||
// CHECK: [[ARGBASEGEPCAST:%.*]] = bitcast i8** [[ARGBASEGEP]] to { float*, float*, i64, [1 x i64], [1 x i64] }*
|
||||
// CHECK: store { float*, float*, i64, [1 x i64], [1 x i64] } [[ARGBASE]], { float*, float*, i64, [1 x i64], [1 x i64] }* [[ARGBASEGEPCAST]], align 8
|
||||
// CHECK: [[ARGGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARG_ALLOCA]], i32 0, i32 0
|
||||
// CHECK: [[ARGGEPCAST:%.*]] = bitcast i8** [[ARGGEP]] to float**
|
||||
// CHECK: store float* [[ARG]], float** [[ARGGEPCAST]], align 8
|
||||
// CHECK: [[SIZEGEP:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[SIZE_ALLOCA]], i32 0, i32 0
|
||||
// CHECK: store i64 [[ARGSIZE]], i64* [[SIZEGEP]], align 4
|
||||
|
||||
// CHECK: [[ARGBASEGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARGBASE_ALLOCA]], i32 0, i32 1
|
||||
// CHECK: [[ARGBASEGEPCAST:%.*]] = bitcast i8** [[ARGBASEGEP]] to float**
|
||||
// CHECK: store float* [[SIMPLEPTR]], float** [[ARGBASEGEPCAST]], align 8
|
||||
// CHECK: [[ARGGEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARG_ALLOCA]], i32 0, i32 1
|
||||
// CHECK: [[ARGGEPCAST:%.*]] = bitcast i8** [[ARGGEP]] to float**
|
||||
// CHECK: store float* [[SIMPLEPTR]], float** [[ARGGEPCAST]], align 8
|
||||
// CHECK: [[SIZEGEP:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[SIZE_ALLOCA]], i32 0, i32 1
|
||||
// CHECK: store i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64), i64* [[SIZEGEP]], align 4
|
||||
|
||||
// CHECK: [[ARGBASE_ALLOCA_GEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARGBASE_ALLOCA]], i32 0, i32 0
|
||||
// CHECK: [[ARG_ALLOCA_GEP:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[ARG_ALLOCA]], i32 0, i32 0
|
||||
// CHECK: [[SIZE_ALLOCA_GEP:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[SIZE_ALLOCA]], i32 0, i32 0
|
||||
|
||||
// CHECK: call void @__tgt_target_data_begin_mapper(%struct.ident_t* [[LOCGLOBAL]], i64 -1, i32 2, i8** [[ARGBASE_ALLOCA_GEP]], i8** [[ARG_ALLOCA_GEP]], i64* [[SIZE_ALLOCA_GEP]], i64* getelementptr inbounds ([{{[0-9]*}} x i64], [{{[0-9]*}} x i64]* [[MAPTYPES]], i32 0, i32 0), i8** getelementptr inbounds ([{{[0-9]*}} x i8*], [{{[0-9]*}} x i8*]* [[MAPNAMES]], i32 0, i32 0), i8** null)
|
||||
|
||||
// CHECK: declare void @__tgt_target_data_begin_mapper(%struct.ident_t*, i64, i32, i8**, i8**, i64*, i64*, i8**, i8**) #0
|
Loading…
Reference in New Issue