<div dir="ltr">This had some dead variables where you should have used isa rather than dyn_cast. I've fixed them in r307988<div><br></div><div>Also for some post commit review this is a ton of mostly uncommented code.</div><div><br></div><div>-eric</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 13, 2017 at 6:36 AM Alexey Bataev via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: abataev<br>
Date: Thu Jul 13 06:36:14 2017<br>
New Revision: 307910<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=307910&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=307910&view=rev</a><br>
Log:<br>
[OPENMP] Generalization of codegen for reduction clauses.<br>
<br>
Reworked codegen for reduction clauses for future support of reductions<br>
in task-based directives.<br>
<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp<br>
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h<br>
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp<br>
    cfe/trunk/test/OpenMP/for_reduction_codegen.cpp<br>
    cfe/trunk/test/OpenMP/for_reduction_codegen_UDR.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=307910&r1=307909&r2=307910&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=307910&r1=307909&r2=307910&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Thu Jul 13 06:36:14 2017<br>
@@ -697,6 +697,400 @@ void RegionCodeGenTy::operator()(CodeGen<br>
   }<br>
 }<br>
<br>
+/// Check if the combiner is a call to UDR combiner and if it is so return the<br>
+/// UDR decl used for reduction.<br>
+static const OMPDeclareReductionDecl *<br>
+getReductionInit(const Expr *ReductionOp) {<br>
+  if (auto *CE = dyn_cast<CallExpr>(ReductionOp))<br>
+    if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))<br>
+      if (auto *DRE =<br>
+              dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))<br>
+        if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))<br>
+          return DRD;<br>
+  return nullptr;<br>
+}<br>
+<br>
+static void emitInitWithReductionInitializer(CodeGenFunction &CGF,<br>
+                                             const OMPDeclareReductionDecl *DRD,<br>
+                                             const Expr *InitOp,<br>
+                                             Address Private, Address Original,<br>
+                                             QualType Ty) {<br>
+  if (DRD->getInitializer()) {<br>
+    std::pair<llvm::Function *, llvm::Function *> Reduction =<br>
+        CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);<br>
+    auto *CE = cast<CallExpr>(InitOp);<br>
+    auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());<br>
+    const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();<br>
+    const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();<br>
+    auto *LHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());<br>
+    auto *RHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());<br>
+    CodeGenFunction::OMPPrivateScope PrivateScope(CGF);<br>
+    PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),<br>
+                            [=]() -> Address { return Private; });<br>
+    PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),<br>
+                            [=]() -> Address { return Original; });<br>
+    (void)PrivateScope.Privatize();<br>
+    RValue Func = RValue::get(Reduction.second);<br>
+    CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);<br>
+    CGF.EmitIgnoredExpr(InitOp);<br>
+  } else {<br>
+    llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);<br>
+    auto *GV = new llvm::GlobalVariable(<br>
+        CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,<br>
+        llvm::GlobalValue::PrivateLinkage, Init, ".init");<br>
+    LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);<br>
+    RValue InitRVal;<br>
+    switch (CGF.getEvaluationKind(Ty)) {<br>
+    case TEK_Scalar:<br>
+      InitRVal = CGF.EmitLoadOfLValue(LV, SourceLocation());<br>
+      break;<br>
+    case TEK_Complex:<br>
+      InitRVal =<br>
+          RValue::getComplex(CGF.EmitLoadOfComplex(LV, SourceLocation()));<br>
+      break;<br>
+    case TEK_Aggregate:<br>
+      InitRVal = RValue::getAggregate(LV.getAddress());<br>
+      break;<br>
+    }<br>
+    OpaqueValueExpr OVE(SourceLocation(), Ty, VK_RValue);<br>
+    CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);<br>
+    CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),<br>
+                         /*IsInitializer=*/false);<br>
+  }<br>
+}<br>
+<br>
+/// \brief Emit initialization of arrays of complex types.<br>
+/// \param DestAddr Address of the array.<br>
+/// \param Type Type of array.<br>
+/// \param Init Initial expression of array.<br>
+/// \param SrcAddr Address of the original array.<br>
+static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,<br>
+                                 QualType Type, const Expr *Init,<br>
+                                 Address SrcAddr = Address::invalid()) {<br>
+  auto *DRD = getReductionInit(Init);<br>
+  // Perform element-by-element initialization.<br>
+  QualType ElementTy;<br>
+<br>
+  // Drill down to the base element type on both arrays.<br>
+  auto ArrayTy = Type->getAsArrayTypeUnsafe();<br>
+  auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);<br>
+  DestAddr =<br>
+      CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());<br>
+  if (DRD)<br>
+    SrcAddr =<br>
+        CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());<br>
+<br>
+  llvm::Value *SrcBegin = nullptr;<br>
+  if (DRD)<br>
+    SrcBegin = SrcAddr.getPointer();<br>
+  auto DestBegin = DestAddr.getPointer();<br>
+  // Cast from pointer to array type to pointer to single element.<br>
+  auto DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);<br>
+  // The basic structure here is a while-do loop.<br>
+  auto BodyBB = CGF.createBasicBlock("omp.arrayinit.body");<br>
+  auto DoneBB = CGF.createBasicBlock("omp.arrayinit.done");<br>
+  auto IsEmpty =<br>
+      CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");<br>
+  CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);<br>
+<br>
+  // Enter the loop body, making that address the current address.<br>
+  auto EntryBB = CGF.Builder.GetInsertBlock();<br>
+  CGF.EmitBlock(BodyBB);<br>
+<br>
+  CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);<br>
+<br>
+  llvm::PHINode *SrcElementPHI = nullptr;<br>
+  Address SrcElementCurrent = Address::invalid();<br>
+  if (DRD) {<br>
+    SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,<br>
+                                          "omp.arraycpy.srcElementPast");<br>
+    SrcElementPHI->addIncoming(SrcBegin, EntryBB);<br>
+    SrcElementCurrent =<br>
+        Address(SrcElementPHI,<br>
+                SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));<br>
+  }<br>
+  llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(<br>
+      DestBegin->getType(), 2, "omp.arraycpy.destElementPast");<br>
+  DestElementPHI->addIncoming(DestBegin, EntryBB);<br>
+  Address DestElementCurrent =<br>
+      Address(DestElementPHI,<br>
+              DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));<br>
+<br>
+  // Emit copy.<br>
+  {<br>
+    CodeGenFunction::RunCleanupsScope InitScope(CGF);<br>
+    if (DRD && (DRD->getInitializer() || !Init)) {<br>
+      emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,<br>
+                                       SrcElementCurrent, ElementTy);<br>
+    } else<br>
+      CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),<br>
+                           /*IsInitializer=*/false);<br>
+  }<br>
+<br>
+  if (DRD) {<br>
+    // Shift the address forward by one element.<br>
+    auto SrcElementNext = CGF.Builder.CreateConstGEP1_32(<br>
+        SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");<br>
+    SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());<br>
+  }<br>
+<br>
+  // Shift the address forward by one element.<br>
+  auto DestElementNext = CGF.Builder.CreateConstGEP1_32(<br>
+      DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");<br>
+  // Check whether we've reached the end.<br>
+  auto Done =<br>
+      CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");<br>
+  CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);<br>
+  DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());<br>
+<br>
+  // Done.<br>
+  CGF.EmitBlock(DoneBB, /*IsFinished=*/true);<br>
+}<br>
+<br>
+LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {<br>
+  if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))<br>
+    return CGF.EmitOMPArraySectionExpr(OASE);<br>
+  if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))<br>
+    return CGF.EmitLValue(ASE);<br>
+  auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());<br>
+  DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),<br>
+                  CGF.CapturedStmtInfo &&<br>
+                      CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,<br>
+                  E->getType(), VK_LValue, E->getExprLoc());<br>
+  // Store the address of the original variable associated with the LHS<br>
+  // implicit variable.<br>
+  return CGF.EmitLValue(&DRE);<br>
+}<br>
+<br>
+LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,<br>
+                                            const Expr *E) {<br>
+  if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))<br>
+    return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);<br>
+  return LValue();<br>
+}<br>
+<br>
+void ReductionCodeGen::emitAggregateInitialization(CodeGenFunction &CGF,<br>
+                                                   unsigned N,<br>
+                                                   Address PrivateAddr,<br>
+                                                   LValue SharedLVal) {<br>
+  // Emit VarDecl with copy init for arrays.<br>
+  // Get the address of the original variable captured in current<br>
+  // captured region.<br>
+  auto *PrivateVD =<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());<br>
+  auto *DRD = getReductionInit(ClausesData[N].ReductionOp);<br>
+  EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),<br>
+                       DRD ? ClausesData[N].ReductionOp : PrivateVD->getInit(),<br>
+                       SharedLVal.getAddress());<br>
+}<br>
+<br>
+ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,<br>
+                                   ArrayRef<const Expr *> Privates,<br>
+                                   ArrayRef<const Expr *> ReductionOps) {<br>
+  ClausesData.reserve(Shareds.size());<br>
+  SharedAddresses.reserve(Shareds.size());<br>
+  Sizes.reserve(Shareds.size());<br>
+  auto IPriv = Privates.begin();<br>
+  auto IRed = ReductionOps.begin();<br>
+  for (const auto *Ref : Shareds) {<br>
+    ClausesData.emplace_back(Ref, *IPriv, *IRed);<br>
+    std::advance(IPriv, 1);<br>
+    std::advance(IRed, 1);<br>
+  }<br>
+}<br>
+<br>
+void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {<br>
+  assert(SharedAddresses.size() == N &&<br>
+         "Number of generated lvalues must be exactly N.");<br>
+  SharedAddresses.emplace_back(emitSharedLValue(CGF, ClausesData[N].Ref),<br>
+                               emitSharedLValueUB(CGF, ClausesData[N].Ref));<br>
+}<br>
+<br>
+void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {<br>
+  auto *PrivateVD =<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());<br>
+  QualType PrivateType = PrivateVD->getType();<br>
+  bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);<br>
+  if (!AsArraySection && !PrivateType->isVariablyModifiedType()) {<br>
+    Sizes.emplace_back(nullptr);<br>
+    return;<br>
+  }<br>
+  llvm::Value *Size;<br>
+  if (AsArraySection) {<br>
+    Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(),<br>
+                                     SharedAddresses[N].first.getPointer());<br>
+    Size = CGF.Builder.CreateNUWAdd(<br>
+        Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));<br>
+  } else {<br>
+    Size = CGF.getTypeSize(<br>
+        SharedAddresses[N].first.getType().getNonReferenceType());<br>
+  }<br>
+  Sizes.emplace_back(Size);<br>
+  CodeGenFunction::OpaqueValueMapping OpaqueMap(<br>
+      CGF,<br>
+      cast<OpaqueValueExpr>(<br>
+          CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),<br>
+      RValue::get(Size));<br>
+  CGF.EmitVariablyModifiedType(PrivateType);<br>
+}<br>
+<br>
+void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,<br>
+                                         llvm::Value *Size) {<br>
+  auto *PrivateVD =<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());<br>
+  QualType PrivateType = PrivateVD->getType();<br>
+  bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);<br>
+  if (!AsArraySection && !PrivateType->isVariablyModifiedType()) {<br>
+    assert(!Size && !Sizes[N] &&<br>
+           "Size should be nullptr for non-variably modified redution "<br>
+           "items.");<br>
+    return;<br>
+  }<br>
+  CodeGenFunction::OpaqueValueMapping OpaqueMap(<br>
+      CGF,<br>
+      cast<OpaqueValueExpr>(<br>
+          CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),<br>
+      RValue::get(Size));<br>
+  CGF.EmitVariablyModifiedType(PrivateType);<br>
+}<br>
+<br>
+void ReductionCodeGen::emitInitialization(<br>
+    CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,<br>
+    llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {<br>
+  assert(SharedAddresses.size() > N && "No variable was generated");<br>
+  auto *PrivateVD =<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());<br>
+  auto *DRD = getReductionInit(ClausesData[N].ReductionOp);<br>
+  QualType PrivateType = PrivateVD->getType();<br>
+  PrivateAddr = CGF.Builder.CreateElementBitCast(<br>
+      PrivateAddr, CGF.ConvertTypeForMem(PrivateType));<br>
+  QualType SharedType = SharedAddresses[N].first.getType();<br>
+  SharedLVal = CGF.MakeAddrLValue(<br>
+      CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),<br>
+                                       CGF.ConvertTypeForMem(SharedType)),<br>
+      SharedType, SharedAddresses[N].first.getBaseInfo());<br>
+  if (isa<OMPArraySectionExpr>(ClausesData[N].Ref) ||<br>
+      CGF.getContext().getAsArrayType(PrivateVD->getType())) {<br>
+    emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal);<br>
+  } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {<br>
+    emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,<br>
+                                     PrivateAddr, SharedLVal.getAddress(),<br>
+                                     SharedLVal.getType());<br>
+  } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&<br>
+             !CGF.isTrivialInitializer(PrivateVD->getInit())) {<br>
+    CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,<br>
+                         PrivateVD->getType().getQualifiers(),<br>
+                         /*IsInitializer=*/false);<br>
+  }<br>
+}<br>
+<br>
+bool ReductionCodeGen::needCleanups(unsigned N) {<br>
+  auto *PrivateVD =<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());<br>
+  QualType PrivateType = PrivateVD->getType();<br>
+  QualType::DestructionKind DTorKind = PrivateType.isDestructedType();<br>
+  return DTorKind != QualType::DK_none;<br>
+}<br>
+<br>
+void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,<br>
+                                    Address PrivateAddr) {<br>
+  auto *PrivateVD =<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());<br>
+  QualType PrivateType = PrivateVD->getType();<br>
+  QualType::DestructionKind DTorKind = PrivateType.isDestructedType();<br>
+  if (needCleanups(N)) {<br>
+    PrivateAddr = CGF.Builder.CreateElementBitCast(<br>
+        PrivateAddr, CGF.ConvertTypeForMem(PrivateType));<br>
+    CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);<br>
+  }<br>
+}<br>
+<br>
+static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,<br>
+                          LValue BaseLV) {<br>
+  BaseTy = BaseTy.getNonReferenceType();<br>
+  while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&<br>
+         !CGF.getContext().hasSameType(BaseTy, ElTy)) {<br>
+    if (auto *PtrTy = BaseTy->getAs<PointerType>())<br>
+      BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);<br>
+    else {<br>
+      BaseLV = CGF.EmitLoadOfReferenceLValue(BaseLV.getAddress(),<br>
+                                             BaseTy->castAs<ReferenceType>());<br>
+    }<br>
+    BaseTy = BaseTy->getPointeeType();<br>
+  }<br>
+  return CGF.MakeAddrLValue(<br>
+      CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),<br>
+                                       CGF.ConvertTypeForMem(ElTy)),<br>
+      BaseLV.getType(), BaseLV.getBaseInfo());<br>
+}<br>
+<br>
+static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,<br>
+                          llvm::Type *BaseLVType, CharUnits BaseLVAlignment,<br>
+                          llvm::Value *Addr) {<br>
+  Address Tmp = Address::invalid();<br>
+  Address TopTmp = Address::invalid();<br>
+  Address MostTopTmp = Address::invalid();<br>
+  BaseTy = BaseTy.getNonReferenceType();<br>
+  while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&<br>
+         !CGF.getContext().hasSameType(BaseTy, ElTy)) {<br>
+    Tmp = CGF.CreateMemTemp(BaseTy);<br>
+    if (TopTmp.isValid())<br>
+      CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);<br>
+    else<br>
+      MostTopTmp = Tmp;<br>
+    TopTmp = Tmp;<br>
+    BaseTy = BaseTy->getPointeeType();<br>
+  }<br>
+  llvm::Type *Ty = BaseLVType;<br>
+  if (Tmp.isValid())<br>
+    Ty = Tmp.getElementType();<br>
+  Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);<br>
+  if (Tmp.isValid()) {<br>
+    CGF.Builder.CreateStore(Addr, Tmp);<br>
+    return MostTopTmp;<br>
+  }<br>
+  return Address(Addr, BaseLVAlignment);<br>
+}<br>
+<br>
+Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,<br>
+                                               Address PrivateAddr) {<br>
+  const DeclRefExpr *DE;<br>
+  const VarDecl *OrigVD = nullptr;<br>
+  if (auto *OASE = dyn_cast<OMPArraySectionExpr>(ClausesData[N].Ref)) {<br>
+    auto *Base = OASE->getBase()->IgnoreParenImpCasts();<br>
+    while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))<br>
+      Base = TempOASE->getBase()->IgnoreParenImpCasts();<br>
+    while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))<br>
+      Base = TempASE->getBase()->IgnoreParenImpCasts();<br>
+    DE = cast<DeclRefExpr>(Base);<br>
+    OrigVD = cast<VarDecl>(DE->getDecl());<br>
+  } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(ClausesData[N].Ref)) {<br>
+    auto *Base = ASE->getBase()->IgnoreParenImpCasts();<br>
+    while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))<br>
+      Base = TempASE->getBase()->IgnoreParenImpCasts();<br>
+    DE = cast<DeclRefExpr>(Base);<br>
+    OrigVD = cast<VarDecl>(DE->getDecl());<br>
+  }<br>
+  if (OrigVD) {<br>
+    BaseDecls.emplace_back(OrigVD);<br>
+    auto OriginalBaseLValue = CGF.EmitLValue(DE);<br>
+    LValue BaseLValue =<br>
+        loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),<br>
+                    OriginalBaseLValue);<br>
+    llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(<br>
+        BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());<br>
+    llvm::Value *Ptr =<br>
+        CGF.Builder.CreateGEP(PrivateAddr.getPointer(), Adjustment);<br>
+    return castToBase(CGF, OrigVD->getType(),<br>
+                      SharedAddresses[N].first.getType(),<br>
+                      OriginalBaseLValue.getPointer()->getType(),<br>
+                      OriginalBaseLValue.getAlignment(), Ptr);<br>
+  }<br>
+  BaseDecls.emplace_back(<br>
+      cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));<br>
+  return PrivateAddr;<br>
+}<br>
+<br>
 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {<br>
   return CGF.EmitLoadOfPointerLValue(<br>
       CGF.GetAddrOfLocalVar(getThreadIDVariable()),<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=307910&r1=307909&r2=307910&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h?rev=307910&r1=307909&r2=307910&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.h Thu Jul 13 06:36:14 2017<br>
@@ -105,6 +105,86 @@ struct OMPTaskDataTy final {<br>
   bool Nogroup = false;<br>
 };<br>
<br>
+/// Class intended to support codegen of all kind of the reduction clauses.<br>
+class ReductionCodeGen {<br>
+private:<br>
+  /// Data requiored for codegen of reduction clauses.<br>
+  struct ReductionData {<br>
+    /// Reference to the original shared item.<br>
+    const Expr *Ref = nullptr;<br>
+    /// Helper expression for generation of private copy.<br>
+    const Expr *Private = nullptr;<br>
+    /// Helper expression for generation reduction operation.<br>
+    const Expr *ReductionOp = nullptr;<br>
+    ReductionData(const Expr *Ref, const Expr *Private, const Expr *ReductionOp)<br>
+        : Ref(Ref), Private(Private), ReductionOp(ReductionOp) {}<br>
+  };<br>
+  /// List of reduction-based clauses.<br>
+  SmallVector<ReductionData, 4> ClausesData;<br>
+<br>
+  /// List of addresses of original shared variables/expressions.<br>
+  SmallVector<std::pair<LValue, LValue>, 4> SharedAddresses;<br>
+  /// Sizes of the reduction items in chars.<br>
+  SmallVector<llvm::Value *, 4> Sizes;<br>
+  /// Base declarations for the reduction items.<br>
+  SmallVector<const VarDecl *, 4> BaseDecls;<br>
+  /// Emits lvalue for shared expresion.<br>
+  LValue emitSharedLValue(CodeGenFunction &CGF, const Expr *E);<br>
+  /// Emits upper bound for shared expression (if array section).<br>
+  LValue emitSharedLValueUB(CodeGenFunction &CGF, const Expr *E);<br>
+  /// Performs aggregate initialization.<br>
+  /// \param N Number of reduction item in the common list.<br>
+  /// \param PrivateAddr Address of the corresponding private item.<br>
+  /// \param SharedLVal Addreiss of the original shared variable.<br>
+  void emitAggregateInitialization(CodeGenFunction &CGF, unsigned N,<br>
+                                   Address PrivateAddr, LValue SharedLVal);<br>
+<br>
+public:<br>
+  ReductionCodeGen(ArrayRef<const Expr *> Shareds,<br>
+                   ArrayRef<const Expr *> Privates,<br>
+                   ArrayRef<const Expr *> ReductionOps);<br>
+  /// Emits lvalue for a reduction item.<br>
+  /// \param N Number of the reduction item.<br>
+  void emitSharedLValue(CodeGenFunction &CGF, unsigned N);<br>
+  /// Emits the code for the variable-modified type, if required.<br>
+  /// \param N Number of the reduction item.<br>
+  void emitAggregateType(CodeGenFunction &CGF, unsigned N);<br>
+  /// Emits the code for the variable-modified type, if required.<br>
+  /// \param N Number of the reduction item.<br>
+  /// \param Size Size of the type in chars.<br>
+  void emitAggregateType(CodeGenFunction &CGF, unsigned N, llvm::Value *Size);<br>
+  /// Performs initialization of the private copy for the reduction item.<br>
+  /// \param N Number of the reduction item.<br>
+  /// \param PrivateAddr Address of the corresponding private item.<br>
+  /// \param DefaultInit Default initialization sequence that should be<br>
+  /// performed if no reduction specific initialization is found.<br>
+  /// \param SharedLVal Addreiss of the original shared variable.<br>
+  /// \return true, if the initialization sequence was emitted, false otherwise.<br>
+  void<br>
+  emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr,<br>
+                     LValue SharedLVal,<br>
+                     llvm::function_ref<bool(CodeGenFunction &)> DefaultInit);<br>
+  /// ReturCns true if the private copy requires cleanups.<br>
+  bool needCleanups(unsigned N);<br>
+  /// Emits cleanup code nfor the reduction item.<br>
+  /// \param N Number of the reduction item.<br>
+  /// \param PrivateAddr Address of the corresponding private item.<br>
+  void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr);<br>
+  /// Adjusts \p PrivatedAddr for using ninstead of the original variable<br>
+  /// address in normal operations.<br>
+  /// \param N Number of the reduction item.<br>
+  /// \param PrivateAddr Address of the corresponding private item.<br>
+  Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,<br>
+                               Address PrivateAddr);<br>
+  /// Returns LValue for the reduction item.<br>
+  LValue getSharedLValue(unsigned N) const { return SharedAddresses[N].first; }<br>
+  /// Returns the size of the reduction item in chars, or nullptr, if the size<br>
+  /// is a constant.<br>
+  llvm::Value *getSizeInChars(unsigned N) const { return Sizes[N]; }<br>
+  /// Returns the base declaration of the reduction item.<br>
+  const VarDecl *getBaseDecl(unsigned N) const { return BaseDecls[N]; }<br>
+};<br>
+<br>
 class CGOpenMPRuntime {<br>
 protected:<br>
   CodeGenModule &CGM;<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=307910&r1=307909&r2=307910&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=307910&r1=307909&r2=307910&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Thu Jul 13 06:36:14 2017<br>
@@ -549,156 +549,6 @@ void CodeGenFunction::EmitOMPAggregateAs<br>
   EmitBlock(DoneBB, /*IsFinished=*/true);<br>
 }<br>
