r264709 - [OPENMP] Remove extra code transformation.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 29 01:58:55 PDT 2016


Author: abataev
Date: Tue Mar 29 03:58:54 2016
New Revision: 264709

URL: http://llvm.org/viewvc/llvm-project?rev=264709&view=rev
Log:
[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.

Modified:
    cfe/trunk/include/clang/AST/StmtOpenMP.h
    cfe/trunk/lib/AST/StmtOpenMP.cpp
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/OpenMP/distribute_codegen.cpp
    cfe/trunk/test/OpenMP/for_codegen.cpp
    cfe/trunk/test/OpenMP/for_loop_messages.cpp
    cfe/trunk/test/OpenMP/for_simd_loop_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_simd_loop_messages.cpp
    cfe/trunk/test/OpenMP/simd_codegen.cpp
    cfe/trunk/test/OpenMP/target_parallel_for_loop_messages.cpp
    cfe/trunk/test/OpenMP/taskloop_loop_messages.cpp
    cfe/trunk/test/OpenMP/taskloop_simd_loop_messages.cpp

Modified: cfe/trunk/include/clang/AST/StmtOpenMP.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtOpenMP.h (original)
+++ cfe/trunk/include/clang/AST/StmtOpenMP.h Tue Mar 29 03:58:54 2016
@@ -312,21 +312,22 @@ class OMPLoopDirective : public OMPExecu
     CondOffset = 5,
     InitOffset = 6,
     IncOffset = 7,
+    PreInitsOffset = 8,
     // The '...End' enumerators do not correspond to child expressions - they
     // specify the offset to the end (and start of the following counters/
     // updates/finals arrays).
-    DefaultEnd = 8,
+    DefaultEnd = 9,
     // The following 7 exprs are used by worksharing loops only.
-    IsLastIterVariableOffset = 8,
-    LowerBoundVariableOffset = 9,
-    UpperBoundVariableOffset = 10,
-    StrideVariableOffset = 11,
-    EnsureUpperBoundOffset = 12,
-    NextLowerBoundOffset = 13,
-    NextUpperBoundOffset = 14,
+    IsLastIterVariableOffset = 9,
+    LowerBoundVariableOffset = 10,
+    UpperBoundVariableOffset = 11,
+    StrideVariableOffset = 12,
+    EnsureUpperBoundOffset = 13,
+    NextLowerBoundOffset = 14,
+    NextUpperBoundOffset = 15,
     // Offset to the end (and start of the following counters/updates/finals
     // arrays) for worksharing loop directives.
-    WorksharingEnd = 15,
+    WorksharingEnd = 16,
   };
 
   /// \brief Get the counters storage.
@@ -422,6 +423,9 @@ protected:
   }
   void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
   void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
+  void setPreInits(Stmt *PreInits) {
+    *std::next(child_begin(), PreInitsOffset) = PreInits;
+  }
   void setIsLastIterVariable(Expr *IL) {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
@@ -521,6 +525,8 @@ public:
     SmallVector<Expr *, 4> Updates;
     /// \brief Final loop counter values for GodeGen.
     SmallVector<Expr *, 4> Finals;
+    /// Init statement for all captured expressions.
+    Stmt *PreInits;
 
     /// \brief Check if all the expressions are built (does not check the
     /// worksharing ones).
@@ -559,6 +565,7 @@ public:
         Updates[i] = nullptr;
         Finals[i] = nullptr;
       }
+      PreInits = nullptr;
     }
   };
 
@@ -593,6 +600,10 @@ public:
     return const_cast<Expr *>(
         reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset)));
   }
+  const Stmt *getPreInits() const {
+    return *std::next(child_begin(), PreInitsOffset);
+  }
+  Stmt *getPreInits() { return *std::next(child_begin(), PreInitsOffset); }
   Expr *getIsLastIterVariable() const {
     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
             isOpenMPTaskLoopDirective(getDirectiveKind()) ||

Modified: cfe/trunk/lib/AST/StmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtOpenMP.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtOpenMP.cpp (original)
+++ cfe/trunk/lib/AST/StmtOpenMP.cpp Tue Mar 29 03:58:54 2016
@@ -105,6 +105,7 @@ OMPSimdDirective::Create(const ASTContex
   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
   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 ASTCon
   Dir->setInits(Exprs.Inits);
   Dir->setUpdates(Exprs.Updates);
   Dir->setFinals(Exprs.Finals);
+  Dir->setPreInits(Exprs.PreInits);
   return Dir;
 }
 
@@ -367,6 +370,7 @@ OMPParallelForDirective *OMPParallelForD
   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 *OMPParallel
   Dir->setInits(Exprs.Inits);
   Dir->setUpdates(Exprs.Updates);
   Dir->setFinals(Exprs.Finals);
+  Dir->setPreInits(Exprs.PreInits);
   return Dir;
 }
 
