diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2016-03-29 08:58:54 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2016-03-29 08:58:54 +0000 |
commit | 5a3af13d93fb62a675b4cee74322244f2f6c6023 (patch) | |
tree | fc9956dcc4b2cd15ac3ea469ed60fc00767d7b59 /clang/lib | |
parent | 1e4b39f18448db4c7e77341a861847752ddce875 (diff) | |
download | bcm5719-llvm-5a3af13d93fb62a675b4cee74322244f2f6c6023.tar.gz bcm5719-llvm-5a3af13d93fb62a675b4cee74322244f2f6c6023.zip |
[OPENMP] Remove extra code transformation.
For better support of some specific GNU extensions some extra
transformation of AST nodes were introduced. These transformations are
very hard to handle. The code is improved in handling of these
extensions by using captured expressions construct.
llvm-svn: 264709
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/StmtOpenMP.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 466 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 1 |
5 files changed, 219 insertions, 282 deletions
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index 49fe88eeddf..f3291a5113c 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -105,6 +105,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -153,6 +154,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); Dir->setHasCancel(HasCancel); return Dir; } @@ -202,6 +204,7 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc, Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -367,6 +370,7 @@ OMPParallelForDirective *OMPParallelForDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); Dir->setHasCancel(HasCancel); return Dir; } @@ -414,6 +418,7 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -750,6 +755,7 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); Dir->setHasCancel(HasCancel); return Dir; } @@ -889,6 +895,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -936,6 +943,7 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } @@ -982,6 +990,7 @@ OMPDistributeDirective *OMPDistributeDirective::Create( Dir->setInits(Exprs.Inits); Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); + Dir->setPreInits(Exprs.PreInits); return Dir; } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 87c9b3b4d1d..84059ab2912 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -52,6 +52,25 @@ public: } }; +/// Private scope for OpenMP loop-based directives, that supports capturing +/// of used expression from loop statement. +class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { + void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) { + if (auto *LD = dyn_cast<OMPLoopDirective>(&S)) { + if (auto *PreInits = cast_or_null<DeclStmt>(LD->getPreInits())) { + for (const auto *I : PreInits->decls()) + CGF.EmitVarDecl(cast<VarDecl>(*I)); + } + } + } + +public: + OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S) + : CodeGenFunction::RunCleanupsScope(CGF) { + emitPreInitStmt(CGF, S); + } +}; + } // namespace llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) { @@ -1467,6 +1486,7 @@ void CodeGenFunction::EmitOMPSimdFinal( void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { + OMPLoopScope PreInitScope(CGF, S); // if (PreCond) { // for (IV in 0..LastIteration) BODY; // <Final counter/linear vars updates>; @@ -1781,6 +1801,7 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) { bool HasLastprivateClause; // Check pre-condition. { + OMPLoopScope PreInitScope(*this, S); // Skip the entire loop if we don't meet the precondition. // If the condition constant folds and can be elided, avoid emitting the // whole loop. @@ -2397,6 +2418,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPDistributeDirective &S) { // Check pre-condition. { + OMPLoopScope PreInitScope(*this, S); // Skip the entire loop if we don't meet the precondition. // If the condition constant folds and can be elided, avoid emitting the // whole loop. @@ -3174,6 +3196,7 @@ void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) { OMPLexicalScope Scope(*this, S); CGM.getOpenMPRuntime().emitInlinedDirective( *this, OMPD_taskloop, [&S](CodeGenFunction &CGF, PrePostActionTy &) { + OMPLoopScope PreInitScope(CGF, S); CGF.EmitStmt( cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); }); @@ -3185,6 +3208,7 @@ void CodeGenFunction::EmitOMPTaskLoopSimdDirective( OMPLexicalScope Scope(*this, S); CGM.getOpenMPRuntime().emitInlinedDirective( *this, OMPD_taskloop_simd, [&S](CodeGenFunction &CGF, PrePostActionTy &) { + OMPLoopScope PreInitScope(CGF, S); CGF.EmitStmt( cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); }); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index d58f91104fe..c1233d8278f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1028,9 +1028,9 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { PopExpressionEvaluationContext(); } -static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, - Expr *NumIterations, Sema &SemaRef, - Scope *S); +static bool +FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, + Expr *NumIterations, Sema &SemaRef, Scope *S); namespace { @@ -1708,10 +1708,11 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { } static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, - Expr *CaptureExpr, bool WithInit) { + Expr *CaptureExpr, bool WithInit, + bool AsExpression) { assert(CaptureExpr); ASTContext &C = S.getASTContext(); - Expr *Init = CaptureExpr->IgnoreImpCasts(); + Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts(); QualType Ty = Init->getType(); if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) { if (S.getLangOpts().CPlusPlus) @@ -1741,17 +1742,28 @@ static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, if (auto *VD = S.IsOpenMPCapturedDecl(D)) CD = cast<OMPCapturedExprDecl>(VD); else - CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit); + CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit, + /*AsExpression=*/false); return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), SourceLocation()); } -static DeclRefExpr *buildCapture(Sema &S, Expr *CaptureExpr) { - auto *CD = - buildCaptureDecl(S, &S.getASTContext().Idents.get(".capture_expr."), - CaptureExpr, /*WithInit=*/true); - return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), - SourceLocation()); +static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref) { + if (!Ref) { + auto *CD = + buildCaptureDecl(S, &S.getASTContext().Idents.get(".capture_expr."), + CaptureExpr, /*WithInit=*/true, /*AsExpression=*/true); + Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(), + CaptureExpr->getExprLoc()); + } + ExprResult Res = Ref; + if (!S.getLangOpts().CPlusPlus && + CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() && + Ref->getType()->isPointerType()) + Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref); + if (!Res.isUsable()) + return ExprError(); + return CaptureExpr->isGLValue() ? Res : S.DefaultLvalueConversion(Res.get()); } StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, @@ -3251,9 +3263,12 @@ public: /// \brief True if the step should be subtracted. bool ShouldSubtractStep() const { return SubtractStep; } /// \brief Build the expression to calculate the number of iterations. - Expr *BuildNumIterations(Scope *S, const bool LimitedType) const; + Expr * + BuildNumIterations(Scope *S, const bool LimitedType, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const; /// \brief Build the precondition expression for the loops. - Expr *BuildPreCond(Scope *S, Expr *Cond) const; + Expr *BuildPreCond(Scope *S, Expr *Cond, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const; /// \brief Build reference expression to the counter be used for codegen. Expr *BuildCounterVar() const; /// \brief Build reference expression to the private counter be used for @@ -3613,62 +3628,26 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) { return true; } -namespace { -// Transform variables declared in GNU statement expressions to new ones to -// avoid crash on codegen. -class TransformToNewDefs : public TreeTransform<TransformToNewDefs> { - typedef TreeTransform<TransformToNewDefs> BaseTransform; - -public: - TransformToNewDefs(Sema &SemaRef) : BaseTransform(SemaRef) {} - - Decl *TransformDefinition(SourceLocation Loc, Decl *D) { - if (auto *VD = cast<VarDecl>(D)) - if (!isa<ParmVarDecl>(D) && !isa<VarTemplateSpecializationDecl>(D) && - !isa<ImplicitParamDecl>(D)) { - auto *NewVD = VarDecl::Create( - SemaRef.Context, VD->getDeclContext(), VD->getLocStart(), - VD->getLocation(), VD->getIdentifier(), VD->getType(), - VD->getTypeSourceInfo(), VD->getStorageClass()); - NewVD->setTSCSpec(VD->getTSCSpec()); - NewVD->setInit(VD->getInit()); - NewVD->setInitStyle(VD->getInitStyle()); - NewVD->setExceptionVariable(VD->isExceptionVariable()); - NewVD->setNRVOVariable(VD->isNRVOVariable()); - NewVD->setCXXForRangeDecl(VD->isCXXForRangeDecl()); - NewVD->setConstexpr(VD->isConstexpr()); - NewVD->setInitCapture(VD->isInitCapture()); - NewVD->setPreviousDeclInSameBlockScope( - VD->isPreviousDeclInSameBlockScope()); - VD->getDeclContext()->addHiddenDecl(NewVD); - if (VD->hasAttrs()) - NewVD->setAttrs(VD->getAttrs()); - transformedLocalDecl(VD, NewVD); - return NewVD; - } - return BaseTransform::TransformDefinition(Loc, D); - } - - ExprResult TransformDeclRefExpr(DeclRefExpr *E) { - if (auto *NewD = TransformDecl(E->getExprLoc(), E->getDecl())) - if (E->getDecl() != NewD) { - NewD->setReferenced(); - NewD->markUsed(SemaRef.Context); - return DeclRefExpr::Create( - SemaRef.Context, E->getQualifierLoc(), E->getTemplateKeywordLoc(), - cast<ValueDecl>(NewD), E->refersToEnclosingVariableOrCapture(), - E->getNameInfo(), E->getType(), E->getValueKind()); - } - return BaseTransform::TransformDeclRefExpr(E); - } -}; +static ExprResult +tryBuildCapture(Sema &SemaRef, Expr *Capture, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) { + if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects)) + return SemaRef.PerformImplicitConversion( + Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting, + /*AllowExplicit=*/true); + auto I = Captures.find(Capture); + if (I != Captures.end()) + return buildCapture(SemaRef, Capture, I->second); + DeclRefExpr *Ref = nullptr; + ExprResult Res = buildCapture(SemaRef, Capture, Ref); + Captures[Capture] = Ref; + return Res; } /// \brief Build the expression to calculate the number of iterations. -Expr * -OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, - const bool LimitedType) const { - TransformToNewDefs Transform(SemaRef); +Expr *OpenMPIterationSpaceChecker::BuildNumIterations( + Scope *S, const bool LimitedType, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const { ExprResult Diff; auto VarType = Var->getType().getNonReferenceType(); if (VarType->isIntegerType() || VarType->isPointerType() || @@ -3676,24 +3655,8 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, // Upper - Lower auto *UBExpr = TestIsLessOp ? UB : LB; auto *LBExpr = TestIsLessOp ? LB : UB; - Expr *Upper = Transform.TransformExpr(UBExpr).get(); - Expr *Lower = Transform.TransformExpr(LBExpr).get(); - if (!Upper || !Lower) - return nullptr; - if (!SemaRef.Context.hasSameType(Upper->getType(), UBExpr->getType())) { - Upper = SemaRef - .PerformImplicitConversion(Upper, UBExpr->getType(), - Sema::AA_Converting, - /*AllowExplicit=*/true) - .get(); - } - if (!SemaRef.Context.hasSameType(Lower->getType(), LBExpr->getType())) { - Lower = SemaRef - .PerformImplicitConversion(Lower, LBExpr->getType(), - Sema::AA_Converting, - /*AllowExplicit=*/true) - .get(); - } + Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get(); + Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get(); if (!Upper || !Lower) return nullptr; @@ -3720,18 +3683,9 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, return nullptr; // Upper - Lower [- 1] + Step - auto *StepNoImp = Step->IgnoreImplicit(); - auto NewStep = Transform.TransformExpr(StepNoImp); - if (NewStep.isInvalid()) + auto NewStep = tryBuildCapture(SemaRef, Step, Captures); + if (!NewStep.isUsable()) return nullptr; - if (!SemaRef.Context.hasSameType(NewStep.get()->getType(), - StepNoImp->getType())) { - NewStep = SemaRef.PerformImplicitConversion( - NewStep.get(), StepNoImp->getType(), Sema::AA_Converting, - /*AllowExplicit=*/true); - if (NewStep.isInvalid()) - return nullptr; - } Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get()); if (!Diff.isUsable()) return nullptr; @@ -3742,17 +3696,6 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, return nullptr; // (Upper - Lower [- 1] + Step) / Step - NewStep = Transform.TransformExpr(StepNoImp); - if (NewStep.isInvalid()) - return nullptr; - if (!SemaRef.Context.hasSameType(NewStep.get()->getType(), - StepNoImp->getType())) { - NewStep = SemaRef.PerformImplicitConversion( - NewStep.get(), StepNoImp->getType(), Sema::AA_Converting, - /*AllowExplicit=*/true); - if (NewStep.isInvalid()) - return nullptr; - } Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get()); if (!Diff.isUsable()) return nullptr; @@ -3798,35 +3741,25 @@ OpenMPIterationSpaceChecker::BuildNumIterations(Scope *S, return Diff.get(); } -Expr *OpenMPIterationSpaceChecker::BuildPreCond(Scope *S, Expr *Cond) const { +Expr *OpenMPIterationSpaceChecker::BuildPreCond( + Scope *S, Expr *Cond, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) const { // Try to build LB <op> UB, where <op> is <, >, <=, or >=. bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics(); SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true); - TransformToNewDefs Transform(SemaRef); - - auto NewLB = Transform.TransformExpr(LB); - auto NewUB = Transform.TransformExpr(UB); - if (NewLB.isInvalid() || NewUB.isInvalid()) - return Cond; - if (!SemaRef.Context.hasSameType(NewLB.get()->getType(), LB->getType())) { - NewLB = SemaRef.PerformImplicitConversion(NewLB.get(), LB->getType(), - Sema::AA_Converting, - /*AllowExplicit=*/true); - } - if (!SemaRef.Context.hasSameType(NewUB.get()->getType(), UB->getType())) { - NewUB = SemaRef.PerformImplicitConversion(NewUB.get(), UB->getType(), - Sema::AA_Converting, - /*AllowExplicit=*/true); - } - if (NewLB.isInvalid() || NewUB.isInvalid()) - return Cond; + + auto NewLB = tryBuildCapture(SemaRef, LB, Captures); + auto NewUB = tryBuildCapture(SemaRef, UB, Captures); + if (!NewLB.isUsable() || !NewUB.isUsable()) + return nullptr; + auto CondExpr = SemaRef.BuildBinOp( S, DefaultLoc, TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) : (TestIsStrictOp ? BO_GT : BO_GE), NewLB.get(), NewUB.get()); if (CondExpr.isUsable()) { - if (!SemaRef.Context.hasSameType(CondExpr.get()->getType(), - SemaRef.Context.BoolTy)) + if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(), + SemaRef.Context.BoolTy)) CondExpr = SemaRef.PerformImplicitConversion( CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting, /*AllowExplicit=*/true); @@ -3909,7 +3842,8 @@ static bool CheckOpenMPIterationSpace( unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA, - LoopIterationSpace &ResultIterSpace) { + LoopIterationSpace &ResultIterSpace, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) { // OpenMP [2.6, Canonical Loop Form] // for (init-expr; test-expr; incr-expr) structured-block auto For = dyn_cast_or_null<ForStmt>(S); @@ -4027,11 +3961,13 @@ static bool CheckOpenMPIterationSpace( return HasErrors; // Build the loop's iteration space representation. - ResultIterSpace.PreCond = ISC.BuildPreCond(DSA.getCurScope(), For->getCond()); + ResultIterSpace.PreCond = + ISC.BuildPreCond(DSA.getCurScope(), For->getCond(), Captures); ResultIterSpace.NumIterations = ISC.BuildNumIterations( - DSA.getCurScope(), (isOpenMPWorksharingDirective(DKind) || - isOpenMPTaskLoopDirective(DKind) || - isOpenMPDistributeDirective(DKind))); + DSA.getCurScope(), + (isOpenMPWorksharingDirective(DKind) || + isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)), + Captures); ResultIterSpace.CounterVar = ISC.BuildCounterVar(); ResultIterSpace.PrivateCounterVar = ISC.BuildPrivateCounterVar(); ResultIterSpace.CounterInit = ISC.BuildCounterInit(); @@ -4052,23 +3988,15 @@ static bool CheckOpenMPIterationSpace( } /// \brief Build 'VarRef = Start. -static ExprResult BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, - ExprResult VarRef, ExprResult Start) { - TransformToNewDefs Transform(SemaRef); +static ExprResult +BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, + ExprResult Start, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) { // Build 'VarRef = Start. - auto *StartNoImp = Start.get()->IgnoreImplicit(); - auto NewStart = Transform.TransformExpr(StartNoImp); - if (NewStart.isInvalid()) + auto NewStart = tryBuildCapture(SemaRef, Start.get(), Captures); + if (!NewStart.isUsable()) return ExprError(); if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), - StartNoImp->getType())) { - NewStart = SemaRef.PerformImplicitConversion( - NewStart.get(), StartNoImp->getType(), Sema::AA_Converting, - /*AllowExplicit=*/true); - if (NewStart.isInvalid()) - return ExprError(); - } - if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), VarRef.get()->getType())) { NewStart = SemaRef.PerformImplicitConversion( NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting, @@ -4083,29 +4011,22 @@ static ExprResult BuildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, } /// \brief Build 'VarRef = Start + Iter * Step'. -static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S, - SourceLocation Loc, ExprResult VarRef, - ExprResult Start, ExprResult Iter, - ExprResult Step, bool Subtract) { +static ExprResult +BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, + ExprResult VarRef, ExprResult Start, ExprResult Iter, + ExprResult Step, bool Subtract, + llvm::MapVector<Expr *, DeclRefExpr *> *Captures = nullptr) { // Add parentheses (for debugging purposes only). Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get()); if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() || !Step.isUsable()) return ExprError(); - auto *StepNoImp = Step.get()->IgnoreImplicit(); - TransformToNewDefs Transform(SemaRef); - auto NewStep = Transform.TransformExpr(StepNoImp); + ExprResult NewStep = Step; + if (Captures) + NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures); if (NewStep.isInvalid()) return ExprError(); - if (!SemaRef.Context.hasSameType(NewStep.get()->getType(), - StepNoImp->getType())) { - NewStep = SemaRef.PerformImplicitConversion( - NewStep.get(), StepNoImp->getType(), Sema::AA_Converting, - /*AllowExplicit=*/true); - if (NewStep.isInvalid()) - return ExprError(); - } ExprResult Update = SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get()); if (!Update.isUsable()) @@ -4113,18 +4034,11 @@ static ExprResult BuildCounterUpdate(Sema &SemaRef, Scope *S, // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or // 'VarRef = Start (+|-) Iter * Step'. - auto *StartNoImp = Start.get()->IgnoreImplicit(); - auto NewStart = Transform.TransformExpr(StartNoImp); + ExprResult NewStart = Start; + if (Captures) + NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures); if (NewStart.isInvalid()) return ExprError(); - if (!SemaRef.Context.hasSameType(NewStart.get()->getType(), - StartNoImp->getType())) { - NewStart = SemaRef.PerformImplicitConversion( - NewStart.get(), StartNoImp->getType(), Sema::AA_Converting, - /*AllowExplicit=*/true); - if (NewStart.isInvalid()) - return ExprError(); - } // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'. ExprResult SavedUpdate = Update; @@ -4196,6 +4110,49 @@ static bool FitsInto(unsigned Bits, bool Signed, Expr *E, Sema &SemaRef) { return false; } +/// Build preinits statement for the given declarations. +static Stmt *buildPreInits(ASTContext &Context, + SmallVectorImpl<Decl *> &PreInits) { + if (!PreInits.empty()) { + return new (Context) DeclStmt( + DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()), + SourceLocation(), SourceLocation()); + } + return nullptr; +} + +/// Build preinits statement for the given declarations. +static Stmt *buildPreInits(ASTContext &Context, + llvm::MapVector<Expr *, DeclRefExpr *> &Captures) { + if (!Captures.empty()) { + SmallVector<Decl *, 16> PreInits; + for (auto &Pair : Captures) + PreInits.push_back(Pair.second->getDecl()); + return buildPreInits(Context, PreInits); + } + return nullptr; +} + +/// Build postupdate expression for the given list of postupdates expressions. +static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) { + Expr *PostUpdate = nullptr; + if (!PostUpdates.empty()) { + for (auto *E : PostUpdates) { + Expr *ConvE = S.BuildCStyleCastExpr( + E->getExprLoc(), + S.Context.getTrivialTypeSourceInfo(S.Context.VoidTy), + E->getExprLoc(), E) + .get(); + PostUpdate = PostUpdate + ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma, + PostUpdate, ConvE) + .get() + : ConvE; + } + } + return PostUpdate; +} + /// \brief Called on a for stmt to check itself and nested loops (if any). /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, /// number of collapsed loops otherwise. @@ -4229,6 +4186,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, } // This is helper routine for loop directives (e.g., 'for', 'simd', // 'for simd', etc.). + llvm::MapVector<Expr *, DeclRefExpr *> Captures; SmallVector<LoopIterationSpace, 4> IterSpaces; IterSpaces.resize(NestedLoopCount); Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true); @@ -4236,7 +4194,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount, CollapseLoopCountExpr, OrderedLoopCountExpr, VarsWithImplicitDSA, - IterSpaces[Cnt])) + IterSpaces[Cnt], Captures)) return 0; // Move on to the next nested for loop, or to the loop body. // OpenMP [2.8.1, simd construct, Restrictions] @@ -4358,19 +4316,13 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context); ExprResult CalcLastIteration; if (!IsConstant) { - SourceLocation SaveLoc; - VarDecl *SaveVar = - buildVarDecl(SemaRef, SaveLoc, LastIteration.get()->getType(), - ".omp.last.iteration"); - ExprResult SaveRef = buildDeclRefExpr( - SemaRef, SaveVar, LastIteration.get()->getType(), SaveLoc); - CalcLastIteration = SemaRef.BuildBinOp(CurScope, SaveLoc, BO_Assign, - SaveRef.get(), LastIteration.get()); + ExprResult SaveRef = + tryBuildCapture(SemaRef, LastIteration.get(), Captures); LastIteration = SaveRef; // Prepare SaveRef + 1. NumIterations = SemaRef.BuildBinOp( - CurScope, SaveLoc, BO_Add, SaveRef.get(), + CurScope, SourceLocation(), BO_Add, SaveRef.get(), SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get()); if (!NumIterations.isUsable()) return 0; @@ -4525,14 +4477,14 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(), /*RefersToCapture=*/true); ExprResult Init = BuildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar, - IS.CounterInit); + IS.CounterInit, Captures); if (!Init.isUsable()) { HasErrors = true; break; } - ExprResult Update = - BuildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar, - IS.CounterInit, Iter, IS.CounterStep, IS.Subtract); + ExprResult Update = BuildCounterUpdate( + SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter, + IS.CounterStep, IS.Subtract, &Captures); if (!Update.isUsable()) { HasErrors = true; break; @@ -4541,7 +4493,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step ExprResult Final = BuildCounterUpdate( SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, - IS.NumIterations, IS.CounterStep, IS.Subtract); + IS.NumIterations, IS.CounterStep, IS.Subtract, &Captures); if (!Final.isUsable()) { HasErrors = true; break; @@ -4586,6 +4538,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.CalcLastIteration = SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); Built.PreCond = PreCond.get(); + Built.PreInits = buildPreInits(C, Captures); Built.Cond = Cond.get(); Built.Init = Init.get(); Built.Inc = Inc.get(); @@ -6201,6 +6154,16 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective( assert((CurContext->isDependentContext() || B.builtAll()) && "omp for loop exprs were not built"); + if (!CurContext->isDependentContext()) { + // Finalize the clauses that need pre-built expressions for CodeGen. + for (auto C : Clauses) { + if (auto LC = dyn_cast<OMPLinearClause>(C)) + if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), + B.NumIterations, *this, CurScope)) + return StmtError(); + } + } + // OpenMP, [2.9.2 taskloop Construct, Restrictions] // The grainsize clause and num_tasks clause are mutually exclusive and may // not appear on the same taskloop directive. @@ -6847,13 +6810,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( return nullptr; } } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { - ValExpr = buildCapture(*this, ValExpr); - Decl *D = cast<DeclRefExpr>(ValExpr)->getDecl(); - HelperValStmt = - new (Context) DeclStmt(DeclGroupRef::Create(Context, &D, - /*NumDecls=*/1), - SourceLocation(), SourceLocation()); - ValExpr = DefaultLvalueConversion(ValExpr).get(); + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); } } } @@ -7569,16 +7528,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, if (Vars.empty()) return nullptr; - Stmt *PreInit = nullptr; - if (!ExprCaptures.empty()) { - PreInit = new (Context) - DeclStmt(DeclGroupRef::Create(Context, ExprCaptures.begin(), - ExprCaptures.size()), - SourceLocation(), SourceLocation()); - } return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, - Vars, PrivateCopies, Inits, PreInit); + Vars, PrivateCopies, Inits, + buildPreInits(Context, ExprCaptures)); } OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, @@ -7730,27 +7683,11 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, if (Vars.empty()) return nullptr; - 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 OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs, AssignmentOps, - PreInit, PostUpdate); + buildPreInits(Context, ExprCaptures), + buildPostUpdate(*this, ExprPostUpdates)); } OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, @@ -8482,20 +8419,20 @@ OMPClause *Sema::ActOnOpenMPReductionClause( } else { VarsExpr = 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 (!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()); } } } @@ -8509,28 +8446,12 @@ OMPClause *Sema::ActOnOpenMPReductionClause( if (Vars.empty()) return nullptr; - 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 OMPReductionClause::Create( Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars, ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates, - LHSs, RHSs, ReductionOps, PreInit, PostUpdate); + LHSs, RHSs, ReductionOps, buildPreInits(Context, ExprCaptures), + buildPostUpdate(*this, ExprPostUpdates)); } OMPClause *Sema::ActOnOpenMPLinearClause( @@ -8696,32 +8617,16 @@ OMPClause *Sema::ActOnOpenMPLinearClause( } } - 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, PreInit, PostUpdate); + StepExpr, CalcStepExpr, + buildPreInits(Context, ExprCaptures), + buildPostUpdate(*this, ExprPostUpdates)); } -static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, - Expr *NumIterations, Sema &SemaRef, - Scope *S) { +static bool +FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, + Expr *NumIterations, Sema &SemaRef, Scope *S) { // Walk the vars and build update/final expressions for the CodeGen. SmallVector<Expr *, 8> Updates; SmallVector<Expr *, 8> Finals; @@ -8731,8 +8636,9 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, // If linear-step is not specified it is assumed to be 1. if (Step == nullptr) Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(); - else if (CalcStep) + else if (CalcStep) { Step = cast<BinaryOperator>(CalcStep)->getLHS(); + } bool HasErrors = false; auto CurInit = Clause.inits().begin(); auto CurPrivate = Clause.privates().begin(); @@ -10315,13 +10221,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( return nullptr; } } else if (isParallelOrTaskRegion(DSAStack->getCurrentDirective())) { - ValExpr = buildCapture(*this, ValExpr); - Decl *D = cast<DeclRefExpr>(ValExpr)->getDecl(); - HelperValStmt = - new (Context) DeclStmt(DeclGroupRef::Create(Context, &D, - /*NumDecls=*/1), - SourceLocation(), SourceLocation()); - ValExpr = DefaultLvalueConversion(ValExpr).get(); + llvm::MapVector<Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); } } } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index f8fb2b86034..2de0b58fa4a 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2310,6 +2310,7 @@ void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) { D->setCond(Reader.ReadSubExpr()); D->setInit(Reader.ReadSubExpr()); D->setInc(Reader.ReadSubExpr()); + D->setPreInits(Reader.ReadSubStmt()); if (isOpenMPWorksharingDirective(D->getDirectiveKind()) || isOpenMPTaskLoopDirective(D->getDirectiveKind()) || isOpenMPDistributeDirective(D->getDirectiveKind())) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 3738c8e9a78..a29a3007ed6 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2097,6 +2097,7 @@ void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) { Writer.AddStmt(D->getCond()); Writer.AddStmt(D->getInit()); Writer.AddStmt(D->getInc()); + Writer.AddStmt(D->getPreInits()); if (isOpenMPWorksharingDirective(D->getDirectiveKind()) || isOpenMPTaskLoopDirective(D->getDirectiveKind()) || isOpenMPDistributeDirective(D->getDirectiveKind())) { |