r307910 - [OPENMP] Generalization of codegen for reduction clauses.

Eric Christopher via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 13 18:44:11 PDT 2017


This had some dead variables where you should have used isa rather than
dyn_cast. I've fixed them in r307988

Also for some post commit review this is a ton of mostly uncommented code.

-eric

On Thu, Jul 13, 2017 at 6:36 AM Alexey Bataev via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

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


More information about the cfe-commits mailing list