<br>
-/// Check if the combiner is a call to UDR combiner and if it is so return the<br>
-/// UDR decl used for reduction.<br>
-static const OMPDeclareReductionDecl *<br>
-getReductionInit(const Expr *ReductionOp) {<br>
-  if (auto *CE = dyn_cast<CallExpr>(ReductionOp))<br>
-    if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))<br>
-      if (auto *DRE =<br>
-              dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))<br>
-        if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))<br>
-          return DRD;<br>
-  return nullptr;<br>
-}<br>
-<br>
-static void emitInitWithReductionInitializer(CodeGenFunction &CGF,<br>
-                                             const OMPDeclareReductionDecl *DRD,<br>
-                                             const Expr *InitOp,<br>
-                                             Address Private, Address Original,<br>
-                                             QualType Ty) {<br>
-  if (DRD->getInitializer()) {<br>
-    std::pair<llvm::Function *, llvm::Function *> Reduction =<br>
-        CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);<br>
-    auto *CE = cast<CallExpr>(InitOp);<br>
-    auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());<br>
-    const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();<br>
-    const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();<br>
-    auto *LHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());<br>
-    auto *RHSDRE = cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());<br>
-    CodeGenFunction::OMPPrivateScope PrivateScope(CGF);<br>
-    PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),<br>
-                            [=]() -> Address { return Private; });<br>
-    PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),<br>
-                            [=]() -> Address { return Original; });<br>
-    (void)PrivateScope.Privatize();<br>
-    RValue Func = RValue::get(Reduction.second);<br>
-    CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);<br>
-    CGF.EmitIgnoredExpr(InitOp);<br>
-  } else {<br>
-    llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);<br>
-    auto *GV = new llvm::GlobalVariable(<br>
-        CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,<br>
-        llvm::GlobalValue::PrivateLinkage, Init, ".init");<br>
-    LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);<br>
-    RValue InitRVal;<br>
-    switch (CGF.getEvaluationKind(Ty)) {<br>
-    case TEK_Scalar:<br>
-      InitRVal = CGF.EmitLoadOfLValue(LV, SourceLocation());<br>
-      break;<br>
-    case TEK_Complex:<br>
-      InitRVal =<br>
-          RValue::getComplex(CGF.EmitLoadOfComplex(LV, SourceLocation()));<br>
-      break;<br>
-    case TEK_Aggregate:<br>
-      InitRVal = RValue::getAggregate(LV.getAddress());<br>
-      break;<br>
-    }<br>
-    OpaqueValueExpr OVE(SourceLocation(), Ty, VK_RValue);<br>
-    CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);<br>
-    CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),<br>
-                         /*IsInitializer=*/false);<br>
-  }<br>
-}<br>
-<br>
-/// \brief Emit initialization of arrays of complex types.<br>
-/// \param DestAddr Address of the array.<br>
-/// \param Type Type of array.<br>
-/// \param Init Initial expression of array.<br>
-/// \param SrcAddr Address of the original array.<br>
-static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,<br>
-                                 QualType Type, const Expr *Init,<br>
-                                 Address SrcAddr = Address::invalid()) {<br>
-  auto *DRD = getReductionInit(Init);<br>
-  // Perform element-by-element initialization.<br>
-  QualType ElementTy;<br>
-<br>
-  // Drill down to the base element type on both arrays.<br>
-  auto ArrayTy = Type->getAsArrayTypeUnsafe();<br>
-  auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);<br>
-  DestAddr =<br>
-      CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());<br>
-  if (DRD)<br>
-    SrcAddr =<br>
-        CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());<br>
-<br>
-  llvm::Value *SrcBegin = nullptr;<br>
-  if (DRD)<br>
-    SrcBegin = SrcAddr.getPointer();<br>
-  auto DestBegin = DestAddr.getPointer();<br>
-  // Cast from pointer to array type to pointer to single element.<br>
-  auto DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);<br>
-  // The basic structure here is a while-do loop.<br>
-  auto BodyBB = CGF.createBasicBlock("omp.arrayinit.body");<br>
-  auto DoneBB = CGF.createBasicBlock("omp.arrayinit.done");<br>
-  auto IsEmpty =<br>
-      CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");<br>
-  CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);<br>
-<br>
-  // Enter the loop body, making that address the current address.<br>
-  auto EntryBB = CGF.Builder.GetInsertBlock();<br>
-  CGF.EmitBlock(BodyBB);<br>
-<br>
-  CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);<br>
-<br>
-  llvm::PHINode *SrcElementPHI = nullptr;<br>
-  Address SrcElementCurrent = Address::invalid();<br>
-  if (DRD) {<br>
-    SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,<br>
-                                          "omp.arraycpy.srcElementPast");<br>
-    SrcElementPHI->addIncoming(SrcBegin, EntryBB);<br>
-    SrcElementCurrent =<br>
-        Address(SrcElementPHI,<br>
-                SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));<br>
-  }<br>
-  llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(<br>
-      DestBegin->getType(), 2, "omp.arraycpy.destElementPast");<br>
-  DestElementPHI->addIncoming(DestBegin, EntryBB);<br>
-  Address DestElementCurrent =<br>
-      Address(DestElementPHI,<br>
-              DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));<br>
-<br>
-  // Emit copy.<br>
-  {<br>
-    CodeGenFunction::RunCleanupsScope InitScope(CGF);<br>
-    if (DRD && (DRD->getInitializer() || !Init)) {<br>
-      emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,<br>
-                                       SrcElementCurrent, ElementTy);<br>
-    } else<br>
-      CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),<br>
-                           /*IsInitializer=*/false);<br>
-  }<br>
-<br>
-  if (DRD) {<br>
-    // Shift the address forward by one element.<br>
-    auto SrcElementNext = CGF.Builder.CreateConstGEP1_32(<br>
-        SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");<br>
-    SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());<br>
-  }<br>
-<br>
-  // Shift the address forward by one element.<br>
-  auto DestElementNext = CGF.Builder.CreateConstGEP1_32(<br>
-      DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");<br>
-  // Check whether we've reached the end.<br>
-  auto Done =<br>
-      CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");<br>
-  CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);<br>
-  DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());<br>
-<br>
-  // Done.<br>
-  CGF.EmitBlock(DoneBB, /*IsFinished=*/true);<br>
-}<br>
-<br>
 void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,<br>
                                   Address SrcAddr, const VarDecl *DestVD,<br>
                                   const VarDecl *SrcVD, const Expr *Copy) {<br>
@@ -1051,253 +901,106 @@ void CodeGenFunction::EmitOMPLastprivate<br>
     EmitBlock(DoneBB, /*IsFinished=*/true);<br>
 }<br>
