[OPENMP50]Handle lastprivate conditionals passed as shared in inner
regions.
If the lastprivate conditional is passed as shared in inner region, we
shall check if it was ever changed and use this updated value after exit
from the inner region as an update value.
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 9150d3b..cbe1bfc 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1801,16 +1801,17 @@
OpenMPLocThreadIDMap.erase(CGF.CurFn);
}
if (FunctionUDRMap.count(CGF.CurFn) > 0) {
- for(auto *D : FunctionUDRMap[CGF.CurFn])
+ for(const auto *D : FunctionUDRMap[CGF.CurFn])
UDRMap.erase(D);
FunctionUDRMap.erase(CGF.CurFn);
}
auto I = FunctionUDMMap.find(CGF.CurFn);
if (I != FunctionUDMMap.end()) {
- for(auto *D : I->second)
+ for(const auto *D : I->second)
UDMMap.erase(D);
FunctionUDMMap.erase(I);
}
+ LastprivateConditionalToTypes.erase(CGF.CurFn);
}
llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
@@ -11333,17 +11334,101 @@
[VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
}
+void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
+ const OMPExecutableDirective &S,
+ llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled)
+ const {
+ llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
+ // Vars in target/task regions must be excluded completely.
+ if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) ||
+ isOpenMPTaskingDirective(S.getDirectiveKind())) {
+ SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+ getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind());
+ const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
+ for (const CapturedStmt::Capture &Cap : CS->captures()) {
+ if (Cap.capturesVariable() || Cap.capturesVariableByCopy())
+ NeedToCheckForLPCs.insert(Cap.getCapturedVar());
+ }
+ }
+ // Exclude vars in private clauses.
+ for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ NeedToCheckForLPCs.insert(DRE->getDecl());
+ }
+ }
+ for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ NeedToCheckForLPCs.insert(DRE->getDecl());
+ }
+ }
+ for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ NeedToCheckForLPCs.insert(DRE->getDecl());
+ }
+ }
+ for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ NeedToCheckForLPCs.insert(DRE->getDecl());
+ }
+ }
+ for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ NeedToCheckForLPCs.insert(DRE->getDecl());
+ }
+ }
+ for (const Decl *VD : NeedToCheckForLPCs) {
+ for (const LastprivateConditionalData &Data :
+ llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
+ if (Data.DeclToUniqueName.count(VD) > 0) {
+ if (!Data.Disabled)
+ NeedToAddForLPCsAsDisabled.insert(VD);
+ break;
+ }
+ }
+ }
+}
+
CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal)
: CGM(CGF.CGM),
- NeedToPush(llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
- [](const OMPLastprivateClause *C) {
- return C->getKind() ==
- OMPC_LASTPRIVATE_conditional;
- })) {
+ Action((CGM.getLangOpts().OpenMP >= 50 &&
+ llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
+ [](const OMPLastprivateClause *C) {
+ return C->getKind() ==
+ OMPC_LASTPRIVATE_conditional;
+ }))
+ ? ActionToDo::PushAsLastprivateConditional
+ : ActionToDo::DoNotPush) {
assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
- if (!NeedToPush)
+ if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
return;
+ assert(Action == ActionToDo::PushAsLastprivateConditional &&
+ "Expected a push action.");
LastprivateConditionalData &Data =
CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
@@ -11351,60 +11436,136 @@
continue;
for (const Expr *Ref : C->varlists()) {
- Data.DeclToUniqeName.try_emplace(
+ Data.DeclToUniqueName.insert(std::make_pair(
cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
- generateUniqueName(CGM, "pl_cond", Ref));
+ SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref))));
}
}
Data.IVLVal = IVLVal;
- Data.CGF = &CGF;
+ Data.Fn = CGF.CurFn;
+}
+
+CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
+ CodeGenFunction &CGF, const OMPExecutableDirective &S)
+ : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) {
+ assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
+ if (CGM.getLangOpts().OpenMP < 50)
+ return;
+ llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
+ tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
+ if (!NeedToAddForLPCsAsDisabled.empty()) {
+ Action = ActionToDo::DisableLastprivateConditional;
+ LastprivateConditionalData &Data =
+ CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
+ for (const Decl *VD : NeedToAddForLPCsAsDisabled)
+ Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>()));
+ Data.Fn = CGF.CurFn;
+ Data.Disabled = true;
+ }
+}
+
+CGOpenMPRuntime::LastprivateConditionalRAII
+CGOpenMPRuntime::LastprivateConditionalRAII::disable(
+ CodeGenFunction &CGF, const OMPExecutableDirective &S) {
+ return LastprivateConditionalRAII(CGF, S);
}
CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() {
- if (!NeedToPush)
+ if (CGM.getLangOpts().OpenMP < 50)
return;
- CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
+ if (Action == ActionToDo::DisableLastprivateConditional) {
+ assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
+ "Expected list of disabled private vars.");
+ CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
+ }
+ if (Action == ActionToDo::PushAsLastprivateConditional) {
+ assert(
+ !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
+ "Expected list of lastprivate conditional vars.");
+ CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
+ }
+}
+
+Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
+ const VarDecl *VD) {
+ ASTContext &C = CGM.getContext();
+ auto I = LastprivateConditionalToTypes.find(CGF.CurFn);
+ if (I == LastprivateConditionalToTypes.end())
+ I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first;
+ QualType NewType;
+ const FieldDecl *VDField;
+ const FieldDecl *FiredField;
+ LValue BaseLVal;
+ auto VI = I->getSecond().find(VD);
+ if (VI == I->getSecond().end()) {
+ RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional");
+ RD->startDefinition();
+ VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
+ FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
+ RD->completeDefinition();
+ NewType = C.getRecordType(RD);
+ Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
+ BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
+ I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
+ } else {
+ NewType = std::get<0>(VI->getSecond());
+ VDField = std::get<1>(VI->getSecond());
+ FiredField = std::get<2>(VI->getSecond());
+ BaseLVal = std::get<3>(VI->getSecond());
+ }
+ LValue FiredLVal =
+ CGF.EmitLValueForField(BaseLVal, FiredField);
+ CGF.EmitStoreOfScalar(
+ llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)),
+ FiredLVal);
+ return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF);
}
namespace {
/// Checks if the lastprivate conditional variable is referenced in LHS.
class LastprivateConditionalRefChecker final
: public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> {
- CodeGenFunction &CGF;
ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM;
const Expr *FoundE = nullptr;
const Decl *FoundD = nullptr;
StringRef UniqueDeclName;
LValue IVLVal;
+ llvm::Function *FoundFn = nullptr;
SourceLocation Loc;
public:
bool VisitDeclRefExpr(const DeclRefExpr *E) {
for (const CGOpenMPRuntime::LastprivateConditionalData &D :
llvm::reverse(LPM)) {
- auto It = D.DeclToUniqeName.find(E->getDecl());
- if (It == D.DeclToUniqeName.end())
+ auto It = D.DeclToUniqueName.find(E->getDecl());
+ if (It == D.DeclToUniqueName.end())
continue;
+ if (D.Disabled)
+ return false;
FoundE = E;
FoundD = E->getDecl()->getCanonicalDecl();
- UniqueDeclName = It->getSecond();
+ UniqueDeclName = It->second;
IVLVal = D.IVLVal;
+ FoundFn = D.Fn;
break;
}
return FoundE == E;
}
bool VisitMemberExpr(const MemberExpr *E) {
- if (!CGF.IsWrappedCXXThis(E->getBase()))
+ if (!CodeGenFunction::IsWrappedCXXThis(E->getBase()))
return false;
for (const CGOpenMPRuntime::LastprivateConditionalData &D :
llvm::reverse(LPM)) {
- auto It = D.DeclToUniqeName.find(E->getMemberDecl());
- if (It == D.DeclToUniqeName.end())
+ auto It = D.DeclToUniqueName.find(E->getMemberDecl());
+ if (It == D.DeclToUniqueName.end())
continue;
+ if (D.Disabled)
+ return false;
FoundE = E;
FoundD = E->getMemberDecl()->getCanonicalDecl();
- UniqueDeclName = It->getSecond();
+ UniqueDeclName = It->second;
IVLVal = D.IVLVal;
+ FoundFn = D.Fn;
break;
}
return FoundE == E;
@@ -11422,30 +11583,20 @@
return false;
}
explicit LastprivateConditionalRefChecker(
- CodeGenFunction &CGF,
ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
- : CGF(CGF), LPM(LPM) {}
- std::tuple<const Expr *, const Decl *, StringRef, LValue>
+ : LPM(LPM) {}
+ std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
getFoundData() const {
- return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal);
+ return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
}
};
} // namespace
-void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
- const Expr *LHS) {
- if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty() ||
- LastprivateConditionalStack.back().CGF != &CGF)
- return;
- LastprivateConditionalRefChecker Checker(CGF, LastprivateConditionalStack);
- if (!Checker.Visit(LHS))
- return;
- const Expr *FoundE;
- const Decl *FoundD;
- StringRef UniqueDeclName;
- LValue IVLVal;
- std::tie(FoundE, FoundD, UniqueDeclName, IVLVal) = Checker.getFoundData();
-
+void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF,
+ LValue IVLVal,
+ StringRef UniqueDeclName,
+ LValue LVal,
+ SourceLocation Loc) {
// Last updated loop counter for the lastprivate conditional var.
// int<xx> last_iv = 0;
llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType());
@@ -11455,21 +11606,18 @@
IVLVal.getAlignment().getAsAlign());
LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType());
- // Private address of the lastprivate conditional in the current context.
- // priv_a
- LValue LVal = CGF.EmitLValue(FoundE);
// Last value of the lastprivate conditional.
// decltype(priv_a) last_a;
llvm::Constant *Last = getOrCreateInternalVariable(
- LVal.getAddress(CGF).getElementType(), UniqueDeclName);
+ CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName);
cast<llvm::GlobalVariable>(Last)->setAlignment(
LVal.getAlignment().getAsAlign());
LValue LastLVal =
CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment());
// Global loop counter. Required to handle inner parallel-for regions.
- // global_iv
- llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, FoundE->getExprLoc());
+ // iv
+ llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc);
// #pragma omp critical(a)
// if (last_iv <= iv) {
@@ -11477,11 +11625,10 @@
// last_a = priv_a;
// }
auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
- FoundE](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
- llvm::Value *LastIVVal =
- CGF.EmitLoadOfScalar(LastIVLVal, FoundE->getExprLoc());
- // (last_iv <= global_iv) ? Check if the variable is updated and store new
+ llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc);
+ // (last_iv <= iv) ? Check if the variable is updated and store new
// value in global var.
llvm::Value *CmpRes;
if (IVLVal.getType()->isSignedIntegerType()) {
@@ -11497,19 +11644,18 @@
// {
CGF.EmitBlock(ThenBB);
- // last_iv = global_iv;
+ // last_iv = iv;
CGF.EmitStoreOfScalar(IVVal, LastIVLVal);
// last_a = priv_a;
switch (CGF.getEvaluationKind(LVal.getType())) {
case TEK_Scalar: {
- llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, FoundE->getExprLoc());
+ llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc);
CGF.EmitStoreOfScalar(PrivVal, LastLVal);
break;
}
case TEK_Complex: {
- CodeGenFunction::ComplexPairTy PrivVal =
- CGF.EmitLoadOfComplex(LVal, FoundE->getExprLoc());
+ CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc);
CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false);
break;
}
@@ -11529,7 +11675,100 @@
RegionCodeGenTy ThenRCG(CodeGen);
ThenRCG(CGF);
} else {
- emitCriticalRegion(CGF, UniqueDeclName, CodeGen, FoundE->getExprLoc());
+ emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc);
+ }
+}
+
+void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
+ const Expr *LHS) {
+ if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
+ return;
+ LastprivateConditionalRefChecker Checker(LastprivateConditionalStack);
+ if (!Checker.Visit(LHS))
+ return;
+ const Expr *FoundE;
+ const Decl *FoundD;
+ StringRef UniqueDeclName;
+ LValue IVLVal;
+ llvm::Function *FoundFn;
+ std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
+ Checker.getFoundData();
+ if (FoundFn != CGF.CurFn) {
+ // Special codegen for inner parallel regions.
+ // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1;
+ auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD);
+ assert(It != LastprivateConditionalToTypes[FoundFn].end() &&
+ "Lastprivate conditional is not found in outer region.");
+ QualType StructTy = std::get<0>(It->getSecond());
+ const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
+ LValue PrivLVal = CGF.EmitLValue(FoundE);
+ Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ PrivLVal.getAddress(CGF),
+ CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)));
+ LValue BaseLVal =
+ CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl);
+ LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl);
+ CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get(
+ CGF.ConvertTypeForMem(FiredDecl->getType()), 1)),
+ FiredLVal, llvm::AtomicOrdering::Unordered,
+ /*IsVolatile=*/true, /*isInit=*/false);
+ return;
+ }
+
+ // Private address of the lastprivate conditional in the current context.
+ // priv_a
+ LValue LVal = CGF.EmitLValue(FoundE);
+ emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal,
+ FoundE->getExprLoc());
+}
+
+void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) {
+ if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
+ return;
+ auto Range = llvm::reverse(LastprivateConditionalStack);
+ auto It = llvm::find_if(
+ Range, [](const LastprivateConditionalData &D) { return !D.Disabled; });
+ if (It == Range.end() || It->Fn != CGF.CurFn)
+ return;
+ auto LPCI = LastprivateConditionalToTypes.find(It->Fn);
+ assert(LPCI != LastprivateConditionalToTypes.end() &&
+ "Lastprivates must be registered already.");
+ SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
+ getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
+ const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
+ for (const auto &Pair : It->DeclToUniqueName) {
+ const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
+ if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0)
+ continue;
+ auto I = LPCI->getSecond().find(Pair.first);
+ assert(I != LPCI->getSecond().end() &&
+ "Lastprivate must be rehistered already.");
+ // bool Cmp = priv_a.Fired != 0;
+ LValue BaseLVal = std::get<3>(I->getSecond());
+ LValue FiredLVal =
+ CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond()));
+ llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc());
+ llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res);
+ llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then");
+ llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done");
+ // if (Cmp) {
+ CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
+ CGF.EmitBlock(ThenBB);
+ Address Addr = CGF.GetAddrOfLocalVar(VD);
+ LValue LVal;
+ if (VD->getType()->isReferenceType())
+ LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
+ AlignmentSource::Decl);
+ else
+ LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(),
+ AlignmentSource::Decl);
+ emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal,
+ D.getBeginLoc());
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
+ CGF.EmitBlock(DoneBB, /*IsFinal=*/true);
+ // }
}
}
@@ -11538,10 +11777,10 @@
SourceLocation Loc) {
if (CGF.getLangOpts().OpenMP < 50)
return;
- auto It = LastprivateConditionalStack.back().DeclToUniqeName.find(VD);
- assert(It != LastprivateConditionalStack.back().DeclToUniqeName.end() &&
+ auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD);
+ assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() &&
"Unknown lastprivate conditional variable.");
- StringRef UniqueName = It->getSecond();
+ StringRef UniqueName = It->second;
llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName);
// The variable was not updated in the region - exit.
if (!GV)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index dbbf253..2f83b41 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -230,19 +230,37 @@
/// Also, stores the expression for the private loop counter and it
/// threaprivate name.
struct LastprivateConditionalData {
- llvm::SmallDenseMap<CanonicalDeclPtr<const Decl>, SmallString<16>>
- DeclToUniqeName;
+ llvm::MapVector<CanonicalDeclPtr<const Decl>, SmallString<16>>
+ DeclToUniqueName;
LValue IVLVal;
- CodeGenFunction *CGF = nullptr;
+ llvm::Function *Fn = nullptr;
+ bool Disabled = false;
};
/// Manages list of lastprivate conditional decls for the specified directive.
class LastprivateConditionalRAII {
+ enum class ActionToDo {
+ DoNotPush,
+ PushAsLastprivateConditional,
+ DisableLastprivateConditional,
+ };
CodeGenModule &CGM;
- const bool NeedToPush;
+ ActionToDo Action = ActionToDo::DoNotPush;
+
+ /// Check and try to disable analysis of inner regions for changes in
+ /// lastprivate conditional.
+ void tryToDisableInnerAnalysis(const OMPExecutableDirective &S,
+ llvm::DenseSet<CanonicalDeclPtr<const Decl>>
+ &NeedToAddForLPCsAsDisabled) const;
+
+ LastprivateConditionalRAII(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S);
public:
- LastprivateConditionalRAII(CodeGenFunction &CGF,
- const OMPExecutableDirective &S, LValue IVLVal);
+ explicit LastprivateConditionalRAII(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S,
+ LValue IVLVal);
+ static LastprivateConditionalRAII disable(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S);
~LastprivateConditionalRAII();
};
@@ -388,6 +406,13 @@
llvm::DenseMap<llvm::Function *,
SmallVector<const OMPDeclareMapperDecl *, 4>>;
FunctionUDMMapTy FunctionUDMMap;
+ /// Maps local variables marked as lastprivate conditional to their internal
+ /// types.
+ llvm::DenseMap<llvm::Function *,
+ llvm::DenseMap<CanonicalDeclPtr<const Decl>,
+ std::tuple<QualType, const FieldDecl *,
+ const FieldDecl *, LValue>>>
+ LastprivateConditionalToTypes;
/// Type kmp_critical_name, originally defined as typedef kmp_int32
/// kmp_critical_name[8];
llvm::ArrayType *KmpCriticalNameTy;
@@ -822,6 +847,11 @@
const OMPLoopDirective &D)>
SizeEmitter);
+ /// Emit update for lastprivate conditional data.
+ void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal,
+ StringRef UniqueDeclName, LValue LVal,
+ SourceLocation Loc);
+
public:
explicit CGOpenMPRuntime(CodeGenModule &CGM)
: CGOpenMPRuntime(CGM, ".", ".") {}
@@ -1688,6 +1718,10 @@
/// current context.
bool isNontemporalDecl(const ValueDecl *VD) const;
+ /// Create specialized alloca to handle lastprivate conditionals.
+ Address emitLastprivateConditionalInit(CodeGenFunction &CGF,
+ const VarDecl *VD);
+
/// Checks if the provided \p LVal is lastprivate conditional and emits the
/// code to update the value of the original variable.
/// \code
@@ -1704,6 +1738,30 @@
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
const Expr *LHS);
+ /// Checks if the lastprivate conditional was updated in inner region and
+ /// writes the value.
+ /// \code
+ /// lastprivate(conditional: a)
+ /// ...
+ /// <type> a;bool Fired = false;
+ /// #pragma omp ... shared(a)
+ /// {
+ /// lp_a = ...;
+ /// Fired = true;
+ /// }
+ /// if (Fired) {
+ /// #pragma omp critical(a)
+ /// if (last_iv_a <= iv) {
+ /// last_iv_a = iv;
+ /// global_a = lp_a;
+ /// }
+ /// Fired = false;
+ /// }
+ /// \endcode
+ virtual void checkAndEmitSharedLastprivateConditional(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls);
+
/// Gets the address of the global copy used for lastprivate conditional
/// update, if any.
/// \param PrivLVal LValue for the private copy.
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index fcc619d..f64efd0 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -752,11 +752,12 @@
getLangOpts().OpenMPIsDevice &&
isOpenMPTargetExecutionDirective(D.getDirectiveKind());
bool FirstprivateIsLastprivate = false;
- llvm::DenseSet<const VarDecl *> Lastprivates;
+ llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
for (const auto *D : C->varlists())
- Lastprivates.insert(
- cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
+ Lastprivates.try_emplace(
+ cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl(),
+ C->getKind());
}
llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
@@ -766,8 +767,8 @@
bool MustEmitFirstprivateCopy =
CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
- auto IRef = C->varlist_begin();
- auto InitsRef = C->inits().begin();
+ const auto *IRef = C->varlist_begin();
+ const auto *InitsRef = C->inits().begin();
for (const Expr *IInit : C->private_copies()) {
const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
bool ThisFirstprivateIsLastprivate =
@@ -858,14 +859,34 @@
});
} else {
Address OriginalAddr = OriginalLVal.getAddress(*this);
- IsRegistered = PrivateScope.addPrivate(
- OrigVD, [this, VDInit, OriginalAddr, VD]() {
+ IsRegistered =
+ PrivateScope.addPrivate(OrigVD, [this, VDInit, OriginalAddr, VD,
+ ThisFirstprivateIsLastprivate,
+ OrigVD, &Lastprivates, IRef]() {
// Emit private VarDecl with copy init.
// Remap temp VDInit variable to the address of the original
// variable (for proper handling of captured global variables).
setAddrOfLocalVar(VDInit, OriginalAddr);
EmitDecl(*VD);
LocalDeclMap.erase(VDInit);
+ if (ThisFirstprivateIsLastprivate &&
+ Lastprivates[OrigVD->getCanonicalDecl()] ==
+ OMPC_LASTPRIVATE_conditional) {
+ // Create/init special variable for lastprivate conditionals.
+ Address VDAddr =
+ CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
+ *this, OrigVD);
+ llvm::Value *V = EmitLoadOfScalar(
+ MakeAddrLValue(GetAddrOfLocalVar(VD), (*IRef)->getType(),
+ AlignmentSource::Decl),
+ (*IRef)->getExprLoc());
+ EmitStoreOfScalar(V,
+ MakeAddrLValue(VDAddr, (*IRef)->getType(),
+ AlignmentSource::Decl));
+ LocalDeclMap.erase(VD);
+ setAddrOfLocalVar(VD, VDAddr);
+ return VDAddr;
+ }
return GetAddrOfLocalVar(VD);
});
}
@@ -995,8 +1016,8 @@
if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
!getLangOpts().OpenMPSimd)
break;
- auto IRef = C->varlist_begin();
- auto IDestRef = C->destination_exprs().begin();
+ const auto *IRef = C->varlist_begin();
+ const auto *IDestRef = C->destination_exprs().begin();
for (const Expr *IInit : C->private_copies()) {
// Keep the address of the original variable for future update at the end
// of the loop.
@@ -1018,7 +1039,15 @@
// for 'firstprivate' clause.
if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
- bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() {
+ bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD, C,
+ OrigVD]() {
+ if (C->getKind() == OMPC_LASTPRIVATE_conditional) {
+ Address VDAddr =
+ CGM.getOpenMPRuntime().emitLastprivateConditionalInit(*this,
+ OrigVD);
+ setAddrOfLocalVar(VD, VDAddr);
+ return VDAddr;
+ }
// Emit private VarDecl with copy init.
EmitDecl(*VD);
return GetAddrOfLocalVar(VD);
@@ -1293,6 +1322,63 @@
CodeGenBoundParametersTy;
} // anonymous namespace
+static void
+checkForLastprivateConditionalUpdate(CodeGenFunction &CGF,
+ const OMPExecutableDirective &S) {
+ if (CGF.getLangOpts().OpenMP < 50)
+ return;
+ llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
+ for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
+ CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
+ }
+ }
+ for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
+ CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
+ }
+ }
+ for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
+ CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
+ }
+ }
+ // Privates should ne analyzed since they are not captured at all.
+ // Task reductions may be skipped - tasks are ignored.
+ // Firstprivates do not return value but may be passed by reference - no need
+ // to check for updated lastprivate conditional.
+ for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
+ for (const Expr *Ref : C->varlists()) {
+ if (!Ref->getType()->isScalarType())
+ continue;
+ const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
+ if (!DRE)
+ continue;
+ PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
+ }
+ }
+ CGF.CGM.getOpenMPRuntime().checkAndEmitSharedLastprivateConditional(
+ CGF, S, PrivateDecls);
+}
+
static void emitCommonOMPParallelDirective(
CodeGenFunction &CGF, const OMPExecutableDirective &S,
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
@@ -1333,19 +1419,6 @@
CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn,
CapturedVars, IfCond);
- // Check for outer lastprivate conditional update.
- for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
- for (const Expr *Ref : C->varlists())
- CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
- }
- for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
- for (const Expr *Ref : C->varlists())
- CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
- }
- for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
- for (const Expr *Ref : C->varlists())
- CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
- }
}
static void emitEmptyBoundParameters(CodeGenFunction &,
@@ -1353,7 +1426,6 @@
llvm::SmallVectorImpl<llvm::Value *> &) {}
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
-
if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
// Check if we have any if clause associated with the directive.
llvm::Value *IfCond = nullptr;
@@ -1454,10 +1526,16 @@
CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
};
- emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
- emitEmptyBoundParameters);
- emitPostUpdateForReductionClause(*this, S,
- [](CodeGenFunction &) { return nullptr; });
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
+ emitEmptyBoundParameters);
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
@@ -2049,8 +2127,14 @@
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
emitOMPSimdRegion(CGF, S, Action);
};
- OMPLexicalScope Scope(*this, S, OMPD_unknown);
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
+ CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPOuterLoop(
@@ -2778,6 +2862,8 @@
emitDispatchForLoopBounds);
};
{
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
S.hasCancel());
@@ -2786,6 +2872,8 @@
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
@@ -2797,6 +2885,8 @@
emitDispatchForLoopBounds);
};
{
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
}
@@ -2804,6 +2894,8 @@
// Emit an implicit barrier at the end.
if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
@@ -2961,6 +3053,8 @@
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
{
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S, OMPD_unknown);
EmitSections(S);
}
@@ -2969,6 +3063,8 @@
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
OMPD_sections);
}
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
@@ -3007,6 +3103,8 @@
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
{
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
CopyprivateVars, DestExprs,
@@ -3019,6 +3117,8 @@
*this, S.getBeginLoc(),
S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
}
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
@@ -3058,8 +3158,14 @@
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
};
- emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
- emitEmptyBoundParameters);
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
+ emitEmptyBoundParameters);
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPParallelForSimdDirective(
@@ -3071,8 +3177,14 @@
CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
emitDispatchForLoopBounds);
};
- emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen,
- emitEmptyBoundParameters);
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen,
+ emitEmptyBoundParameters);
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPParallelMasterDirective(
@@ -3098,10 +3210,16 @@
emitMaster(CGF, S);
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
};
- emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
- emitEmptyBoundParameters);
- emitPostUpdateForReductionClause(*this, S,
- [](CodeGenFunction &) { return nullptr; });
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
+ emitEmptyBoundParameters);
+ emitPostUpdateForReductionClause(*this, S,
+ [](CodeGenFunction &) { return nullptr; });
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPParallelSectionsDirective(
@@ -3112,8 +3230,14 @@
Action.Enter(CGF);
CGF.EmitSections(S);
};
- emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
- emitEmptyBoundParameters);
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
+ emitEmptyBoundParameters);
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, S);
}
void CodeGenFunction::EmitOMPTaskBasedDirective(
@@ -3549,6 +3673,8 @@
SharedsTy, CapturedStruct, IfCond,
Data);
};
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
}
@@ -4390,6 +4516,8 @@
return;
}
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(CGF, S);
llvm::Function *Fn = nullptr;
llvm::Constant *FnID = nullptr;
@@ -5396,11 +5524,15 @@
}
void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
EmitOMPTaskLoopBasedDirective(S);
}
void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
const OMPTaskLoopSimdDirective &S) {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S);
EmitOMPTaskLoopBasedDirective(S);
}
@@ -5411,6 +5543,8 @@
Action.Enter(CGF);
EmitOMPTaskLoopBasedDirective(S);
};
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S, llvm::None, /*EmitPreInitStmt=*/false);
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
}
@@ -5421,6 +5555,8 @@
Action.Enter(CGF);
EmitOMPTaskLoopBasedDirective(S);
};
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
OMPLexicalScope Scope(*this, S);
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
}
@@ -5437,6 +5573,8 @@
CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
S.getBeginLoc());
};
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen,
emitEmptyBoundParameters);
}
@@ -5453,6 +5591,8 @@
CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
S.getBeginLoc());
};
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen,
emitEmptyBoundParameters);
}
@@ -5521,10 +5661,16 @@
CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
}
};
- OMPSimdLexicalScope Scope(*this, D);
- CGM.getOpenMPRuntime().emitInlinedDirective(
- *this,
- isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
- : D.getDirectiveKind(),
- CodeGen);
+ {
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, D);
+ OMPSimdLexicalScope Scope(*this, D);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this,
+ isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
+ : D.getDirectiveKind(),
+ CodeGen);
+ }
+ // Check for outer lastprivate conditional update.
+ checkForLastprivateConditionalUpdate(*this, D);
}