@@ -750,6 +755,7 @@ OMPTargetParallelForDirective *OMPTarget
   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 *OMPTaskLoopDirecti
   Dir->setInits(Exprs.Inits);
   Dir->setUpdates(Exprs.Updates);
   Dir->setFinals(Exprs.Finals);
+  Dir->setPreInits(Exprs.PreInits);
   return Dir;
 }
 
@@ -936,6 +943,7 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSim
   Dir->setInits(Exprs.Inits);
   Dir->setUpdates(Exprs.Updates);
   Dir->setFinals(Exprs.Finals);
+  Dir->setPreInits(Exprs.PreInits);
   return Dir;
 }
 
@@ -982,6 +990,7 @@ OMPDistributeDirective *OMPDistributeDir
   Dir->setInits(Exprs.Inits);
   Dir->setUpdates(Exprs.Updates);
   Dir->setFinals(Exprs.Finals);
+  Dir->setPreInits(Exprs.PreInits);
   return Dir;
 }
 

Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Tue Mar 29 03:58:54 2016
@@ -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::EmitOMPWorksharing
   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::EmitOMPDistributeL
 
   // 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::EmitOMPTaskLoopDir
   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::EmitOMPTaskLoopSim
   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());
       });

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Mar 29 03:58:54 2016
@@ -1028,9 +1028,9 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDi
   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(OpenMP
 }
 
 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
   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::CheckI
   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::BuildNumIte
     // 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::BuildNumIte
     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::BuildNumIte
     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::BuildNumIte
   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
 }
 
 /// \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(Sem
 
   // 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
   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 DKin
   }
   // 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 DKin
     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 DKin
       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 DKin
           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 DKin
       // 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 DKin
   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::ActOnOpenMPTaskLoopSimd
   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::ActOnOpenMPScheduleClau
           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::ActOnOpenMPFirstprivate
 
   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::ActOnOpenMPLastprivateC
 
   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::ActOnOpenMPReductionCla
       } 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::ActOnOpenMPReductionCla
 
   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(OMP
   // 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::ActOnOpenMPDistSchedule
           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);
       }
     }
   }

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Mar 29 03:58:54 2016
@@ -2310,6 +2310,7 @@ void ASTStmtReader::VisitOMPLoopDirectiv
   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())) {

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Mar 29 03:58:54 2016
@@ -2097,6 +2097,7 @@ void ASTStmtWriter::VisitOMPLoopDirectiv
   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())) {

Modified: cfe/trunk/test/OpenMP/distribute_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/distribute_codegen.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/distribute_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/distribute_codegen.cpp Tue Mar 29 03:58:54 2016
@@ -224,8 +224,10 @@ void test_precond() {
 // ..many loads of %0..
 // CHECK:  [[A2:%.+]] = load i8*, i8** [[APTRADDR]]
 // CHECK:  [[AVAL0:%.+]] = load i8, i8* [[A2]]
-// CHECK:  [[AVAL1:%.+]] = load i8, i8* [[A2]]
-// CHECK:  [[AVAL2:%.+]] = load i8, i8* [[A2]]
+// CHECK:  store i8 [[AVAL0]], i8* [[CAP_EXPR:%.+]],
+// CHECK:  [[AVAL1:%.+]] = load i8, i8* [[CAP_EXPR]]
+// CHECK:  load i8, i8* [[CAP_EXPR]]
+// CHECK:  [[AVAL2:%.+]] = load i8, i8* [[CAP_EXPR]]
 // CHECK:  [[ACONV:%.+]] = sext i8 [[AVAL2]] to i32
 // CHECK:  [[ACMP:%.+]] = icmp slt i32 [[ACONV]], 10
 // CHECK:  br i1 [[ACMP]], label %[[PRECOND_THEN:.+]], label %[[PRECOND_END:.+]]

Modified: cfe/trunk/test/OpenMP/for_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_codegen.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/for_codegen.cpp Tue Mar 29 03:58:54 2016
@@ -327,12 +327,13 @@ void runtime(float *a, float *b, float *
 // CHECK-LABEL: test_precond
 void test_precond() {
   // CHECK: [[A_ADDR:%.+]] = alloca i8,
+  // CHECK: [[CAP:%.+]] = alloca i8,
   // CHECK: [[I_ADDR:%.+]] = alloca i8,
   char a = 0;
   // CHECK: store i8 0,
   // CHECK: store i32
   // CHECK: store i8
-  // CHECK: [[A:%.+]] = load i8, i8* [[A_ADDR]],
+  // CHECK: [[A:%.+]] = load i8, i8* [[CAP]],
   // CHECK: [[CONV:%.+]] = sext i8 [[A]] to i32
   // CHECK: [[CMP:%.+]] = icmp slt i32 [[CONV]], 10
   // CHECK: br i1 [[CMP]], label %[[PRECOND_THEN:[^,]+]], label %[[PRECOND_END:[^,]+]]

Modified: cfe/trunk/test/OpenMP/for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -439,12 +439,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -495,7 +495,7 @@ int test_with_random_access_iterator() {
 #pragma omp for
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
-// expected-error at +4 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +4 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp parallel
 #pragma omp for

Modified: cfe/trunk/test/OpenMP/for_simd_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_simd_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_simd_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_simd_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -408,12 +408,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -465,7 +465,7 @@ int test_with_random_access_iterator() {
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
 #pragma omp parallel
-// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp for simd
   for (begin = begin0; begin < end; ++begin)

Modified: cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -354,12 +354,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -402,7 +402,7 @@ int test_with_random_access_iterator() {
 #pragma omp parallel for
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
-// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp parallel for
   for (begin = begin0; begin < end; ++begin)

Modified: cfe/trunk/test/OpenMP/parallel_for_simd_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_simd_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_simd_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_simd_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -355,12 +355,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -403,7 +403,7 @@ int test_with_random_access_iterator() {
 #pragma omp parallel for simd
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
-// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp parallel for simd
   for (begin = begin0; begin < end; ++begin)

Modified: cfe/trunk/test/OpenMP/simd_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/simd_codegen.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/simd_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/simd_codegen.cpp Tue Mar 29 03:58:54 2016
@@ -321,7 +321,6 @@ public:
 // CHECK-LABEL: define {{.*void}} @{{.*}}iter_simple{{.*}}
 void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
 //
-// CHECK: store i32 0, i32* [[IT_OMP_IV:%[^,]+]]
 // Calculate number of iterations before the loop body.
 // CHECK: [[DIFF1:%.+]] = invoke {{.*}}i32 @{{.*}}IterDouble{{.*}}
 // CHECK: [[DIFF2:%.+]] = sub nsw i32 [[DIFF1]], 1
@@ -329,6 +328,7 @@ void iter_simple(IterDouble ia, IterDoub
 // CHECK-NEXT: [[DIFF4:%.+]] = sdiv i32 [[DIFF3]], 1
 // CHECK-NEXT: [[DIFF5:%.+]] = sub nsw i32 [[DIFF4]], 1
 // CHECK-NEXT: store i32 [[DIFF5]], i32* [[OMP_LAST_IT:%[^,]+]]{{.+}}
+// CHECK: store i32 0, i32* [[IT_OMP_IV:%[^,]+]]
   #pragma omp simd
 
 // CHECK: [[IV:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}} !llvm.mem.parallel_loop_access ![[ITER_LOOP_ID:[0-9]+]]

Modified: cfe/trunk/test/OpenMP/target_parallel_for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/target_parallel_for_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/target_parallel_for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/target_parallel_for_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -354,12 +354,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -402,7 +402,7 @@ int test_with_random_access_iterator() {
 #pragma omp target parallel for
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
-// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +3 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp target parallel for
   for (begin = begin0; begin < end; ++begin)

Modified: cfe/trunk/test/OpenMP/taskloop_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/taskloop_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/taskloop_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/taskloop_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -427,12 +427,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -483,7 +483,7 @@ int test_with_random_access_iterator() {
 #pragma omp taskloop
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
-// expected-error at +4 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +4 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp parallel
 #pragma omp taskloop

Modified: cfe/trunk/test/OpenMP/taskloop_simd_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/taskloop_simd_loop_messages.cpp?rev=264709&r1=264708&r2=264709&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/taskloop_simd_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/taskloop_simd_loop_messages.cpp Tue Mar 29 03:58:54 2016
@@ -428,12 +428,12 @@ public:
   typedef int difference_type;
   typedef std::random_access_iterator_tag iterator_category;
 };
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 int operator-(GoodIter a, GoodIter b) { return 0; }
 // expected-note at +1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
 GoodIter operator-(GoodIter a) { return a; }
-// expected-note at +2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 2nd argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
 GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
 // expected-note at +1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
@@ -484,7 +484,7 @@ int test_with_random_access_iterator() {
 #pragma omp taskloop simd
   for (begin = GoodIter(0); begin < end; ++begin)
     ++begin;
-// expected-error at +4 {{invalid operands to binary expression ('GoodIter' and 'Iter0')}}
+// expected-error at +4 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
 // expected-error at +3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
 #pragma omp parallel
 #pragma omp taskloop simd




More information about the cfe-commits mailing list