<br>
-static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,<br>
-                          LValue BaseLV, llvm::Value *Addr) {<br>
-  Address Tmp = Address::invalid();<br>
-  Address TopTmp = Address::invalid();<br>
-  Address MostTopTmp = Address::invalid();<br>
-  BaseTy = BaseTy.getNonReferenceType();<br>
-  while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&<br>
-         !CGF.getContext().hasSameType(BaseTy, ElTy)) {<br>
-    Tmp = CGF.CreateMemTemp(BaseTy);<br>
-    if (TopTmp.isValid())<br>
-      CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);<br>
-    else<br>
-      MostTopTmp = Tmp;<br>
-    TopTmp = Tmp;<br>
-    BaseTy = BaseTy->getPointeeType();<br>
-  }<br>
-  llvm::Type *Ty = BaseLV.getPointer()->getType();<br>
-  if (Tmp.isValid())<br>
-    Ty = Tmp.getElementType();<br>
-  Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);<br>
-  if (Tmp.isValid()) {<br>
-    CGF.Builder.CreateStore(Addr, Tmp);<br>
-    return MostTopTmp;<br>
-  }<br>
-  return Address(Addr, BaseLV.getAlignment());<br>
-}<br>
-<br>
-static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,<br>
-                          LValue BaseLV) {<br>
-  BaseTy = BaseTy.getNonReferenceType();<br>
-  while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&<br>
-         !CGF.getContext().hasSameType(BaseTy, ElTy)) {<br>
-    if (auto *PtrTy = BaseTy->getAs<PointerType>())<br>
-      BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);<br>
-    else {<br>
-      BaseLV = CGF.EmitLoadOfReferenceLValue(BaseLV.getAddress(),<br>
-                                             BaseTy->castAs<ReferenceType>());<br>
-    }<br>
-    BaseTy = BaseTy->getPointeeType();<br>
-  }<br>
-  return CGF.MakeAddrLValue(<br>
-      Address(<br>
-          CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(<br>
-              BaseLV.getPointer(), CGF.ConvertTypeForMem(ElTy)->getPointerTo()),<br>
-          BaseLV.getAlignment()),<br>
-      BaseLV.getType(), BaseLV.getBaseInfo());<br>
-}<br>
-<br>
 void CodeGenFunction::EmitOMPReductionClauseInit(<br>
     const OMPExecutableDirective &D,<br>
     CodeGenFunction::OMPPrivateScope &PrivateScope) {<br>
   if (!HaveInsertPoint())<br>
     return;<br>
+  SmallVector<const Expr *, 4> Shareds;<br>
+  SmallVector<const Expr *, 4> Privates;<br>
+  SmallVector<const Expr *, 4> ReductionOps;<br>
+  SmallVector<const Expr *, 4> LHSs;<br>
+  SmallVector<const Expr *, 4> RHSs;<br>
   for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {<br>
-    auto ILHS = C->lhs_exprs().begin();<br>
-    auto IRHS = C->rhs_exprs().begin();<br>
     auto IPriv = C->privates().begin();<br>
     auto IRed = C->reduction_ops().begin();<br>
-    for (auto IRef : C->varlists()) {<br>
-      auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());<br>
-      auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());<br>
-      auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());<br>
-      auto *DRD = getReductionInit(*IRed);<br>
-      if (auto *OASE = dyn_cast<OMPArraySectionExpr>(IRef)) {<br>
-        auto *Base = OASE->getBase()->IgnoreParenImpCasts();<br>
-        while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))<br>
-          Base = TempOASE->getBase()->IgnoreParenImpCasts();<br>
-        while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))<br>
-          Base = TempASE->getBase()->IgnoreParenImpCasts();<br>
-        auto *DE = cast<DeclRefExpr>(Base);<br>
-        auto *OrigVD = cast<VarDecl>(DE->getDecl());<br>
-        auto OASELValueLB = EmitOMPArraySectionExpr(OASE);<br>
-        auto OASELValueUB =<br>
-            EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);<br>
-        auto OriginalBaseLValue = EmitLValue(DE);<br>
-        LValue BaseLValue =<br>
-            loadToBegin(*this, OrigVD->getType(), OASELValueLB.getType(),<br>
-                        OriginalBaseLValue);<br>
-        // Store the address of the original variable associated with the LHS<br>
-        // implicit variable.<br>
-        PrivateScope.addPrivate(LHSVD, [OASELValueLB]() -> Address {<br>
-          return OASELValueLB.getAddress();<br>
-        });<br>
-        // Emit reduction copy.<br>
-        bool IsRegistered = PrivateScope.addPrivate(<br>
-            OrigVD, [this, OrigVD, PrivateVD, BaseLValue, OASELValueLB,<br>
-                     OASELValueUB, OriginalBaseLValue, DRD, IRed]() -> Address {<br>
-              // Emit VarDecl with copy init for arrays.<br>
-              // Get the address of the original variable captured in current<br>
-              // captured region.<br>
-              auto *Size = Builder.CreatePtrDiff(OASELValueUB.getPointer(),<br>
-                                                 OASELValueLB.getPointer());<br>
-              Size = Builder.CreateNUWAdd(<br>
-                  Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));<br>
-              CodeGenFunction::OpaqueValueMapping OpaqueMap(<br>
-                  *this, cast<OpaqueValueExpr>(<br>
-                             getContext()<br>
-                                 .getAsVariableArrayType(PrivateVD->getType())<br>
-                                 ->getSizeExpr()),<br>
-                  RValue::get(Size));<br>
-              EmitVariablyModifiedType(PrivateVD->getType());<br>
-              auto Emission = EmitAutoVarAlloca(*PrivateVD);<br>
-              auto Addr = Emission.getAllocatedAddress();<br>
-              auto *Init = PrivateVD->getInit();<br>
-              EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(),<br>
-                                   DRD ? *IRed : Init,<br>
-                                   OASELValueLB.getAddress());<br>
-              EmitAutoVarCleanups(Emission);<br>
-              // Emit private VarDecl with reduction init.<br>
-              auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),<br>
-                                                   OASELValueLB.getPointer());<br>
-              auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);<br>
-              return castToBase(*this, OrigVD->getType(),<br>
-                                OASELValueLB.getType(), OriginalBaseLValue,<br>
-                                Ptr);<br>
-            });<br>
-        assert(IsRegistered && "private var already registered as private");<br>
-        // Silence the warning about unused variable.<br>
-        (void)IsRegistered;<br>
-        PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {<br>
-          return GetAddrOfLocalVar(PrivateVD);<br>
-        });<br>
-      } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(IRef)) {<br>
-        auto *Base = ASE->getBase()->IgnoreParenImpCasts();<br>
-        while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))<br>
-          Base = TempASE->getBase()->IgnoreParenImpCasts();<br>
-        auto *DE = cast<DeclRefExpr>(Base);<br>
-        auto *OrigVD = cast<VarDecl>(DE->getDecl());<br>
-        auto ASELValue = EmitLValue(ASE);<br>
-        auto OriginalBaseLValue = EmitLValue(DE);<br>
-        LValue BaseLValue = loadToBegin(<br>
-            *this, OrigVD->getType(), ASELValue.getType(), OriginalBaseLValue);<br>
-        // Store the address of the original variable associated with the LHS<br>
-        // implicit variable.<br>
-        PrivateScope.addPrivate(<br>
-            LHSVD, [ASELValue]() -> Address { return ASELValue.getAddress(); });<br>
-        // Emit reduction copy.<br>
-        bool IsRegistered = PrivateScope.addPrivate(<br>
-            OrigVD, [this, OrigVD, PrivateVD, BaseLValue, ASELValue,<br>
-                     OriginalBaseLValue, DRD, IRed]() -> Address {<br>
-              // Emit private VarDecl with reduction init.<br>
-              AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);<br>
-              auto Addr = Emission.getAllocatedAddress();<br>
-              if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {<br>
-                emitInitWithReductionInitializer(*this, DRD, *IRed, Addr,<br>
-                                                 ASELValue.getAddress(),<br>
-                                                 ASELValue.getType());<br>
-              } else<br>
-                EmitAutoVarInit(Emission);<br>
-              EmitAutoVarCleanups(Emission);<br>
-              auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),<br>
-                                                   ASELValue.getPointer());<br>
-              auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);<br>
-              return castToBase(*this, OrigVD->getType(), ASELValue.getType(),<br>
-                                OriginalBaseLValue, Ptr);<br>
-            });<br>
-        assert(IsRegistered && "private var already registered as private");<br>
-        // Silence the warning about unused variable.<br>
-        (void)IsRegistered;<br>
-        PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address {<br>
-          return Builder.CreateElementBitCast(<br>
-              GetAddrOfLocalVar(PrivateVD), ConvertTypeForMem(RHSVD->getType()),<br>
-              "rhs.begin");<br>
-        });<br>
-      } else {<br>
-        auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());<br>
-        QualType Type = PrivateVD->getType();<br>
-        if (getContext().getAsArrayType(Type)) {<br>
-          // Store the address of the original variable associated with the LHS<br>
-          // implicit variable.<br>
-          DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),<br>
-                          CapturedStmtInfo->lookup(OrigVD) != nullptr,<br>
-                          IRef->getType(), VK_LValue, IRef->getExprLoc());<br>
-          Address OriginalAddr = EmitLValue(&DRE).getAddress();<br>
-          PrivateScope.addPrivate(LHSVD, [this, &OriginalAddr,<br>
-                                          LHSVD]() -> Address {<br>
-            OriginalAddr = Builder.CreateElementBitCast(<br>
-                OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");<br>
-            return OriginalAddr;<br>
-          });<br>
-          bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {<br>
-            if (Type->isVariablyModifiedType()) {<br>
-              CodeGenFunction::OpaqueValueMapping OpaqueMap(<br>
-                  *this, cast<OpaqueValueExpr>(<br>
-                             getContext()<br>
-                                 .getAsVariableArrayType(PrivateVD->getType())<br>
-                                 ->getSizeExpr()),<br>
-                  RValue::get(<br>
-                      getTypeSize(OrigVD->getType().getNonReferenceType())));<br>
-              EmitVariablyModifiedType(Type);<br>
-            }<br>
-            auto Emission = EmitAutoVarAlloca(*PrivateVD);<br>
-            auto Addr = Emission.getAllocatedAddress();<br>
-            auto *Init = PrivateVD->getInit();<br>
-            EmitOMPAggregateInit(*this, Addr, PrivateVD->getType(),<br>
-                                 DRD ? *IRed : Init, OriginalAddr);<br>
-            EmitAutoVarCleanups(Emission);<br>
-            return Emission.getAllocatedAddress();<br>
-          });<br>
-          assert(IsRegistered && "private var already registered as private");<br>
-          // Silence the warning about unused variable.<br>
-          (void)IsRegistered;<br>
-          PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address {<br>
-            return Builder.CreateElementBitCast(<br>
-                GetAddrOfLocalVar(PrivateVD),<br>
-                ConvertTypeForMem(RHSVD->getType()), "rhs.begin");<br>
-          });<br>
-        } else {<br>
-          // Store the address of the original variable associated with the LHS<br>
-          // implicit variable.<br>
-          Address OriginalAddr = Address::invalid();<br>
-          PrivateScope.addPrivate(LHSVD, [this, OrigVD, IRef,<br>
-                                          &OriginalAddr]() -> Address {<br>
-            DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),<br>
-                            CapturedStmtInfo->lookup(OrigVD) != nullptr,<br>
-                            IRef->getType(), VK_LValue, IRef->getExprLoc());<br>
-            OriginalAddr = EmitLValue(&DRE).getAddress();<br>
-            return OriginalAddr;<br>
-          });<br>
-          // Emit reduction copy.<br>
-          bool IsRegistered = PrivateScope.addPrivate(<br>
-              OrigVD, [this, PrivateVD, OriginalAddr, DRD, IRed]() -> Address {<br>
-                // Emit private VarDecl with reduction init.<br>
-                AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);<br>
-                auto Addr = Emission.getAllocatedAddress();<br>
-                if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {<br>
-                  emitInitWithReductionInitializer(*this, DRD, *IRed, Addr,<br>
-                                                   OriginalAddr,<br>
-                                                   PrivateVD->getType());<br>
-                } else<br>
-                  EmitAutoVarInit(Emission);<br>
-                EmitAutoVarCleanups(Emission);<br>
-                return Addr;<br>
-              });<br>
-          assert(IsRegistered && "private var already registered as private");<br>
-          // Silence the warning about unused variable.<br>
-          (void)IsRegistered;<br>
-          PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {<br>
-            return GetAddrOfLocalVar(PrivateVD);<br>
-          });<br>
-        }<br>
+    auto ILHS = C->lhs_exprs().begin();<br>
+    auto IRHS = C->rhs_exprs().begin();<br>
+    for (const auto *Ref : C->varlists()) {<br>
+      Shareds.emplace_back(Ref);<br>
+      Privates.emplace_back(*IPriv);<br>
+      ReductionOps.emplace_back(*IRed);<br>
+      LHSs.emplace_back(*ILHS);<br>
+      RHSs.emplace_back(*IRHS);<br>
+      std::advance(IPriv, 1);<br>
+      std::advance(IRed, 1);<br>
+      std::advance(ILHS, 1);<br>
+      std::advance(IRHS, 1);<br>
+    }<br>
+  }<br>
+  ReductionCodeGen RedCG(Shareds, Privates, ReductionOps);<br>
+  unsigned Count = 0;<br>
+  auto ILHS = LHSs.begin();<br>
+  auto IRHS = RHSs.begin();<br>
+  auto IPriv = Privates.begin();<br>
+  for (const auto *IRef : Shareds) {<br>
+    auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());<br>
+    // Emit private VarDecl with reduction init.<br>
+    RedCG.emitSharedLValue(*this, Count);<br>
+    RedCG.emitAggregateType(*this, Count);<br>
+    auto Emission = EmitAutoVarAlloca(*PrivateVD);<br>
+    RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(),<br>
+                             RedCG.getSharedLValue(Count),<br>
+                             [&Emission](CodeGenFunction &CGF) {<br>
+                               CGF.EmitAutoVarInit(Emission);<br>
+                               return true;<br>
+                             });<br>
+    EmitAutoVarCleanups(Emission);<br>
+    Address BaseAddr = RedCG.adjustPrivateAddress(<br>
+        *this, Count, Emission.getAllocatedAddress());<br>
+    bool IsRegistered = PrivateScope.addPrivate(<br>
+        RedCG.getBaseDecl(Count), [BaseAddr]() -> Address { return BaseAddr; });<br>
+    assert(IsRegistered && "private var already registered as private");<br>
+    // Silence the warning about unused variable.<br>
+    (void)IsRegistered;<br>
+<br>
+    auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());<br>
+    auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());<br>
+    if (auto *OASE = dyn_cast<OMPArraySectionExpr>(IRef)) {<br>
+      // Store the address of the original variable associated with the LHS<br>
+      // implicit variable.<br>
+      PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() -> Address {<br>
+        return RedCG.getSharedLValue(Count).getAddress();<br>
+      });<br>
+      PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address {<br>
+        return GetAddrOfLocalVar(PrivateVD);<br>
+      });<br>
+    } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(IRef)) {<br>
+      // Store the address of the original variable associated with the LHS<br>
+      // implicit variable.<br>
+      PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() -> Address {<br>
+        return RedCG.getSharedLValue(Count).getAddress();<br>
+      });<br>
+      PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address {<br>
+        return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD),<br>
+                                            ConvertTypeForMem(RHSVD->getType()),<br>
+                                            "rhs.begin");<br>
+      });<br>
+    } else {<br>
+      QualType Type = PrivateVD->getType();<br>
+      bool IsArray = getContext().getAsArrayType(Type) != nullptr;<br>
+      Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress();<br>
+      // Store the address of the original variable associated with the LHS<br>
+      // implicit variable.<br>
+      if (IsArray) {<br>
+        OriginalAddr = Builder.CreateElementBitCast(<br>
+            OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");<br>
       }<br>
-      ++ILHS;<br>
-      ++IRHS;<br>
-      ++IPriv;<br>
-      ++IRed;<br>
+      PrivateScope.addPrivate(<br>
+          LHSVD, [OriginalAddr]() -> Address { return OriginalAddr; });<br>
+      PrivateScope.addPrivate(<br>
+          RHSVD, [this, PrivateVD, RHSVD, IsArray]() -> Address {<br>
+            return IsArray<br>
+                       ? Builder.CreateElementBitCast(<br>
+                             GetAddrOfLocalVar(PrivateVD),<br>
+                             ConvertTypeForMem(RHSVD->getType()), "rhs.begin")<br>
+                       : GetAddrOfLocalVar(PrivateVD);<br>
+          });<br>
     }<br>
+    ++ILHS;<br>
+    ++IRHS;<br>
+    ++IPriv;<br>
+    ++Count;<br>
   }<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/test/OpenMP/for_reduction_codegen.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_reduction_codegen.cpp?rev=307910&r1=307909&r2=307910&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_reduction_codegen.cpp?rev=307910&r1=307909&r2=307910&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/OpenMP/for_reduction_codegen.cpp (original)<br>
