forked from OSchip/llvm-project
[OPENMP] Fix for '#pragma omp task' codegen.
Internal task structure must be generated like typedef struct kmp_task { void * shareds; kmp_routine_entry_t routine; kmp_int32 part_id; kmp_routine_entry_t destructors; } kmp_task_t; struct kmp_task_t_with_privates { kmp_task_t task_data; .kmp_private. privates; }; to avoid possible additional alignment bytes in first fields (shareds, routine, part_id and destructors). Runtime library is not aware of such kind additional alignment bytes. llvm-svn: 237561
This commit is contained in:
parent
b8573cba02
commit
8fc69dcf42
|
@ -1605,9 +1605,6 @@ enum KmpTaskTFields {
|
|||
KmpTaskTPartId,
|
||||
/// \brief Function with call of destructors for private variables.
|
||||
KmpTaskTDestructors,
|
||||
/// \brief Record with list of all private/firstprivate copies for the task
|
||||
/// directive.
|
||||
KmpTaskTPrivates,
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
@ -1660,7 +1657,6 @@ createPrivatesRecordDecl(CodeGenModule &CGM,
|
|||
addFieldToRecordDecl(
|
||||
C, RD, Pair.second.Original->getType().getNonReferenceType());
|
||||
}
|
||||
// TODO: add firstprivate fields.
|
||||
RD->completeDefinition();
|
||||
return RD;
|
||||
}
|
||||
|
@ -1669,15 +1665,13 @@ createPrivatesRecordDecl(CodeGenModule &CGM,
|
|||
|
||||
static RecordDecl *
|
||||
createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
|
||||
QualType KmpRoutineEntryPointerQTy,
|
||||
const ArrayRef<PrivateDataTy> Privates) {
|
||||
QualType KmpRoutineEntryPointerQTy) {
|
||||
auto &C = CGM.getContext();
|
||||
// Build struct kmp_task_t {
|
||||
// void * shareds;
|
||||
// kmp_routine_entry_t routine;
|
||||
// kmp_int32 part_id;
|
||||
// kmp_routine_entry_t destructors;
|
||||
// /* private vars */
|
||||
// };
|
||||
auto *RD = C.buildImplicitRecord("kmp_task_t");
|
||||
RD->startDefinition();
|
||||
|
@ -1685,6 +1679,21 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
|
|||
addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
|
||||
addFieldToRecordDecl(C, RD, KmpInt32Ty);
|
||||
addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
|
||||
RD->completeDefinition();
|
||||
return RD;
|
||||
}
|
||||
|
||||
static RecordDecl *
|
||||
createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
|
||||
const ArrayRef<PrivateDataTy> Privates) {
|
||||
auto &C = CGM.getContext();
|
||||
// Build struct kmp_task_t_with_privates {
|
||||
// kmp_task_t task_data;
|
||||
// .kmp_privates_t. privates;
|
||||
// };
|
||||
auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
|
||||
RD->startDefinition();
|
||||
addFieldToRecordDecl(C, RD, KmpTaskTQTy);
|
||||
if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) {
|
||||
addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
|
||||
}
|
||||
|
@ -1702,14 +1711,14 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty,
|
|||
/// \endcode
|
||||
static llvm::Value *
|
||||
emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
|
||||
QualType KmpInt32Ty, QualType KmpTaskTPtrQTy,
|
||||
QualType SharedsPtrTy, llvm::Value *TaskFunction,
|
||||
llvm::Type *KmpTaskTTy) {
|
||||
QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy,
|
||||
QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
|
||||
QualType SharedsPtrTy, llvm::Value *TaskFunction) {
|
||||
auto &C = CGM.getContext();
|
||||
FunctionArgList Args;
|
||||
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
|
||||
ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
|
||||
/*Id=*/nullptr, KmpTaskTPtrQTy);
|
||||
/*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
|
||||
Args.push_back(&GtidArg);
|
||||
Args.push_back(&TaskTypeArg);
|
||||
FunctionType::ExtInfo Info;
|
||||
|
@ -1725,23 +1734,27 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
|
|||
CGF.disableDebugInfo();
|
||||
CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args);
|
||||
|
||||
// TaskFunction(gtid, tt->part_id, tt->shareds);
|
||||
// TaskFunction(gtid, tt->task_data.part_id, tt->task_data.shareds);
|
||||
auto *GtidParam = CGF.EmitLoadOfScalar(
|
||||
CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false,
|
||||
C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
|
||||
auto TaskTypeArgAddr = CGF.EmitLoadOfScalar(
|
||||
CGF.GetAddrOfLocalVar(&TaskTypeArg), /*Volatile=*/false,
|
||||
CGM.PointerAlignInBytes, KmpTaskTPtrQTy, Loc);
|
||||
auto *PartidPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
|
||||
/*Idx=*/KmpTaskTPartId);
|
||||
auto *PartidParam = CGF.EmitLoadOfScalar(
|
||||
PartidPtr, /*Volatile=*/false,
|
||||
C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc);
|
||||
auto *SharedsPtr = CGF.Builder.CreateStructGEP(KmpTaskTTy, TaskTypeArgAddr,
|
||||
/*Idx=*/KmpTaskTShareds);
|
||||
auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
|
||||
CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
|
||||
LValue Base =
|
||||
CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
|
||||
auto *KmpTaskTWithPrivatesQTyRD =
|
||||
cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
|
||||
Base =
|
||||
CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
|
||||
auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
|
||||
auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
|
||||
auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
|
||||
auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal();
|
||||
|
||||
auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
|
||||
auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
|
||||
auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||
CGF.EmitLoadOfScalar(SharedsPtr, /*Volatile=*/false,
|
||||
CGM.PointerAlignInBytes, C.VoidPtrTy, Loc),
|
||||
CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(),
|
||||
CGF.ConvertTypeForMem(SharedsPtrTy));
|
||||
|
||||
llvm::Value *CallArgs[] = {GtidParam, PartidParam, SharedsParam};
|
||||
|
@ -1753,15 +1766,16 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
|
|||
return TaskEntry;
|
||||
}
|
||||
|
||||
static llvm::Value *
|
||||
emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc,
|
||||
QualType KmpInt32Ty, QualType KmpTaskTPtrQTy,
|
||||
QualType KmpTaskQTy, RecordDecl *KmpTaskQTyRD) {
|
||||
static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
|
||||
SourceLocation Loc,
|
||||
QualType KmpInt32Ty,
|
||||
QualType KmpTaskTWithPrivatesPtrQTy,
|
||||
QualType KmpTaskTWithPrivatesQTy) {
|
||||
auto &C = CGM.getContext();
|
||||
FunctionArgList Args;
|
||||
ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty);
|
||||
ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc,
|
||||
/*Id=*/nullptr, KmpTaskTPtrQTy);
|
||||
/*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
|
||||
Args.push_back(&GtidArg);
|
||||
Args.push_back(&TaskTypeArg);
|
||||
FunctionType::ExtInfo Info;
|
||||
|
@ -1778,11 +1792,13 @@ emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc,
|
|||
CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
|
||||
Args);
|
||||
|
||||
auto *TaskTypeArgAddr = CGF.EmitLoadOfScalar(
|
||||
CGF.GetAddrOfLocalVar(&TaskTypeArg), /*Volatile=*/false,
|
||||
CGM.PointerAlignInBytes, KmpTaskTPtrQTy, Loc);
|
||||
LValue Base = CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskQTy);
|
||||
auto FI = std::next(KmpTaskQTyRD->field_begin(), KmpTaskTPrivates);
|
||||
auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad(
|
||||
CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes);
|
||||
LValue Base =
|
||||
CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy);
|
||||
auto *KmpTaskTWithPrivatesQTyRD =
|
||||
cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
|
||||
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
|
||||
Base = CGF.EmitLValueForField(Base, *FI);
|
||||
for (auto *Field :
|
||||
cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
|
||||
|
@ -1837,21 +1853,29 @@ void CGOpenMPRuntime::emitTaskCall(
|
|||
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
|
||||
// Build type kmp_routine_entry_t (if not built yet).
|
||||
emitKmpRoutineEntryT(KmpInt32Ty);
|
||||
// Build type kmp_task_t (if not built yet).
|
||||
if (KmpTaskTQTy.isNull()) {
|
||||
KmpTaskTQTy = C.getRecordType(
|
||||
createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy));
|
||||
}
|
||||
auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
|
||||
// Build particular struct kmp_task_t for the given task.
|
||||
auto *KmpTaskQTyRD = createKmpTaskTRecordDecl(
|
||||
CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy, Privates);
|
||||
auto KmpTaskQTy = C.getRecordType(KmpTaskQTyRD);
|
||||
QualType KmpTaskTPtrQTy = C.getPointerType(KmpTaskQTy);
|
||||
auto *KmpTaskTTy = CGF.ConvertType(KmpTaskQTy);
|
||||
auto *KmpTaskTPtrTy = KmpTaskTTy->getPointerTo();
|
||||
auto KmpTaskTySize = CGM.getSize(C.getTypeSizeInChars(KmpTaskQTy));
|
||||
auto *KmpTaskTWithPrivatesQTyRD =
|
||||
createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
|
||||
auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
|
||||
QualType KmpTaskTWithPrivatesPtrQTy =
|
||||
C.getPointerType(KmpTaskTWithPrivatesQTy);
|
||||
auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
|
||||
auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo();
|
||||
auto KmpTaskTWithPrivatesTySize =
|
||||
CGM.getSize(C.getTypeSizeInChars(KmpTaskTWithPrivatesQTy));
|
||||
QualType SharedsPtrTy = C.getPointerType(SharedsTy);
|
||||
|
||||
// Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
|
||||
// kmp_task_t *tt);
|
||||
auto *TaskEntry =
|
||||
emitProxyTaskFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy, SharedsPtrTy,
|
||||
TaskFunction, KmpTaskTTy);
|
||||
auto *TaskEntry = emitProxyTaskFunction(
|
||||
CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy,
|
||||
KmpTaskTQTy, SharedsPtrTy, TaskFunction);
|
||||
|
||||
// Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
|
||||
// kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
|
||||
|
@ -1870,29 +1894,34 @@ void CGOpenMPRuntime::emitTaskCall(
|
|||
: CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0);
|
||||
TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
|
||||
auto SharedsSize = C.getTypeSizeInChars(SharedsTy);
|
||||
llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
|
||||
getThreadID(CGF, Loc), TaskFlags, KmpTaskTySize,
|
||||
CGM.getSize(SharedsSize),
|
||||
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||
TaskEntry, KmpRoutineEntryPtrTy)};
|
||||
llvm::Value *AllocArgs[] = {
|
||||
emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), TaskFlags,
|
||||
KmpTaskTWithPrivatesTySize, CGM.getSize(SharedsSize),
|
||||
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskEntry,
|
||||
KmpRoutineEntryPtrTy)};
|
||||
auto *NewTask = CGF.EmitRuntimeCall(
|
||||
createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
|
||||
auto *NewTaskNewTaskTTy =
|
||||
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(NewTask, KmpTaskTPtrTy);
|
||||
auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||
NewTask, KmpTaskTWithPrivatesPtrTy);
|
||||
LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
|
||||
KmpTaskTWithPrivatesQTy);
|
||||
LValue TDBase =
|
||||
CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
|
||||
// Fill the data in the resulting kmp_task_t record.
|
||||
// Copy shareds if there are any.
|
||||
auto *KmpTaskSharedsPtr = CGF.EmitLoadOfScalar(
|
||||
CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
|
||||
/*Idx=*/KmpTaskTShareds),
|
||||
/*Volatile=*/false, CGM.PointerAlignInBytes, SharedsPtrTy, Loc);
|
||||
if (!SharedsTy->getAsStructureType()->getDecl()->field_empty())
|
||||
llvm::Value *KmpTaskSharedsPtr = nullptr;
|
||||
if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
|
||||
KmpTaskSharedsPtr = CGF.EmitLoadOfScalar(
|
||||
CGF.EmitLValueForField(
|
||||
TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
|
||||
Loc);
|
||||
CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
|
||||
}
|
||||
// Emit initial values for private copies (if any).
|
||||
bool NeedsCleanup = false;
|
||||
if (!Privates.empty()) {
|
||||
LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, KmpTaskQTy);
|
||||
auto FI = std::next(KmpTaskQTyRD->field_begin(), KmpTaskTPrivates);
|
||||
Base = CGF.EmitLValueForField(Base, *FI);
|
||||
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
|
||||
auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
|
||||
FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
|
||||
LValue SharedsBase = CGF.MakeNaturalAlignAddrLValue(
|
||||
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||
|
@ -1903,7 +1932,7 @@ void CGOpenMPRuntime::emitTaskCall(
|
|||
for (auto &&Pair : Privates) {
|
||||
auto *VD = Pair.second.PrivateCopy;
|
||||
auto *Init = VD->getAnyInitializer();
|
||||
LValue PrivateLValue = CGF.EmitLValueForField(Base, *FI);
|
||||
LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
|
||||
if (Init) {
|
||||
if (auto *Elem = Pair.second.PrivateElemInit) {
|
||||
auto *OriginalVD = Pair.second.Original;
|
||||
|
@ -1974,17 +2003,16 @@ void CGOpenMPRuntime::emitTaskCall(
|
|||
}
|
||||
// Provide pointer to function with destructors for privates.
|
||||
llvm::Value *DestructorFn =
|
||||
NeedsCleanup
|
||||
? emitDestructorsFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy,
|
||||
KmpTaskQTy, KmpTaskQTyRD)
|
||||
: llvm::ConstantPointerNull::get(
|
||||
cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
|
||||
CGF.Builder.CreateAlignedStore(
|
||||
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DestructorFn,
|
||||
KmpRoutineEntryPtrTy),
|
||||
CGF.Builder.CreateStructGEP(KmpTaskTTy, NewTaskNewTaskTTy,
|
||||
/*Idx=*/KmpTaskTDestructors),
|
||||
CGM.PointerAlignInBytes);
|
||||
NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty,
|
||||
KmpTaskTWithPrivatesPtrQTy,
|
||||
KmpTaskTWithPrivatesQTy)
|
||||
: llvm::ConstantPointerNull::get(
|
||||
cast<llvm::PointerType>(KmpRoutineEntryPtrTy));
|
||||
LValue Destructor = CGF.EmitLValueForField(
|
||||
TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors));
|
||||
CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||
DestructorFn, KmpRoutineEntryPtrTy),
|
||||
Destructor);
|
||||
// NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
|
||||
// libcall.
|
||||
// Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
|
||||
|
|
|
@ -232,6 +232,16 @@ private:
|
|||
/// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
|
||||
llvm::Type *KmpRoutineEntryPtrTy;
|
||||
QualType KmpRoutineEntryPtrQTy;
|
||||
/// \brief Type typedef struct kmp_task {
|
||||
/// void * shareds; /**< pointer to block of pointers to
|
||||
/// shared vars */
|
||||
/// kmp_routine_entry_t routine; /**< pointer to routine to call for
|
||||
/// executing task */
|
||||
/// kmp_int32 part_id; /**< part id for the task */
|
||||
/// kmp_routine_entry_t destructors; /* pointer to function to invoke
|
||||
/// deconstructors of firstprivate C++ objects */
|
||||
/// } kmp_task_t;
|
||||
QualType KmpTaskTQTy;
|
||||
|
||||
/// \brief Build type kmp_routine_entry_t (if not built yet).
|
||||
void emitKmpRoutineEntryT(QualType KmpInt32Ty);
|
||||
|
|
|
@ -22,14 +22,15 @@ struct S {
|
|||
|
||||
volatile double g;
|
||||
|
||||
// CHECK-DAG: [[KMP_TASK_T_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, i32 (i32, i8*)* }
|
||||
// CHECK-DAG: [[S_DOUBLE_TY:%.+]] = type { double }
|
||||
// CHECK-DAG: [[CAP_MAIN_TY:%.+]] = type { [2 x i32]*, i32*, [2 x [[S_DOUBLE_TY]]]*, [[S_DOUBLE_TY]]* }
|
||||
// CHECK-DAG: [[PRIVATES_MAIN_TY:%.+]] = type {{.?}}{ [[S_DOUBLE_TY]], [2 x [[S_DOUBLE_TY]]], i32, [2 x i32]
|
||||
// CHECK-DAG: [[KMP_TASK_MAIN_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, i32 (i32, i8*)*, [[PRIVATES_MAIN_TY]] }
|
||||
// CHECK-DAG: [[KMP_TASK_MAIN_TY:%.+]] = type { [[KMP_TASK_T_TY]], [[PRIVATES_MAIN_TY]] }
|
||||
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i32 }
|
||||
// CHECK-DAG: [[CAP_TMAIN_TY:%.+]] = type { [2 x i32]*, i32*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* }
|
||||
// CHECK-DAG: [[PRIVATES_TMAIN_TY:%.+]] = type { i32, [2 x i32], [2 x [[S_INT_TY]]], [[S_INT_TY]] }
|
||||
// CHECK-DAG: [[KMP_TASK_TMAIN_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, i32 (i32, i8*)*, [[PRIVATES_TMAIN_TY]] }
|
||||
// CHECK-DAG: [[KMP_TASK_TMAIN_TY:%.+]] = type { [[KMP_TASK_T_TY]], [[PRIVATES_TMAIN_TY]] }
|
||||
template <typename T>
|
||||
T tmain() {
|
||||
S<T> ttt;
|
||||
|
@ -54,7 +55,7 @@ int main() {
|
|||
[&]() {
|
||||
// LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
|
||||
// LAMBDA: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 40, i64 8, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 4
|
||||
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
|
||||
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[PRIVATES]], i{{.+}} 0, i{{.+}} 0
|
||||
// LAMBDA: [[G_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 0
|
||||
// LAMBDA: [[G_REF:%.+]] = load double*, double** [[G_ADDR_REF]]
|
||||
|
@ -91,7 +92,7 @@ int main() {
|
|||
^{
|
||||
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
|
||||
// BLOCKS: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 40, i64 8, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 4
|
||||
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
|
||||
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[PRIVATES]], i{{.+}} 0, i{{.+}} 0
|
||||
// BLOCKS: [[G_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 0
|
||||
// BLOCKS: [[G_REF:%.+]] = load double*, double** [[G_ADDR_REF]]
|
||||
|
@ -159,24 +160,22 @@ int main() {
|
|||
|
||||
// Allocate task.
|
||||
// Returns struct kmp_task_t {
|
||||
// void * shareds;
|
||||
// kmp_routine_entry_t routine;
|
||||
// kmp_int32 part_id;
|
||||
// kmp_routine_entry_t destructors;
|
||||
// [[KMP_TASK_T]] task_data;
|
||||
// [[KMP_TASK_MAIN_TY]] privates;
|
||||
// };
|
||||
// CHECK: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc([[LOC]], i32 [[GTID]], i32 1, i64 72, i64 32, i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// CHECK: [[RES_KMP_TASK:%.+]] = bitcast i8* [[RES]] to [[KMP_TASK_MAIN_TY]]*
|
||||
|
||||
// Fill kmp_task_t->shareds by copying from original capture argument.
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
|
||||
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
|
||||
|
||||
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
|
||||
// Also copy address of private copy to the corresponding shareds reference.
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_MAIN_TY]]*
|
||||
|
||||
// Constructors for s_arr and var.
|
||||
|
@ -225,7 +224,7 @@ int main() {
|
|||
// CHECK: store [2 x i32]* [[PRIVATE_VEC_REF]], [2 x i32]** [[VEC_ADDR_REF]],
|
||||
|
||||
// Provide pointer to destructor function, which will destroy private variables at the end of the task.
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_REF]],
|
||||
|
||||
// Start task.
|
||||
|
@ -243,7 +242,8 @@ int main() {
|
|||
//
|
||||
// CHECK: define internal i32 [[TASK_ENTRY]](i32, [[KMP_TASK_MAIN_TY]]*)
|
||||
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_ADDR_REF]],
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_MAIN_TY]]*
|
||||
|
||||
|
@ -256,7 +256,7 @@ int main() {
|
|||
// CHECK: ret
|
||||
|
||||
// CHECK: define internal i32 [[DESTRUCTORS]](i32, [[KMP_TASK_MAIN_TY]]*)
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[PRIVATE_VAR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[PRIVATE_S_ARR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 1
|
||||
// CHECK: getelementptr inbounds [2 x [[S_DOUBLE_TY]]], [2 x [[S_DOUBLE_TY]]]* [[PRIVATE_S_ARR_REF]], i{{.+}} 0, i{{.+}} 0
|
||||
|
@ -291,23 +291,21 @@ int main() {
|
|||
|
||||
// Allocate task.
|
||||
// Returns struct kmp_task_t {
|
||||
// void * shareds;
|
||||
// kmp_routine_entry_t routine;
|
||||
// kmp_int32 part_id;
|
||||
// kmp_routine_entry_t destructors;
|
||||
// [[KMP_TASK_T_TY]] task_data;
|
||||
// [[KMP_TASK_TMAIN_TY]] privates;
|
||||
// };
|
||||
// CHECK: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc([[LOC]], i32 [[GTID]], i32 1, i64 56, i64 32, i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// CHECK: [[RES_KMP_TASK:%.+]] = bitcast i8* [[RES]] to [[KMP_TASK_TMAIN_TY]]*
|
||||
|
||||
// Fill kmp_task_t->shareds by copying from original capture argument.
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
|
||||
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
|
||||
|
||||
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_TMAIN_TY]]*
|
||||
|
||||
// t_var;
|
||||
|
@ -355,7 +353,7 @@ int main() {
|
|||
// CHECK: store [[S_INT_TY]]* [[PRIVATE_VAR_REF]], [[S_INT_TY]]** [[VAR_ADDR_REF]],
|
||||
|
||||
// Provide pointer to destructor function, which will destroy private variables at the end of the task.
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_REF]],
|
||||
|
||||
// Start task.
|
||||
|
@ -372,7 +370,8 @@ int main() {
|
|||
// CHECK: define internal i32 [[TASK_ENTRY]](i32, [[KMP_TASK_TMAIN_TY]]*)
|
||||
|
||||
// Substitute addresses of shared variables in capture struct by address of private copies from kmp_task_t.
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_ADDR_REF]],
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_TMAIN_TY]]*
|
||||
|
||||
|
@ -385,7 +384,7 @@ int main() {
|
|||
// CHECK: ret
|
||||
|
||||
// CHECK: define internal i32 [[DESTRUCTORS]](i32, [[KMP_TASK_TMAIN_TY]]*)
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[PRIVATE_S_ARR_REF:%.+]] = getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
|
||||
// CHECK: [[PRIVATE_VAR_REF:%.+]] = getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[PRIVATE_VAR_REF]])
|
||||
|
|
|
@ -22,14 +22,15 @@ struct S {
|
|||
|
||||
volatile double g;
|
||||
|
||||
// CHECK-DAG: [[KMP_TASK_T_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, i32 (i32, i8*)* }
|
||||
// CHECK-DAG: [[S_DOUBLE_TY:%.+]] = type { double }
|
||||
// CHECK-DAG: [[CAP_MAIN_TY:%.+]] = type { [2 x i32]*, i32*, [2 x [[S_DOUBLE_TY]]]*, [[S_DOUBLE_TY]]* }
|
||||
// CHECK-DAG: [[PRIVATES_MAIN_TY:%.+]] = type {{.?}}{ [[S_DOUBLE_TY]], [2 x [[S_DOUBLE_TY]]], i32, [2 x i32]
|
||||
// CHECK-DAG: [[KMP_TASK_MAIN_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, i32 (i32, i8*)*, [[PRIVATES_MAIN_TY]] }
|
||||
// CHECK-DAG: [[KMP_TASK_MAIN_TY:%.+]] = type { [[KMP_TASK_T_TY]], [[PRIVATES_MAIN_TY]] }
|
||||
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i32 }
|
||||
// CHECK-DAG: [[CAP_TMAIN_TY:%.+]] = type { [2 x i32]*, i32*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* }
|
||||
// CHECK-DAG: [[PRIVATES_TMAIN_TY:%.+]] = type { i32, [2 x i32], [2 x [[S_INT_TY]]], [[S_INT_TY]] }
|
||||
// CHECK-DAG: [[KMP_TASK_TMAIN_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, i32 (i32, i8*)*, [[PRIVATES_TMAIN_TY]] }
|
||||
// CHECK-DAG: [[KMP_TASK_TMAIN_TY:%.+]] = type { [[KMP_TASK_T_TY]], [[PRIVATES_TMAIN_TY]] }
|
||||
template <typename T>
|
||||
T tmain() {
|
||||
S<T> test;
|
||||
|
@ -53,7 +54,7 @@ int main() {
|
|||
[&]() {
|
||||
// LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
|
||||
// LAMBDA: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 40, i64 8, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 4
|
||||
// LAMBDA: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
|
||||
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[PRIVATES]], i{{.+}} 0, i{{.+}} 0
|
||||
// LAMBDA: [[G_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 0
|
||||
// LAMBDA: store double* [[G_PRIVATE_ADDR]], double** [[G_ADDR_REF]],
|
||||
|
@ -86,7 +87,7 @@ int main() {
|
|||
^{
|
||||
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
|
||||
// BLOCKS: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{[^ ]+}} @{{[^,]+}}, i32 %{{[^,]+}}, i32 1, i64 40, i64 8, i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 4
|
||||
// BLOCKS: [[PRIVATES:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 1
|
||||
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[PRIVATES]], i{{.+}} 0, i{{.+}} 0
|
||||
// BLOCKS: [[G_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* %{{.+}}, i{{.+}} 0, i{{.+}} 0
|
||||
// BLOCKS: store double* [[G_PRIVATE_ADDR]], double** [[G_ADDR_REF]],
|
||||
|
@ -148,24 +149,22 @@ int main() {
|
|||
|
||||
// Allocate task.
|
||||
// Returns struct kmp_task_t {
|
||||
// void * shareds;
|
||||
// kmp_routine_entry_t routine;
|
||||
// kmp_int32 part_id;
|
||||
// kmp_routine_entry_t destructors;
|
||||
// [[KMP_TASK_T_TY]] task_data;
|
||||
// [[KMP_TASK_MAIN_TY]] privates;
|
||||
// };
|
||||
// CHECK: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc([[LOC]], i32 [[GTID]], i32 1, i64 72, i64 32, i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// CHECK: [[RES_KMP_TASK:%.+]] = bitcast i8* [[RES]] to [[KMP_TASK_MAIN_TY]]*
|
||||
|
||||
// Fill kmp_task_t->shareds by copying from original capture argument.
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
|
||||
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_MAIN_TY]]* %{{.+}} to i8*
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
|
||||
|
||||
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
|
||||
// Also copy address of private copy to the corresponding shareds reference.
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_MAIN_TY]]*
|
||||
|
||||
// Constructors for s_arr and var.
|
||||
|
@ -201,7 +200,7 @@ int main() {
|
|||
// CHECK: store [2 x i32]* [[PRIVATE_VEC_REF]], [2 x i32]** [[VEC_ADDR_REF]],
|
||||
|
||||
// Provide pointer to destructor function, which will destroy private variables at the end of the task.
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_MAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_REF]],
|
||||
|
||||
// Start task.
|
||||
|
@ -219,7 +218,8 @@ int main() {
|
|||
//
|
||||
// CHECK: define internal i32 [[TASK_ENTRY]](i32, [[KMP_TASK_MAIN_TY]]*)
|
||||
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_ADDR_REF]],
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_MAIN_TY]]*
|
||||
|
||||
|
@ -232,7 +232,7 @@ int main() {
|
|||
// CHECK: ret
|
||||
|
||||
// CHECK: define internal i32 [[DESTRUCTORS]](i32, [[KMP_TASK_MAIN_TY]]*)
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_MAIN_TY]], [[KMP_TASK_MAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[PRIVATE_VAR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[PRIVATE_S_ARR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 1
|
||||
// CHECK: getelementptr inbounds [2 x [[S_DOUBLE_TY]]], [2 x [[S_DOUBLE_TY]]]* [[PRIVATE_S_ARR_REF]], i{{.+}} 0, i{{.+}} 0
|
||||
|
@ -266,23 +266,21 @@ int main() {
|
|||
|
||||
// Allocate task.
|
||||
// Returns struct kmp_task_t {
|
||||
// void * shareds;
|
||||
// kmp_routine_entry_t routine;
|
||||
// kmp_int32 part_id;
|
||||
// kmp_routine_entry_t destructors;
|
||||
// [[KMP_TASK_T_TY]] task_data;
|
||||
// [[KMP_TASK_TMAIN_TY]] privates;
|
||||
// };
|
||||
// CHECK: [[RES:%.+]] = call i8* @__kmpc_omp_task_alloc([[LOC]], i32 [[GTID]], i32 1, i64 56, i64 32, i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[TASK_ENTRY:@[^ ]+]] to i32 (i32, i8*)*))
|
||||
// CHECK: [[RES_KMP_TASK:%.+]] = bitcast i8* [[RES]] to [[KMP_TASK_TMAIN_TY]]*
|
||||
|
||||
// Fill kmp_task_t->shareds by copying from original capture argument.
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF_ADDR:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_REF_ADDR]],
|
||||
// CHECK: [[CAPTURES_ADDR:%.+]] = bitcast [[CAP_TMAIN_TY]]* %{{.+}} to i8*
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[CAPTURES_ADDR]], i64 32, i32 8, i1 false)
|
||||
|
||||
// Initialize kmp_task_t->privates with default values (no init for simple types, default constructors for classes).
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_TMAIN_TY]]*
|
||||
|
||||
// shareds->t_var_addr = &kmp_task_t->privates.t_var;
|
||||
|
@ -318,7 +316,7 @@ int main() {
|
|||
// CHECK: store [[S_INT_TY]]* [[PRIVATE_VAR_REF]], [[S_INT_TY]]** [[VAR_ADDR_REF]],
|
||||
|
||||
// Provide pointer to destructor function, which will destroy private variables at the end of the task.
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: [[DESTRUCTORS_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: store i32 (i32, i8*)* bitcast (i32 (i32, [[KMP_TASK_TMAIN_TY]]*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** [[DESTRUCTORS_REF]],
|
||||
|
||||
// Start task.
|
||||
|
@ -335,7 +333,8 @@ int main() {
|
|||
// CHECK: define internal i32 [[TASK_ENTRY]](i32, [[KMP_TASK_TMAIN_TY]]*)
|
||||
|
||||
// Substitute addresses of shared variables in capture struct by address of private copies from kmp_task_t.
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[TASK:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||
// CHECK: [[SHAREDS_ADDR_REF:%.+]] = getelementptr inbounds [[KMP_TASK_T_TY]], [[KMP_TASK_T_TY]]* [[TASK]], i{{.+}} 0, i{{.+}} 0
|
||||
// CHECK: [[SHAREDS_REF:%.+]] = load i8*, i8** [[SHAREDS_ADDR_REF]],
|
||||
// CHECK: [[SHAREDS:%.+]] = bitcast i8* [[SHAREDS_REF]] to [[CAP_TMAIN_TY]]*
|
||||
|
||||
|
@ -348,7 +347,7 @@ int main() {
|
|||
// CHECK: ret
|
||||
|
||||
// CHECK: define internal i32 [[DESTRUCTORS]](i32, [[KMP_TASK_TMAIN_TY]]*)
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 4
|
||||
// CHECK: [[PRIVATES:%.+]] = getelementptr inbounds [[KMP_TASK_TMAIN_TY]], [[KMP_TASK_TMAIN_TY]]* [[RES_KMP_TASK:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||
// CHECK: [[PRIVATE_S_ARR_REF:%.+]] = getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
|
||||
// CHECK: [[PRIVATE_VAR_REF:%.+]] = getelementptr inbounds [[PRIVATES_TMAIN_TY]], [[PRIVATES_TMAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 3
|
||||
// CHECK: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[PRIVATE_VAR_REF]])
|
||||
|
|
Loading…
Reference in New Issue