summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGOpenMPRuntime.cpp
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2016-05-05 08:46:22 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2016-05-05 08:46:22 +0000
commitf93095a0035e58b33db1cb6e96fd517cd982727c (patch)
tree6d843960c9985b6c4ccb2ab451edde6de499130d /clang/lib/CodeGen/CGOpenMPRuntime.cpp
parentc14e8ced85ecaa4d6c65d91107d583c6b60fb25b (diff)
downloadbcm5719-llvm-f93095a0035e58b33db1cb6e96fd517cd982727c.tar.gz
bcm5719-llvm-f93095a0035e58b33db1cb6e96fd517cd982727c.zip
[OPENMP 4.5] Codegen for 'lastprivate' clauses in 'taskloop' directives.
OpenMP 4.5 adds taskloop/taskloop simd directives. These directives allow to use lastprivate clause. Patch adds codegen for this clause. llvm-svn: 268618
Diffstat (limited to 'clang/lib/CodeGen/CGOpenMPRuntime.cpp')
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp286
1 files changed, 211 insertions, 75 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index b280d53dd39..edb9ddad794 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -3292,6 +3292,7 @@ static llvm::Value *
emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
ArrayRef<const Expr *> PrivateVars,
ArrayRef<const Expr *> FirstprivateVars,
+ ArrayRef<const Expr *> LastprivateVars,
QualType PrivatesQTy,
ArrayRef<PrivateDataTy> Privates) {
auto &C = CGM.getContext();
@@ -3322,6 +3323,16 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
PrivateVarsPos[VD] = Counter;
++Counter;
}
+ for (auto *E: LastprivateVars) {
+ Args.push_back(ImplicitParamDecl::Create(
+ C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType()))
+ .withConst()
+ .withRestrict()));
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ PrivateVarsPos[VD] = Counter;
+ ++Counter;
+ }
auto &TaskPrivatesMapFnInfo =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
auto *TaskPrivatesMapTy =
@@ -3361,6 +3372,179 @@ static int array_pod_sort_comparator(const PrivateDataTy *P1,
return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
}
+/// Emit initialization for private variables in task-based directives.
+/// \return true if cleanups are required, false otherwise.
+static bool emitPrivatesInit(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ Address KmpTaskSharedsPtr, LValue TDBase,
+ const RecordDecl *KmpTaskTWithPrivatesQTyRD,
+ QualType SharedsTy, QualType SharedsPtrTy,
+ const OMPTaskDataTy &Data,
+ ArrayRef<PrivateDataTy> Privates, bool ForDup) {
+ auto &C = CGF.getContext();
+ bool NeedsCleanup = false;
+ auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
+ LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
+ LValue SrcBase;
+ if (!Data.FirstprivateVars.empty()) {
+ SrcBase = CGF.MakeAddrLValue(
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
+ SharedsTy);
+ }
+ CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
+ cast<CapturedStmt>(*D.getAssociatedStmt()));
+ FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
+ for (auto &&Pair : Privates) {
+ auto *VD = Pair.second.PrivateCopy;
+ auto *Init = VD->getAnyInitializer();
+ LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
+ if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
+ !CGF.isTrivialInitializer(Init)))) {
+ if (auto *Elem = Pair.second.PrivateElemInit) {
+ auto *OriginalVD = Pair.second.Original;
+ auto *SharedField = CapturesInfo.lookup(OriginalVD);
+ auto SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
+ SharedRefLValue = CGF.MakeAddrLValue(
+ Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
+ SharedRefLValue.getType(), AlignmentSource::Decl);
+ QualType Type = OriginalVD->getType();
+ if (Type->isArrayType()) {
+ // Initialize firstprivate array.
+ if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
+ // Perform simple memcpy.
+ CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
+ SharedRefLValue.getAddress(), Type);
+ } else {
+ // Initialize firstprivate array using element-by-element
+ // intialization.
+ CGF.EmitOMPAggregateAssign(
+ PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
+ [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
+ Address SrcElement) {
+ // Clean up any temporaries needed by the initialization.
+ CodeGenFunction::OMPPrivateScope InitScope(CGF);
+ InitScope.addPrivate(
+ Elem, [SrcElement]() -> Address { return SrcElement; });
+ (void)InitScope.Privatize();
+ // Emit initialization for single element.
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
+ CGF, &CapturesInfo);
+ CGF.EmitAnyExprToMem(Init, DestElement,
+ Init->getType().getQualifiers(),
+ /*IsInitializer=*/false);
+ });
+ }
+ } else {
+ CodeGenFunction::OMPPrivateScope InitScope(CGF);
+ InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
+ return SharedRefLValue.getAddress();
+ });
+ (void)InitScope.Privatize();
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
+ CGF.EmitExprAsInit(Init, VD, PrivateLValue,
+ /*capturedByInit=*/false);
+ }
+ } else
+ CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
+ }
+ NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
+ ++FI;
+ }
+ return NeedsCleanup;
+}
+
+/// Check if duplication function is required for taskloops.
+static bool checkInitIsRequired(CodeGenFunction &CGF,
+ ArrayRef<PrivateDataTy> Privates) {
+ bool InitRequired = false;
+ for (auto &&Pair : Privates) {
+ auto *VD = Pair.second.PrivateCopy;
+ auto *Init = VD->getAnyInitializer();
+ InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
+ !CGF.isTrivialInitializer(Init));
+ }
+ return InitRequired;
+}
+
+
+/// Emit task_dup function (for initialization of
+/// private/firstprivate/lastprivate vars and last_iter flag)
+/// \code
+/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
+/// lastpriv) {
+/// // setup lastprivate flag
+/// task_dst->last = lastpriv;
+/// // could be constructor calls here...
+/// }
+/// \endcode
+static llvm::Value *
+emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
+ const OMPExecutableDirective &D,
+ QualType KmpTaskTWithPrivatesPtrQTy,
+ const RecordDecl *KmpTaskTWithPrivatesQTyRD,
+ const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
+ QualType SharedsPtrTy, const OMPTaskDataTy &Data,
+ ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
+ auto &C = CGM.getContext();
+ FunctionArgList Args;
+ ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
+ ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy);
+ ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc,
+ /*Id=*/nullptr, C.IntTy);
+ Args.push_back(&DstArg);
+ Args.push_back(&SrcArg);
+ Args.push_back(&LastprivArg);
+ auto &TaskDupFnInfo =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ auto *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
+ auto *TaskDup =
+ llvm::Function::Create(TaskDupTy, llvm::GlobalValue::InternalLinkage,
+ ".omp_task_dup.", &CGM.getModule());
+ CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskDup, TaskDupFnInfo);
+ CodeGenFunction CGF(CGM);
+ CGF.disableDebugInfo();
+ CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args);
+
+ LValue TDBase = CGF.EmitLoadOfPointerLValue(
+ CGF.GetAddrOfLocalVar(&DstArg),
+ KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
+ // task_dst->liter = lastpriv;
+ if (WithLastIter) {
+ auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
+ LValue Base = CGF.EmitLValueForField(
+ TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
+ LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
+ llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
+ CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
+ CGF.EmitStoreOfScalar(Lastpriv, LILVal);
+ }
+
+ // Emit initial values for private copies (if any).
+ assert(!Privates.empty());
+ Address KmpTaskSharedsPtr = Address::invalid();
+ if (!Data.FirstprivateVars.empty()) {
+ LValue TDBase = CGF.EmitLoadOfPointerLValue(
+ CGF.GetAddrOfLocalVar(&SrcArg),
+ KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
+ LValue Base = CGF.EmitLValueForField(
+ TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
+ KmpTaskSharedsPtr = Address(
+ CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
+ Base, *std::next(KmpTaskTQTyRD->field_begin(),
+ KmpTaskTShareds)),
+ Loc),
+ CGF.getNaturalTypeAlignment(SharedsTy));
+ }
+ (void)emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase,
+ KmpTaskTWithPrivatesQTyRD, SharedsTy, SharedsPtrTy,
+ Data, Privates, /*ForDup=*/true);
+ CGF.FinishFunction();
+ return TaskDup;
+}
+
CGOpenMPRuntime::TaskResultTy
CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
const OMPExecutableDirective &D,
@@ -3390,6 +3574,15 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
++I;
++IElemInitRef;
}
+ I = Data.LastprivateCopies.begin();
+ for (auto *E : Data.LastprivateVars) {
+ auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Privates.push_back(std::make_pair(
+ C.getDeclAlign(VD),
+ PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
+ /*PrivateElemInit=*/nullptr)));
+ ++I;
+ }
llvm::array_pod_sort(Privates.begin(), Privates.end(),
array_pod_sort_comparator);
auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
@@ -3420,9 +3613,9 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
->getType();
if (!Privates.empty()) {
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
- TaskPrivatesMap = emitTaskPrivateMappingFunction(CGM, Loc, Data.PrivateVars,
- Data.FirstprivateVars,
- FI->getType(), Privates);
+ TaskPrivatesMap = emitTaskPrivateMappingFunction(
+ CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
+ FI->getType(), Privates);
TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
TaskPrivatesMap, TaskPrivatesMapTy);
} else {
@@ -3480,78 +3673,19 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy);
}
// Emit initial values for private copies (if any).
+ TaskResultTy Result;
bool NeedsCleanup = false;
if (!Privates.empty()) {
- auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
- auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
- FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
- LValue SharedsBase;
- if (!Data.FirstprivateVars.empty()) {
- SharedsBase = CGF.MakeAddrLValue(
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
- SharedsTy);
- }
- CodeGenFunction::CGCapturedStmtInfo CapturesInfo(
- cast<CapturedStmt>(*D.getAssociatedStmt()));
- for (auto &&Pair : Privates) {
- auto *VD = Pair.second.PrivateCopy;
- auto *Init = VD->getAnyInitializer();
- LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
- if (Init) {
- if (auto *Elem = Pair.second.PrivateElemInit) {
- auto *OriginalVD = Pair.second.Original;
- auto *SharedField = CapturesInfo.lookup(OriginalVD);
- auto SharedRefLValue =
- CGF.EmitLValueForField(SharedsBase, SharedField);
- SharedRefLValue = CGF.MakeAddrLValue(
- Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
- SharedRefLValue.getType(), AlignmentSource::Decl);
- QualType Type = OriginalVD->getType();
- if (Type->isArrayType()) {
- // Initialize firstprivate array.
- if (!isa<CXXConstructExpr>(Init) ||
- CGF.isTrivialInitializer(Init)) {
- // Perform simple memcpy.
- CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
- SharedRefLValue.getAddress(), Type);
- } else {
- // Initialize firstprivate array using element-by-element
- // intialization.
- CGF.EmitOMPAggregateAssign(
- PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
- Type, [&CGF, Elem, Init, &CapturesInfo](
- Address DestElement, Address SrcElement) {
- // Clean up any temporaries needed by the initialization.
- CodeGenFunction::OMPPrivateScope InitScope(CGF);
- InitScope.addPrivate(Elem, [SrcElement]() -> Address {
- return SrcElement;
- });
- (void)InitScope.Privatize();
- // Emit initialization for single element.
- CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
- CGF, &CapturesInfo);
- CGF.EmitAnyExprToMem(Init, DestElement,
- Init->getType().getQualifiers(),
- /*IsInitializer=*/false);
- });
- }
- } else {
- CodeGenFunction::OMPPrivateScope InitScope(CGF);
- InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
- return SharedRefLValue.getAddress();
- });
- (void)InitScope.Privatize();
- CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
- CGF.EmitExprAsInit(Init, VD, PrivateLValue,
- /*capturedByInit=*/false);
- }
- } else {
- CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
- }
- }
- NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType();
- ++FI;
+ NeedsCleanup = emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base,
+ KmpTaskTWithPrivatesQTyRD, SharedsTy,
+ SharedsPtrTy, Data, Privates,
+ /*ForDup=*/false);
+ if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
+ (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
+ Result.TaskDupFn = emitTaskDupFunction(
+ CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
+ KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
+ /*WithLastIter=*/!Data.LastprivateVars.empty());
}
}
// Provide pointer to function with destructors for privates.
@@ -3566,7 +3700,6 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
DestructorFn, KmpRoutineEntryPtrTy),
Destructor);
- TaskResultTy Result;
Result.NewTask = NewTask;
Result.TaskEntry = TaskEntry;
Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
@@ -3823,7 +3956,10 @@ void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
/*isSigned=*/false)
: llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
- llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
+ Result.TaskDupFn
+ ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Result.TaskDupFn,
+ CGF.VoidPtrTy)
+ : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
}
OpenPOWER on IntegriCloud