+++ cfe/trunk/test/OpenMP/for_reduction_codegen.cpp Thu Jul 13 06:36:14 2017<br>
@@ -718,7 +718,6 @@ int main() {<br>
 // CHECK: br i1 [[DONE]],<br>
<br>
 // Check initialization of private copy.<br>
-// CHECK: [[LHS_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* %{{.+}} to [[S_FLOAT_TY]]*<br>
 // CHECK: [[BEGIN:%.+]] = getelementptr inbounds [10 x [4 x [[S_FLOAT_TY]]]], [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]], i32 0, i32 0, i32 0<br>
 // CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[BEGIN]], i64 40<br>
 // CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[BEGIN]], [[END]]<br>
@@ -727,6 +726,7 @@ int main() {<br>
 // CHECK: call void @_ZN1SIfEC1Ev([[S_FLOAT_TY]]* %<br>
 // CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]<br>
 // CHECK: br i1 [[DONE]],<br>
+// CHECK: [[LHS_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* %{{.+}} to [[S_FLOAT_TY]]*<br>
 // CHECK: [[ARRS_PRIV_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]] to [[S_FLOAT_TY]]*<br>
<br>
 // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]<br>
@@ -903,8 +903,6 @@ int main() {<br>
 // CHECK: getelementptr inbounds [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %{{.+}}, i64 4<br>
 // CHECK: load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %<br>
 // CHECK: getelementptr inbounds [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 6<br>
-// CHECK: [[LD:%.+]] = load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],<br>
-// CHECK: [[ORIG_START:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[LD]],<br>
 // CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64<br>
 // CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]<br>
@@ -912,6 +910,8 @@ int main() {<br>
 // CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1<br>
 // CHECK: call i8* @llvm.stacksave()<br>
 // CHECK: [[VAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],<br>
+// CHECK: [[LD:%.+]] = load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],<br>
+// CHECK: [[ORIG_START:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[LD]],<br>
 // CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64<br>
 // CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]<br>
@@ -933,7 +933,6 @@ int main() {<br>
<br>
 // CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]], i64 0, i64 0<br>
 // CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]], i64 0, i64 4<br>
-// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64<br>
 // CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]<br>
@@ -941,6 +940,7 @@ int main() {<br>
 // CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1<br>
 // CHECK: call i8* @llvm.stacksave()<br>
 // CHECK: [[VVAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],<br>
+// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64<br>
 // CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]<br>
@@ -964,8 +964,6 @@ int main() {<br>
 // CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1<br>
 // CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
 // CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 2<br>
-// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
-// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64<br>
 // CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]<br>
@@ -973,6 +971,8 @@ int main() {<br>
 // CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1<br>
 // CHECK: call i8* @llvm.stacksave()<br>
 // CHECK: [[VAR3_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],<br>
+// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
+// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64<br>
 // CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]<br>
@@ -997,11 +997,11 @@ int main() {<br>
 // CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
 // CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]],<br>
 // CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
-// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], i32 0, i32 0<br>
 // CHECK: getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 2<br>
<br>
 // CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], [2 x [[S_FLOAT_TY]]]** %<br>
+// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
<br>
 // CHECK: ret void<br>
<br>
<br>
Modified: cfe/trunk/test/OpenMP/for_reduction_codegen_UDR.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_reduction_codegen_UDR.cpp?rev=307910&r1=307909&r2=307910&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_reduction_codegen_UDR.cpp?rev=307910&r1=307909&r2=307910&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/OpenMP/for_reduction_codegen_UDR.cpp (original)<br>
+++ cfe/trunk/test/OpenMP/for_reduction_codegen_UDR.cpp Thu Jul 13 06:36:14 2017<br>
@@ -522,8 +522,8 @@ int main() {<br>
 // CHECK: br i1 [[DONE]],<br>
<br>
 // Check initialization of private copy.<br>
-// CHECK: [[LHS_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* %{{.+}} to [[S_FLOAT_TY]]*<br>
 // CHECK: [[BEGIN:%.+]] = getelementptr inbounds [10 x [4 x [[S_FLOAT_TY]]]], [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]], i32 0, i32 0, i32 0<br>
+// CHECK: [[LHS_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* %{{.+}} to [[S_FLOAT_TY]]*<br>
 // CHECK: [[END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[BEGIN]], i64 40<br>
 // CHECK: [[ISEMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[BEGIN]], [[END]]<br>
 // CHECK: br i1 [[ISEMPTY]],<br>
@@ -531,6 +531,7 @@ int main() {<br>
 // CHECK: call void @_Z4initR6BaseS1RKS_(%<br>
 // CHECK: [[DONE:%.+]] = icmp eq [[S_FLOAT_TY]]* %{{.+}}, [[END]]<br>
 // CHECK: br i1 [[DONE]],<br>
+// CHECK: [[LHS_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* %{{.+}} to [[S_FLOAT_TY]]*<br>
 // CHECK: [[ARRS_PRIV_BEGIN:%.+]] = bitcast [10 x [4 x [[S_FLOAT_TY]]]]* [[ARRS_PRIV]] to [[S_FLOAT_TY]]*<br>
<br>
 // CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]<br>
@@ -703,8 +704,6 @@ int main() {<br>
 // CHECK: getelementptr inbounds [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %{{.+}}, i64 4<br>
 // CHECK: load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** %<br>
 // CHECK: getelementptr inbounds [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 6<br>
-// CHECK: [[LD:%.+]] = load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],<br>
-// CHECK: [[ORIG_START:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[LD]],<br>
 // CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64<br>
 // CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]<br>
@@ -712,6 +711,8 @@ int main() {<br>
 // CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1<br>
 // CHECK: call i8* @llvm.stacksave()<br>
 // CHECK: [[VAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],<br>
+// CHECK: [[LD:%.+]] = load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]],<br>
+// CHECK: [[ORIG_START:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[LD]],<br>
 // CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64<br>
 // CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]<br>
@@ -733,7 +734,6 @@ int main() {<br>
<br>
 // CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]], i64 0, i64 0<br>
 // CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]], i64 0, i64 4<br>
-// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64<br>
 // CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]<br>
@@ -741,6 +741,7 @@ int main() {<br>
 // CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1<br>
 // CHECK: call i8* @llvm.stacksave()<br>
 // CHECK: [[VVAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],<br>
+// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VVAR2_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64<br>
 // CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]<br>
@@ -764,8 +765,6 @@ int main() {<br>
 // CHECK: [[LOW:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 1<br>
 // CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
 // CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], i64 0, i64 2<br>
-// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
-// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[LAST:%.+]] = ptrtoint [[S_FLOAT_TY]]* %{{.+}} to i64<br>
 // CHECK: [[FIRST:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[BYTE_DIF:%.+]] = sub i64 [[LAST]], [[FIRST]]<br>
@@ -773,6 +772,8 @@ int main() {<br>
 // CHECK: [[SIZE:%.+]] = add nuw i64 [[DIF]], 1<br>
 // CHECK: call i8* @llvm.stacksave()<br>
 // CHECK: [[VAR3_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]],<br>
+// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
+// CHECK: [[ORIG_START:%.+]] = bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: [[START:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[ORIG_START]] to i64<br>
 // CHECK: [[LOW_BOUND:%.+]] = ptrtoint [[S_FLOAT_TY]]* [[LOW]] to i64<br>
 // CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]]<br>
@@ -797,8 +798,8 @@ int main() {<br>
 // CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
 // CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]],<br>
 // CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]],<br>
-// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], i32 0, i32 0<br>
+// CHECK: bitcast [2 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]] to [[S_FLOAT_TY]]*<br>
 // CHECK: getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* %{{.+}}, i64 2<br>
<br>
 // CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], [2 x [[S_FLOAT_TY]]]** %<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>