///
class OMPLinearClause final
: public OMPVarListClause<OMPLinearClause>,
+ public OMPClauseWithPostUpdate,
private llvm::TrailingObjects<OMPLinearClause, Expr *> {
friend TrailingObjects;
friend OMPVarListClause;
unsigned NumVars)
: OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
EndLoc, NumVars),
- Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {}
+ OMPClauseWithPostUpdate(this), Modifier(Modifier),
+ ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {}
/// \brief Build an empty clause.
///
: OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
SourceLocation(), SourceLocation(),
NumVars),
- Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {}
+ OMPClauseWithPostUpdate(this), Modifier(OMPC_LINEAR_val), ModifierLoc(),
+ ColonLoc() {}
/// \brief Gets the list of initial values for linear variables.
///
/// \param IL List of initial values for the variables.
/// \param Step Linear step.
/// \param CalcStep Calculation of the linear step.
+ /// \param PreInit Statement that must be executed before entering the OpenMP
+ /// region with this clause.
+ /// \param PostUpdate Expression that must be executed after exit from the
+ /// OpenMP region with this clause.
static OMPLinearClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
- ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep);
+ ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep,
+ Stmt *PreInit, Expr *PostUpdate);
/// \brief Creates an empty clause with the place for \a NumVars variables.
///
TRY_TO(TraverseStmt(C->getStep()));
TRY_TO(TraverseStmt(C->getCalcStep()));
TRY_TO(VisitOMPClauseList(C));
+ TRY_TO(VisitOMPClauseWithPostUpdate(C));
for (auto *E : C->privates()) {
TRY_TO(TraverseStmt(E));
}
return static_cast<const OMPLastprivateClause *>(C);
case OMPC_reduction:
return static_cast<const OMPReductionClause *>(C);
+ case OMPC_linear:
+ return static_cast<const OMPLinearClause *>(C);
case OMPC_default:
case OMPC_proc_bind:
case OMPC_if:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
- case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
return static_cast<const OMPLastprivateClause *>(C);
case OMPC_reduction:
return static_cast<const OMPReductionClause *>(C);
+ case OMPC_linear:
+ return static_cast<const OMPLinearClause *>(C);
case OMPC_schedule:
case OMPC_dist_schedule:
case OMPC_firstprivate:
case OMPC_collapse:
case OMPC_private:
case OMPC_shared:
- case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
- ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep) {
+ ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep,
+ Stmt *PreInit, Expr *PostUpdate) {
// Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
// (Step and CalcStep).
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size() + 2));
nullptr);
Clause->setStep(Step);
Clause->setCalcStep(CalcStep);
+ Clause->setPreInitStmt(PreInit);
+ Clause->setPostUpdateExpr(PostUpdate);
return Clause;
}
}
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
+ VistOMPClauseWithPostUpdate(C);
for (auto *E : C->privates()) {
Profiler->VisitStmt(E);
}
}
}
- class PostUpdateCleanup final : public EHScopeStack::Cleanup {
- const OMPExecutableDirective &S;
-
- public:
- PostUpdateCleanup(const OMPExecutableDirective &S) : S(S) {}
-
- void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
- if (!CGF.HaveInsertPoint())
- return;
- (void)S;
- // TODO: add cleanups for clauses that require post update.
- }
- };
-
public:
OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
: Scope(CGF, S.getSourceRange()) {
emitPreInitStmt(CGF, S);
- CGF.EHStack.pushCleanup<PostUpdateCleanup>(NormalAndEHCleanup, S);
}
};
} // namespace
CGF.EmitIgnoredExpr(F);
++IC;
}
+ if (auto *PostUpdate = C->getPostUpdateExpr())
+ EmitIgnoredExpr(PostUpdate);
}
}
RefRes.get());
if (!PostUpdateRes.isUsable())
continue;
- ExprPostUpdates.push_back(PostUpdateRes.get());
+ ExprPostUpdates.push_back(
+ IgnoredValueConversions(PostUpdateRes.get()).get());
}
}
if (TopDVar.CKind != OMPC_firstprivate)
SimpleRefExpr, RefRes.get());
if (!PostUpdateRes.isUsable())
continue;
- ExprPostUpdates.push_back(PostUpdateRes.get());
+ ExprPostUpdates.push_back(
+ IgnoredValueConversions(PostUpdateRes.get()).get());
}
}
}
}
}
-
return OMPReductionClause::Create(
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates,
SmallVector<Expr *, 8> Vars;
SmallVector<Expr *, 8> Privates;
SmallVector<Expr *, 8> Inits;
+ SmallVector<Decl *, 4> ExprCaptures;
+ SmallVector<Expr *, 4> ExprPostUpdates;
if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
LinKind == OMPC_LINEAR_unknown) {
Diag(LinLoc, diag::err_omp_wrong_linear_modifier) << LangOpts.CPlusPlus;
VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
Expr *InitExpr;
DeclRefExpr *Ref = nullptr;
- if (!VD)
- Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
+ if (!VD) {
+ Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
+ if (!IsOpenMPCapturedDecl(D)) {
+ ExprCaptures.push_back(Ref->getDecl());
+ if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
+ ExprResult RefRes = DefaultLvalueConversion(Ref);
+ if (!RefRes.isUsable())
+ continue;
+ ExprResult PostUpdateRes =
+ BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
+ SimpleRefExpr, RefRes.get());
+ if (!PostUpdateRes.isUsable())
+ continue;
+ ExprPostUpdates.push_back(
+ IgnoredValueConversions(PostUpdateRes.get()).get());
+ }
+ }
+ }
if (LinKind == OMPC_LINEAR_uval)
InitExpr = VD ? VD->getInit() : SimpleRefExpr;
else
}
}
+ Stmt *PreInit = nullptr;
+ if (!ExprCaptures.empty()) {
+ PreInit = new (Context)
+ DeclStmt(DeclGroupRef::Create(Context, ExprCaptures.begin(),
+ ExprCaptures.size()),
+ SourceLocation(), SourceLocation());
+ }
+ Expr *PostUpdate = nullptr;
+ if (!ExprPostUpdates.empty()) {
+ for (auto *E : ExprPostUpdates) {
+ ExprResult PostUpdateRes =
+ PostUpdate
+ ? CreateBuiltinBinOp(SourceLocation(), BO_Comma, PostUpdate, E)
+ : E;
+ PostUpdate = PostUpdateRes.get();
+ }
+ }
+
return OMPLinearClause::Create(Context, StartLoc, LParenLoc, LinKind, LinLoc,
ColonLoc, EndLoc, Vars, Privates, Inits,
- StepExpr, CalcStepExpr);
+ StepExpr, CalcStepExpr, PreInit, PostUpdate);
}
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
}
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
+ VisitOMPClauseWithPostUpdate(C);
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
C->setModifier(static_cast<OpenMPLinearClauseKind>(Record[Idx++]));
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
Record.push_back(C->varlist_size());
+ VisitOMPClauseWithPostUpdate(C);
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
Record.push_back(C->getModifier());
}
void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
VisitOMPClauseList(C);
+ VisitOMPClauseWithPostUpdate(C);
for (const auto *E : C->privates()) {
Visitor->AddStmt(E);
}