r259776 - [OPENMP 4.0] Fixed support of array sections/array subscripts.

Alexey Bataev via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 17 04:22:21 PDT 2016


Yes, of course

Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team

17.03.2016 14:18, Hahnfeld, Jonas пишет:
> Hi Alexey,
>
> I think this now also affects the released version of Clang 3.8.0.
> Can this be merged for 3.8.1 if such a version will exist somewhen?
>
> Thanks,
> Jonas
>
>> -----Original Message-----
>> From: cfe-commits [mailto:cfe-commits-bounces at lists.llvm.org] On Behalf
>> Of Alexey Bataev via cfe-commits
>> Sent: Thursday, February 04, 2016 12:27 PM
>> To: cfe-commits at lists.llvm.org
>> Subject: r259776 - [OPENMP 4.0] Fixed support of array sections/array
>> subscripts.
>>
>> Author: abataev
>> Date: Thu Feb  4 05:27:03 2016
>> New Revision: 259776
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=259776&view=rev
>> Log:
>> [OPENMP 4.0] Fixed support of array sections/array subscripts.
>> Codegen for array sections/array subscripts worked only for expressions with
>> arrays as base. Patch fixes codegen for bases with pointer/reference types.
>>
>> Modified:
>>      cfe/trunk/include/clang/AST/ExprOpenMP.h
>>      cfe/trunk/lib/AST/Expr.cpp
>>      cfe/trunk/lib/CodeGen/CGExpr.cpp
>>      cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
>>      cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
>>      cfe/trunk/lib/CodeGen/CodeGenFunction.h
>>      cfe/trunk/lib/Sema/SemaExpr.cpp
>>      cfe/trunk/lib/Sema/SemaOpenMP.cpp
>>      cfe/trunk/test/OpenMP/for_reduction_codegen.cpp
>>      cfe/trunk/test/OpenMP/task_codegen.cpp
>>
>> Modified: cfe/trunk/include/clang/AST/ExprOpenMP.h
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/include/clang/AST/ExprOpenMP.h?rev=259776&r1=25977
>> 5&r2=259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/include/clang/AST/ExprOpenMP.h (original)
>> +++ cfe/trunk/include/clang/AST/ExprOpenMP.h Thu Feb  4 05:27:03 2016
>> @@ -85,7 +85,7 @@ public:
>>     void setBase(Expr *E) { SubExprs[BASE] = E; }
>>
>>     /// \brief Return original type of the base expression for array section.
>> -  static QualType getBaseOriginalType(Expr *Base);
>> +  static QualType getBaseOriginalType(const Expr *Base);
>>
>>     /// \brief Get lower bound of array section.
>>     Expr *getLowerBound() { return
>> cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
>>
>> Modified: cfe/trunk/lib/AST/Expr.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/AST/Expr.cpp?rev=259776&r1=259775&r2=259776&vie
>> w=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/AST/Expr.cpp (original)
>> +++ cfe/trunk/lib/AST/Expr.cpp Thu Feb  4 05:27:03 2016
>> @@ -4026,16 +4026,18 @@ unsigned AtomicExpr::getNumSubExprs(Atom
>>     llvm_unreachable("unknown atomic op");  }
>>
>> -QualType OMPArraySectionExpr::getBaseOriginalType(Expr *Base) {
>> +QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {
>>     unsigned ArraySectionCount = 0;
>>     while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base-
>>> IgnoreParens())) {
>>       Base = OASE->getBase();
>>       ++ArraySectionCount;
>>     }
>> -  while (auto *ASE = dyn_cast<ArraySubscriptExpr>(Base->IgnoreParens()))
>> {
>> +  while (auto *ASE =
>> +             dyn_cast<ArraySubscriptExpr>(Base->IgnoreParenImpCasts()))
>> + {
>>       Base = ASE->getBase();
>>       ++ArraySectionCount;
>>     }
>> +  Base = Base->IgnoreParenImpCasts();
>>     auto OriginalTy = Base->getType();
>>     if (auto *DRE = dyn_cast<DeclRefExpr>(Base))
>>       if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
>>
>> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=259776&r1=259775&r2=259
>> 776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Feb  4 05:27:03 2016
>> @@ -1949,6 +1949,21 @@ LValue CodeGenFunction::EmitLoadOfRefere
>>     return MakeAddrLValue(Addr, RefTy->getPointeeType(), Source);  }
>>
>> +Address CodeGenFunction::EmitLoadOfPointer(Address Ptr,
>> +                                           const PointerType *PtrTy,
>> +                                           AlignmentSource *Source) {
>> +  llvm::Value *Addr = Builder.CreateLoad(Ptr);
>> +  return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(),
>> Source,
>> +
>> +/*forPointeeType=*/true)); }
>> +
>> +LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr,
>> +                                                const PointerType
>> +*PtrTy) {
>> +  AlignmentSource Source;
>> +  Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &Source);
>> +  return MakeAddrLValue(Addr, PtrTy->getPointeeType(), Source); }
>> +
>>   static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
>>                                         const Expr *E, const VarDecl *VD) {
>>     QualType T = E->getType();
>> @@ -2934,21 +2949,54 @@ LValue CodeGenFunction::EmitArraySubscri
>>     return LV;
>>   }
>>
>> +static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const
>> Expr *Base,
>> +                                       AlignmentSource &AlignSource,
>> +                                       QualType BaseTy, QualType ElTy,
>> +                                       bool IsLowerBound) {
>> +  LValue BaseLVal;
>> +  if (auto *ASE = dyn_cast<OMPArraySectionExpr>(Base-
>>> IgnoreParenImpCasts())) {
>> +    BaseLVal = CGF.EmitOMPArraySectionExpr(ASE, IsLowerBound);
>> +    if (BaseTy->isArrayType()) {
>> +      Address Addr = BaseLVal.getAddress();
>> +      AlignSource = BaseLVal.getAlignmentSource();
>> +
>> +      // If the array type was an incomplete type, we need to make sure
>> +      // the decay ends up being the right type.
>> +      llvm::Type *NewTy = CGF.ConvertType(BaseTy);
>> +      Addr = CGF.Builder.CreateElementBitCast(Addr, NewTy);
>> +
>> +      // Note that VLA pointers are always decayed, so we don't need to do
>> +      // anything here.
>> +      if (!BaseTy->isVariableArrayType()) {
>> +        assert(isa<llvm::ArrayType>(Addr.getElementType()) &&
>> +               "Expected pointer to array");
>> +        Addr = CGF.Builder.CreateStructGEP(Addr, 0, CharUnits::Zero(),
>> +                                           "arraydecay");
>> +      }
>> +
>> +      return CGF.Builder.CreateElementBitCast(Addr,
>> +                                              CGF.ConvertTypeForMem(ElTy));
>> +    }
>> +    CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &AlignSource);
>> +    return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()),
>> +Align);
>> +  }
>> +  return CGF.EmitPointerWithAlignment(Base, &AlignSource); }
>> +
>>   LValue CodeGenFunction::EmitOMPArraySectionExpr(const
>> OMPArraySectionExpr *E,
>>                                                   bool IsLowerBound) {
>> -  LValue Base;
>> +  QualType BaseTy;
>>     if (auto *ASE =
>>             dyn_cast<OMPArraySectionExpr>(E->getBase()-
>>> IgnoreParenImpCasts()))
>> -    Base = EmitOMPArraySectionExpr(ASE, IsLowerBound);
>> +    BaseTy = OMPArraySectionExpr::getBaseOriginalType(ASE);
>>     else
>> -    Base = EmitLValue(E->getBase());
>> -  QualType BaseTy = Base.getType();
>> -  llvm::Value *Idx = nullptr;
>> +    BaseTy = E->getBase()->getType();
>>     QualType ResultExprTy;
>>     if (auto *AT = getContext().getAsArrayType(BaseTy))
>>       ResultExprTy = AT->getElementType();
>>     else
>>       ResultExprTy = BaseTy->getPointeeType();
>> +  llvm::Value *Idx = nullptr;
>>     if (IsLowerBound || (!IsLowerBound && E->getColonLoc().isInvalid())) {
>>       // Requesting lower bound or upper bound, but without provided length
>> and
>>       // without ':' symbol for the default length -> length = 1.
>> @@ -2960,9 +3008,9 @@ LValue CodeGenFunction::EmitOMPArraySect
>>       } else
>>         Idx = llvm::ConstantInt::getNullValue(IntPtrTy);
>>     } else {
>> -    // Try to emit length or lower bound as constant. If this is possible,
>> 1 is
>> -    // subtracted from constant length or lower bound. Otherwise, emit LLVM
>> IR
>> -    // (LB + Len) - 1.
>> +    // Try to emit length or lower bound as constant. If this is possible,
>> 1
>> +    // is subtracted from constant length or lower bound. Otherwise, emit
>> LLVM
>> +    // IR (LB + Len) - 1.
>>       auto &C = CGM.getContext();
>>       auto *Length = E->getLength();
>>       llvm::APSInt ConstLength;
>> @@ -3008,12 +3056,15 @@ LValue CodeGenFunction::EmitOMPArraySect
>>           Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength +
>> ConstLowerBound);
>>       } else {
>>         // Idx = ArraySize - 1;
>> -      if (auto *VAT = C.getAsVariableArrayType(BaseTy)) {
>> +      QualType ArrayTy = BaseTy->isPointerType()
>> +                             ?
>> E->getBase()->IgnoreParenImpCasts()->getType()
>> +                             : BaseTy;
>> +      if (auto *VAT = C.getAsVariableArrayType(ArrayTy)) {
>>           Length = VAT->getSizeExpr();
>>           if (Length->isIntegerConstantExpr(ConstLength, C))
>>             Length = nullptr;
>>         } else {
>> -        auto *CAT = C.getAsConstantArrayType(BaseTy);
>> +        auto *CAT = C.getAsConstantArrayType(ArrayTy);
>>           ConstLength = CAT->getSize();
>>         }
>>         if (Length) {
>> @@ -3032,52 +3083,56 @@ LValue CodeGenFunction::EmitOMPArraySect
>>     }
>>     assert(Idx);
>>
>> -  llvm::Value *EltPtr;
>> -  QualType FixedSizeEltType = ResultExprTy;
>> +  Address EltPtr = Address::invalid();
>> +  AlignmentSource AlignSource;
>>     if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) {
>> +    // The base must be a pointer, which is not an aggregate.  Emit
>> +    // it.  It needs to be emitted first in case it's what captures
>> +    // the VLA bounds.
>> +    Address Base =
>> +        emitOMPArraySectionBase(*this, E->getBase(), AlignSource, BaseTy,
>> +                                VLA->getElementType(), IsLowerBound);
>>       // The element count here is the total number of non-VLA elements.
>> -    llvm::Value *numElements = getVLASize(VLA).first;
>> -    FixedSizeEltType = getFixedSizeElementType(getContext(), VLA);
>> +    llvm::Value *NumElements = getVLASize(VLA).first;
>>
>>       // Effectively, the multiply by the VLA size is part of the GEP.
>>       // GEP indexes are signed, and scaling an index isn't permitted to
>>       // signed-overflow, so we use the same semantics for our explicit
>>       // multiply.  We suppress this if overflow is not undefined behavior.
>> -    if (getLangOpts().isSignedOverflowDefined()) {
>> -      Idx = Builder.CreateMul(Idx, numElements);
>> -      EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
>> -    } else {
>> -      Idx = Builder.CreateNSWMul(Idx, numElements);
>> -      EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx,
>> "arrayidx");
>> -    }
>> -  } else if (BaseTy->isConstantArrayType()) {
>> -    llvm::Value *ArrayPtr = Base.getPointer();
>> -    llvm::Value *Zero = llvm::ConstantInt::getNullValue(IntPtrTy);
>> -    llvm::Value *Args[] = {Zero, Idx};
>> -
>>       if (getLangOpts().isSignedOverflowDefined())
>> -      EltPtr = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
>> +      Idx = Builder.CreateMul(Idx, NumElements);
>>       else
>> -      EltPtr = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
>> -  } else {
>> -    // The base must be a pointer, which is not an aggregate.  Emit it.
>> -    if (getLangOpts().isSignedOverflowDefined())
>> -      EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
>> +      Idx = Builder.CreateNSWMul(Idx, NumElements);
>> +    EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(),
>> +
>> + !getLangOpts().isSignedOverflowDefined());
>> +  } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) {
>> +    // If this is A[i] where A is an array, the frontend will have decayed
>> the
>> +    // base to be a ArrayToPointerDecay implicit cast.  While correct, it
>> is
>> +    // inefficient at -O0 to emit a "gep A, 0, 0" when codegen'ing it, then
>> a
>> +    // "gep x, i" here.  Emit one "gep A, 0, i".
>> +    assert(Array->getType()->isArrayType() &&
>> +           "Array to pointer decay must have array source type!");
>> +    LValue ArrayLV;
>> +    // For simple multidimensional array indexing, set the 'accessed' flag
>> for
>> +    // better bounds-checking of the base expression.
>> +    if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Array))
>> +      ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true);
>>       else
>> -      EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx,
>> "arrayidx");
>> -  }
>> -
>> -  CharUnits EltAlign =
>> -    Base.getAlignment().alignmentOfArrayElement(
>> -
>> getContext().getTypeSizeInChars(FixedSizeEltType));
>> -
>> -  // Limit the alignment to that of the result type.
>> -  LValue LV = MakeAddrLValue(Address(EltPtr, EltAlign), ResultExprTy,
>> -                             Base.getAlignmentSource());
>> +      ArrayLV = EmitLValue(Array);
>>
>> -  LV.getQuals().setAddressSpace(BaseTy.getAddressSpace());
>> +    // Propagate the alignment from the array itself to the result.
>> +    EltPtr = emitArraySubscriptGEP(
>> +        *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
>> +        ResultExprTy, !getLangOpts().isSignedOverflowDefined());
>> +    AlignSource = ArrayLV.getAlignmentSource();  } else {
>> +    Address Base = emitOMPArraySectionBase(*this, E->getBase(),
>> AlignSource,
>> +                                           BaseTy, ResultExprTy,
>> IsLowerBound);
>> +    EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
>> +
>> + !getLangOpts().isSignedOverflowDefined());
>> +  }
>>
>> -  return LV;
>> +  return MakeAddrLValue(EltPtr, ResultExprTy, AlignSource);
>>   }
>>
>>   LValue CodeGenFunction::
>>
>> Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=259776&r1=25
>> 9775&r2=259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Thu Feb  4 05:27:03
>> 2016
>> @@ -272,18 +272,10 @@ public:
>>
>>   } // anonymous namespace
>>
>> -static LValue emitLoadOfPointerLValue(CodeGenFunction &CGF, Address
>> PtrAddr,
>> -                                      QualType Ty) {
>> -  AlignmentSource Source;
>> -  CharUnits Align = CGF.getNaturalPointeeTypeAlignment(Ty, &Source);
>> -  return CGF.MakeAddrLValue(Address(CGF.Builder.CreateLoad(PtrAddr),
>> Align),
>> -                            Ty->getPointeeType(), Source);
>> -}
>> -
>>   LValue
>> CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction
>> &CGF) {
>> -  return emitLoadOfPointerLValue(CGF,
>> -
>> CGF.GetAddrOfLocalVar(getThreadIDVariable()),
>> -                                 getThreadIDVariable()->getType());
>> +  return CGF.EmitLoadOfPointerLValue(
>> +      CGF.GetAddrOfLocalVar(getThreadIDVariable()),
>> +      getThreadIDVariable()->getType()->castAs<PointerType>());
>>   }
>>
>>   void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt
>> * /*S*/) { @@ -2567,8 +2559,9 @@
>> emitProxyTaskFunction(CodeGenModule &CGM
>>     // tt->task_data.shareds);
>>     auto *GtidParam = CGF.EmitLoadOfScalar(
>>         CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty,
>> Loc);
>> -  LValue TDBase = emitLoadOfPointerLValue(
>> -      CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg),
>> KmpTaskTWithPrivatesPtrQTy);
>> +  LValue TDBase = CGF.EmitLoadOfPointerLValue(
>> +      CGF.GetAddrOfLocalVar(&TaskTypeArg),
>> +      KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
>>     auto *KmpTaskTWithPrivatesQTyRD =
>>         cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
>>     LValue Base =
>> @@ -2632,8 +2625,9 @@ static llvm::Value *emitDestructorsFunct
>>     CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn,
>> DestructorFnInfo,
>>                       Args);
>>
>> -  LValue Base = emitLoadOfPointerLValue(
>> -      CGF, CGF.GetAddrOfLocalVar(&TaskTypeArg),
>> KmpTaskTWithPrivatesPtrQTy);
>> +  LValue Base = CGF.EmitLoadOfPointerLValue(
>> +      CGF.GetAddrOfLocalVar(&TaskTypeArg),
>> +      KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
>>     auto *KmpTaskTWithPrivatesQTyRD =
>>         cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
>>     auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
>> @@ -2711,16 +2705,17 @@ emitTaskPrivateMappingFunction(CodeGenMo
>>                       TaskPrivatesMapFnInfo, Args);
>>
>>     // *privi = &.privates.privi;
>> -  LValue Base = emitLoadOfPointerLValue(
>> -      CGF, CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
>> TaskPrivatesArg.getType());
>> +  LValue Base = CGF.EmitLoadOfPointerLValue(
>> +      CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
>> +      TaskPrivatesArg.getType()->castAs<PointerType>());
>>     auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
>>     Counter = 0;
>>     for (auto *Field : PrivatesQTyRD->fields()) {
>>       auto FieldLVal = CGF.EmitLValueForField(Base, Field);
>>       auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
>>       auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD-
>>> getType());
>> -    auto RefLoadLVal =
>> -        emitLoadOfPointerLValue(CGF, RefLVal.getAddress(),
>> RefLVal.getType());
>> +    auto RefLoadLVal = CGF.EmitLoadOfPointerLValue(
>> +        RefLVal.getAddress(),
>> + RefLVal.getType()->castAs<PointerType>());
>>       CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
>>       ++Counter;
>>     }
>>
>> Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=259776&r1=25977
>> 5&r2=259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Thu Feb  4 05:27:03 2016
>> @@ -672,6 +672,54 @@ void CodeGenFunction::EmitOMPLastprivate
>>     }
>>   }
>>
>> +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.getAlignmentSource()); }
>> +
>>   void CodeGenFunction::EmitOMPReductionClauseInit(
>>       const OMPExecutableDirective &D,
>>       CodeGenFunction::OMPPrivateScope &PrivateScope) { @@ -697,21 +745,9
>> @@ void CodeGenFunction::EmitOMPReductionCl
>>           auto OASELValueUB =
>>               EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
>>           auto OriginalBaseLValue = EmitLValue(DE);
>> -        auto BaseLValue = OriginalBaseLValue;
>> -        auto *Zero = Builder.getInt64(/*C=*/0);
>> -        llvm::SmallVector<llvm::Value *, 4> Indexes;
>> -        Indexes.push_back(Zero);
>> -        auto *ItemTy =
>> -            OASELValueLB.getPointer()->getType()->getPointerElementType();
>> -        auto *Ty = BaseLValue.getPointer()->getType()-
>>> getPointerElementType();
>> -        while (Ty != ItemTy) {
>> -          Indexes.push_back(Zero);
>> -          Ty = Ty->getPointerElementType();
>> -        }
>> -        BaseLValue = MakeAddrLValue(
>> -            Address(Builder.CreateInBoundsGEP(BaseLValue.getPointer(),
>> Indexes),
>> -                    OASELValueLB.getAlignment()),
>> -            OASELValueLB.getType(), OASELValueLB.getAlignmentSource());
>> +        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, [this, OASELValueLB]() -> Address {
>> @@ -719,8 +755,8 @@ void CodeGenFunction::EmitOMPReductionCl
>>           });
>>           // Emit reduction copy.
>>           bool IsRegistered = PrivateScope.addPrivate(
>> -            OrigVD, [this, PrivateVD, BaseLValue, OASELValueLB,
>> OASELValueUB,
>> -                     OriginalBaseLValue]() -> Address {
>> +            OrigVD, [this, OrigVD, PrivateVD, BaseLValue, OASELValueLB,
>> +                     OASELValueUB, OriginalBaseLValue]() -> Address {
>>                 // Emit VarDecl with copy init for arrays.
>>                 // Get the address of the original variable captured in
>> current
>>                 // captured region.
>> @@ -744,9 +780,9 @@ void CodeGenFunction::EmitOMPReductionCl
>>                 auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
>>
>> OASELValueLB.getPointer());
>>                 auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
>> -              Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(
>> -                  Ptr, OriginalBaseLValue.getPointer()->getType());
>> -              return Address(Ptr, OriginalBaseLValue.getAlignment());
>> +              return castToBase(*this, OrigVD->getType(),
>> +                                OASELValueLB.getType(), OriginalBaseLValue,
>> +                                Ptr);
>>               });
>>           assert(IsRegistered && "private var already registered as
>> private");
>>           // Silence the warning about unused variable.
>> @@ -762,21 +798,8 @@ void CodeGenFunction::EmitOMPReductionCl
>>           auto *OrigVD = cast<VarDecl>(DE->getDecl());
>>           auto ASELValue = EmitLValue(ASE);
>>           auto OriginalBaseLValue = EmitLValue(DE);
>> -        auto BaseLValue = OriginalBaseLValue;
>> -        auto *Zero = Builder.getInt64(/*C=*/0);
>> -        llvm::SmallVector<llvm::Value *, 4> Indexes;
>> -        Indexes.push_back(Zero);
>> -        auto *ItemTy =
>> -            ASELValue.getPointer()->getType()->getPointerElementType();
>> -        auto *Ty = BaseLValue.getPointer()->getType()-
>>> getPointerElementType();
>> -        while (Ty != ItemTy) {
>> -          Indexes.push_back(Zero);
>> -          Ty = Ty->getPointerElementType();
>> -        }
>> -        BaseLValue = MakeAddrLValue(
>> -            Address(Builder.CreateInBoundsGEP(BaseLValue.getPointer(),
>> Indexes),
>> -                    ASELValue.getAlignment()),
>> -            ASELValue.getType(), ASELValue.getAlignmentSource());
>> +        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, [this, ASELValue]() -> Address {
>> @@ -
>> 784,7 +807,7 @@ void CodeGenFunction::EmitOMPReductionCl
>>           });
>>           // Emit reduction copy.
>>           bool IsRegistered = PrivateScope.addPrivate(
>> -            OrigVD, [this, PrivateVD, BaseLValue, ASELValue,
>> +            OrigVD, [this, OrigVD, PrivateVD, BaseLValue, ASELValue,
>>                        OriginalBaseLValue]() -> Address {
>>                 // Emit private VarDecl with reduction init.
>>                 EmitDecl(*PrivateVD);
>> @@ -792,9 +815,8 @@ void CodeGenFunction::EmitOMPReductionCl
>>                 auto *Offset = Builder.CreatePtrDiff(BaseLValue.getPointer(),
>>                                                      ASELValue.getPointer());
>>                 auto *Ptr = Builder.CreateGEP(Addr.getPointer(), Offset);
>> -              Ptr = Builder.CreatePointerBitCastOrAddrSpaceCast(
>> -                  Ptr, OriginalBaseLValue.getPointer()->getType());
>> -              return Address(Ptr, OriginalBaseLValue.getAlignment());
>> +              return castToBase(*this, OrigVD->getType(),
>> ASELValue.getType(),
>> +                                OriginalBaseLValue, Ptr);
>>               });
>>           assert(IsRegistered && "private var already registered as
>> private");
>>           // Silence the warning about unused variable.
>>
>> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=259776&r1=259775
>> &r2=259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
>> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Feb  4 05:27:03 2016
>> @@ -1574,6 +1574,10 @@ public:
>>                                 AlignmentSource *Source = nullptr);
>>     LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType
>> *RefTy);
>>
>> +  Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy,
>> +                            AlignmentSource *Source = nullptr);  LValue
>> + EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy);
>> +
>>     /// CreateTempAlloca - This creates a alloca and inserts it into the
>> entry
>>     /// block. The caller is responsible for setting an appropriate alignment
>> on
>>     /// the alloca.
>>
>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=259776&r1=259775&r2=2597
>> 76&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Feb  4 05:27:03 2016
>> @@ -4148,12 +4148,18 @@ ExprResult Sema::ActOnOMPArraySectionExp
>>       ExprResult Result = CheckPlaceholderExpr(LowerBound);
>>       if (Result.isInvalid())
>>         return ExprError();
>> +    Result = DefaultLvalueConversion(Result.get());
>> +    if (Result.isInvalid())
>> +      return ExprError();
>>       LowerBound = Result.get();
>>     }
>>     if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
>>       ExprResult Result = CheckPlaceholderExpr(Length);
>>       if (Result.isInvalid())
>>         return ExprError();
>> +    Result = DefaultLvalueConversion(Result.get());
>> +    if (Result.isInvalid())
>> +      return ExprError();
>>       Length = Result.get();
>>     }
>>
>> @@ -4260,6 +4266,13 @@ ExprResult Sema::ActOnOMPArraySectionExp
>>       return ExprError();
>>     }
>>
>> +  if (!Base->getType()->isSpecificPlaceholderType(
>> +          BuiltinType::OMPArraySection)) {
>> +    ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
>> +    if (Result.isInvalid())
>> +      return ExprError();
>> +    Base = Result.get();
>> +  }
>>     return new (Context)
>>         OMPArraySectionExpr(Base, LowerBound, Length,
>> Context.OMPArraySectionTy,
>>                             VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
>>
>> Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=259776&r1=259775&r2=
>> 259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Thu Feb  4 05:27:03 2016
>> @@ -7745,9 +7745,9 @@ OMPClause *Sema::ActOnOpenMPReductionCla
>>       if (DE) {
>>         auto D = DE->getDecl();
>>         VD = cast<VarDecl>(D);
>> -      Type = Context.getBaseElementType(VD->getType());
>> +      Type =
>> + Context.getBaseElementType(VD->getType().getNonReferenceType());
>>       } else if (ASE) {
>> -      Type = ASE->getType();
>> +      Type = ASE->getType().getNonReferenceType();
>>         auto *Base = ASE->getBase()->IgnoreParenImpCasts();
>>         while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
>>           Base = TempASE->getBase()->IgnoreParenImpCasts();
>> @@ -7765,6 +7765,7 @@ OMPClause *Sema::ActOnOpenMPReductionCla
>>           Type = ATy->getElementType();
>>         else
>>           Type = BaseType->getPointeeType();
>> +      Type = Type.getNonReferenceType();
>>         auto *Base = OASE->getBase()->IgnoreParenImpCasts();
>>         while (auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
>>           Base = TempOASE->getBase()->IgnoreParenImpCasts();
>> @@ -7806,7 +7807,7 @@ OMPClause *Sema::ActOnOpenMPReductionCla
>>       //  for all threads of the team.
>>       if (!ASE && !OASE) {
>>         VarDecl *VDDef = VD->getDefinition();
>> -      if (Type->isReferenceType() && VDDef) {
>> +      if (VD->getType()->isReferenceType() && VDDef) {
>>           DSARefChecker Check(DSAStack);
>>           if (Check.Visit(VDDef->getInit())) {
>>             Diag(ELoc, diag::err_omp_reduction_ref_type_arg) << ERange; @@ -
>> 8737,8 +8738,12 @@ Sema::ActOnOpenMPDependClause(OpenMPDepe
>>           auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
>>           if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
>>               (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl()))
>> ||
>> -            (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
>> -             !ASE->getBase()->getType()->isArrayType())) {
>> +            (ASE &&
>> +             !ASE->getBase()
>> +                  ->getType()
>> +                  .getNonReferenceType()
>> +                  ->isPointerType() &&
>> +
>> + !ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
>>             Diag(ELoc,
>> diag::err_omp_expected_var_name_member_expr_or_array_item)
>>                 << 0 << RefExpr->getSourceRange();
>>             continue;
>>
>> 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=259776&r
>> 1=259775&r2=259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/test/OpenMP/for_reduction_codegen.cpp (original)
>> +++ cfe/trunk/test/OpenMP/for_reduction_codegen.cpp Thu Feb  4
>> 05:27:03
>> +++ 2016
>> @@ -52,6 +52,8 @@ T tmain() {
>>     return T();
>>   }
>>
>> +extern S<float> **foo();
>> +
>>   int main() {
>>   #ifdef LAMBDA
>>     // LAMBDA: [[G:@.+]] = global double
>> @@ -182,6 +184,9 @@ int main() {
>>     S<float> s_arr[] = {1, 2};
>>     S<float> &var = test;
>>     S<float> var1, arrs[10][4];
>> +  S<float> **var2 = foo();
>> +  S<float> vvar2[2];
>> +  S<float> (&var3)[2] = s_arr;
>>   #pragma omp parallel
>>   #pragma omp for reduction(+:t_var) reduction(&:var) reduction(&& : var1)
>> reduction(min: t_var1)
>>     for (int i = 0; i < 2; ++i) {
>> @@ -196,6 +201,22 @@ int main() {
>>   #pragma omp for reduction(+:arr) reduction(&:arrs)
>>     for (int i = 0; i < 10; ++i)
>>       ++arr[1][i];
>> +#pragma omp parallel
>> +#pragma omp for reduction(& : var2[0 : 5][1 : 6])
>> +  for (int i = 0; i < 10; ++i)
>> +    ;
>> +#pragma omp parallel
>> +#pragma omp for reduction(& : vvar2[0 : 5])
>> +  for (int i = 0; i < 10; ++i)
>> +    ;
>> +#pragma omp parallel
>> +#pragma omp for reduction(& : var3[1 : 2])
>> +  for (int i = 0; i < 10; ++i)
>> +    ;
>> +#pragma omp parallel
>> +#pragma omp for reduction(& : var3)
>> +  for (int i = 0; i < 10; ++i)
>> +    ;
>>     return tmain<int>();
>>   #endif
>>   }
>> @@ -206,6 +227,10 @@ int main() {
>>   // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*,
>> i{{[0-9]+}}*, ...)*,
>> ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 6, void (i{{[0-9]+}}*,
>> i{{[0-
>> 9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, float*,
>> [[S_FLOAT_TY]]*,
>> [[S_FLOAT_TY]]*, float*, [2 x i32]*, [2 x [[S_FLOAT_TY]]]*)*
>> [[MAIN_MICROTASK:@.+]] to void  // CHECK: call void (%{{.+}}*, i{{[0-9]+}},
>> void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}*
>> @{{.+}},
>> i{{[0-9]+}} 5, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void
>> (i{{[0-9]+}}*,
>> i{{[0-9]+}}*, i64, i64, i32*, [2 x i32]*, [10 x [4 x [[S_FLOAT_TY]]]]*)*
>> [[MAIN_MICROTASK1:@.+]] to void  // CHECK: call void (%{{.+}}*, i{{[0-9]+}},
>> void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}*
>> @{{.+}},
>> i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void
>> (i{{[0-9]+}}*,
>> i{{[0-9]+}}*, i64, i64, i32*, [10 x [4 x [[S_FLOAT_TY]]]]*)*
>> [[MAIN_MICROTASK2:@.+]] to void
>> +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*,
>> +i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}},
>> +i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void
>> +(i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)*
>> +[[MAIN_MICROTASK3:@.+]] to void // CHECK: call void (%{{.+}}*,
>> +i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...)
>> + at __kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*,
>> +i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x
>> +[[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK4:@.+]] to void // CHECK: call void
>> +(%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...)
>> + at __kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*,
>> +i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x
>> +[[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK5:@.+]] to void // CHECK: call void
>> +(%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...)
>> + at __kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*,
>> +i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [2 x
>> +[[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK6:@.+]] to void
>>   // CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()  // CHECK: call {{.*}}
>> [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]*
>>   // CHECK: ret
>> @@ -861,6 +886,122 @@ int main() {
>>
>>   // CHECK: ret void
>>
>> +// CHECK: define internal void [[MAIN_MICROTASK3]](i{{[0-9]+}}* noalias
>> +[[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]***
>> +dereferenceable(8) %{{.+}})
>> +
>> +// CHECK: [[VAR2_ORIG_ADDR:%.+]] = alloca [[S_FLOAT_TY]]***,
>> +
>> +// Reduction list for runtime.
>> +// CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*],
>> +
>> +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}**
>> +[[GTID_ADDR_ADDR:%.+]], // CHECK: [[VAR2_ORIG:%.+]] = load
>> +[[S_FLOAT_TY]]***, [[S_FLOAT_TY]]**** [[VAR2_ORIG_ADDR]],
>> +
>> +// CHECK: load [[S_FLOAT_TY]]**, [[S_FLOAT_TY]]*** [[VAR2_ORIG]], //
>> +CHECK: getelementptr inbounds [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]**
>> +%{{.+}}, i64 0 // CHECK: load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % //
>> +CHECK: [[LOW:%.+]] = getelementptr inbounds [[S_FLOAT_TY]],
>> +[[S_FLOAT_TY]]* %{{.+}}, i64 1 // CHECK: load [[S_FLOAT_TY]]**,
>> +[[S_FLOAT_TY]]*** [[VAR2_ORIG]], // 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]] // CHECK: [[DIF:%.+]] =
>> +sdiv exact i64 [[BYTE_DIF]], ptrtoint (float* getelementptr (float,
>> +float* null, i32 1) to i64) // CHECK: [[SIZE:%.+]] = add nuw i64
>> +[[DIF]], 1 // CHECK: call i8* @llvm.stacksave() // CHECK:
>> +[[VAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]], // 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]] //
>> +CHECK: [[OFFSET:%.+]] = sdiv exact i64 [[OFFSET_BYTES]], ptrtoint
>> +(float* getelementptr (float, float* null, i32 1) to i64) // CHECK:
>> +[[PSEUDO_VAR2_PRIV:%.+]] = getelementptr [[S_FLOAT_TY]],
>> +[[S_FLOAT_TY]]* [[VAR2_PRIV]], i64 [[OFFSET]] // CHECK: store
>> +[[S_FLOAT_TY]]** [[REF:.+]], [[S_FLOAT_TY]]*** % // CHECK: store
>> +[[S_FLOAT_TY]]* [[PSEUDO_VAR2_PRIV]], [[S_FLOAT_TY]]** [[REF]] //
>> +CHECK: ret void
>> +
>> +// CHECK: define internal void [[MAIN_MICROTASK4]](i{{[0-9]+}}* noalias
>> +[[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]*
>> +dereferenceable(8) %{{.+}})
>> +
>> +// CHECK: [[VVAR2_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
>> +
>> +// Reduction list for runtime.
>> +// CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*],
>> +
>> +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}**
>> +[[GTID_ADDR_ADDR:%.+]], // CHECK: [[VVAR2_ORIG:%.+]] = load [2 x
>> +[[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[VVAR2_ORIG_ADDR]],
>> +
>> +// 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]] // CHECK: [[DIF:%.+]] =
>> +sdiv exact i64 [[BYTE_DIF]], ptrtoint (float* getelementptr (float,
>> +float* null, i32 1) to i64) // CHECK: [[SIZE:%.+]] = add nuw i64
>> +[[DIF]], 1 // CHECK: call i8* @llvm.stacksave() // CHECK:
>> +[[VVAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], i64 [[SIZE]], // 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]] //
>> +CHECK: [[OFFSET:%.+]] = sdiv exact i64 [[OFFSET_BYTES]], ptrtoint
>> +(float* getelementptr (float, float* null, i32 1) to i64) // CHECK:
>> +[[PSEUDO_VVAR2_PRIV:%.+]] = getelementptr [[S_FLOAT_TY]],
>> +[[S_FLOAT_TY]]* [[VVAR2_PRIV]], i64 [[OFFSET]] // CHECK:
>> +[[VVAR2_PRIV:%.+]] = bitcast [[S_FLOAT_TY]]* [[PSEUDO_VVAR2_PRIV]]
>> to
>> +[2 x [[S_FLOAT_TY]]]* // CHECK: ret void
>> +
>> +// CHECK: define internal void [[MAIN_MICROTASK5]](i{{[0-9]+}}* noalias
>> +[[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]*
>> +dereferenceable(8) %{{.+}})
>> +
>> +// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*,
>> +
>> +// Reduction list for runtime.
>> +// CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*],
>> +
>> +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}**
>> +[[GTID_ADDR_ADDR:%.+]],
>> +
>> +// CHECK: [[VAR3_ORIG:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x
>> +[[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // 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]]
>> +// CHECK: [[DIF:%.+]] = sdiv exact i64 [[BYTE_DIF]], ptrtoint (float*
>> +getelementptr (float, float* null, i32 1) to i64) // CHECK:
>> +[[SIZE:%.+]] = add nuw i64 [[DIF]], 1 // CHECK: call i8*
>> + at llvm.stacksave() // CHECK: [[VAR3_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
>> +i64 [[SIZE]], // 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]] // CHECK: [[OFFSET:%.+]] = sdiv exact i64
>> +[[OFFSET_BYTES]], ptrtoint (float* getelementptr (float, float* null,
>> +i32 1) to i64) // CHECK: [[PSEUDO_VAR3_PRIV:%.+]] = getelementptr
>> +[[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[VAR3_PRIV]], i64 [[OFFSET]] // CHECK:
>> +[[VAR3_PRIV:%.+]] = bitcast [[S_FLOAT_TY]]* [[PSEUDO_VAR3_PRIV]] to [2
>> +x [[S_FLOAT_TY]]]*
>> +
>> +// CHECK: store [2 x [[S_FLOAT_TY]]]* [[VAR3_PRIV]], [2 x
>> +[[S_FLOAT_TY]]]** %
>> +
>> +// CHECK: ret void
>> +
>> +// CHECK: define internal void [[MAIN_MICROTASK6]](i{{[0-9]+}}* noalias
>> +[[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [2 x [[S_FLOAT_TY]]]*
>> +dereferenceable(8) %{{.+}})
>> +
>> +// CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, //
>> +CHECK: [[VAR3_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
>> +
>> +// Reduction list for runtime.
>> +// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*],
>> +
>> +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}**
>> +[[GTID_ADDR_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: ret void
>> +
>>   // CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()  // CHECK: [[TEST:%.+]]
>> =
>> alloca [[S_INT_TY]],  // CHECK: call {{.*}}
>> [[S_INT_TY_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
>>
>> Modified: cfe/trunk/test/OpenMP/task_codegen.cpp
>> URL: http://llvm.org/viewvc/llvm-
>> project/cfe/trunk/test/OpenMP/task_codegen.cpp?rev=259776&r1=259775
>> &r2=259776&view=diff
>> ==========================================================
>> ====================
>> --- cfe/trunk/test/OpenMP/task_codegen.cpp (original)
>> +++ cfe/trunk/test/OpenMP/task_codegen.cpp Thu Feb  4 05:27:03 2016
>> @@ -120,15 +120,15 @@ int main() {
>>   // CHECK: store i64 4, i64*
>>   // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]],
>> [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2  // CHECK: store i8 3, i8*
>> +// CHECK: [[B_VAL:%.+]] = load i8, i8* [[B]] // CHECK: [[IDX2:%.+]] =
>> +sext i8 [[B_VAL]] to i64
>>   // CHECK: [[IDX1:%.+]] = mul nsw i64 4, [[A_VAL]]  // CHECK: [[START:%.+]]
>> =
>> getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]]
>> +// CHECK: [[START1:%.+]] = getelementptr inbounds i32, i32* [[START]],
>> +i64 [[IDX2]]
>>   // CHECK: [[B_VAL:%.+]] = load i8, i8* [[B]]  // CHECK: [[IDX2:%.+]] = sext
>> i8
>> [[B_VAL]] to i64 -// CHECK: [[START1:%.+]] = getelementptr inbounds i32,
>> i32* [[START]], i64 [[IDX2]]  // CHECK: [[IDX1:%.+]] = mul nsw i64 9,
>> [[A_VAL]]
>> // CHECK: [[END:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64
>> [[IDX1]] -// CHECK: [[B_VAL:%.+]] = load i8, i8* [[B]] -// CHECK:
>> [[IDX2:%.+]] =
>> sext i8 [[B_VAL]] to i64  // CHECK: [[END1:%.+]] = getelementptr inbounds
>> i32, i32* [[END]], i64 [[IDX2]]  // CHECK: [[END2:%.+]] = getelementptr i32,
>> i32* [[END1]], i32 1  // CHECK: [[START_INT:%.+]] = ptrtoint i32* [[START1]]
>> to
>> i64 @@ -173,12 +173,12 @@ int main() {  // CHECK: [[START1:%.+]] =
>> getelementptr inbounds i32, i32* [[START]], i64 3  // CHECK:
>> [[NEW_A_VAL:%.+]] = load i32, i32* @{{.+}},  // CHECK:
>> [[NEW_A_VAL_I64:%.+]] = sext i32 [[NEW_A_VAL]] to i64
>> +// CHECK: [[IDX2:%.+]] = sub nsw i64 [[NEW_A_VAL_I64]], 1 // CHECK:
>> +[[NEW_A_VAL:%.+]] = load i32, i32* @{{.+}}, // CHECK:
>> +[[NEW_A_VAL_I64:%.+]] = sext i32 [[NEW_A_VAL]] to i64
>>   // CHECK: [[SUB:%.+]] = add nsw i64 -1, [[NEW_A_VAL_I64]]  // CHECK:
>> [[IDX1:%.+]] = mul nsw i64 [[SUB]], [[A_VAL]]  // CHECK: [[END:%.+]] =
>> getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]] -// CHECK:
>> [[NEW_A_VAL:%.+]] = load i32, i32* @{{.+}}, -// CHECK:
>> [[NEW_A_VAL_I64:%.+]] = sext i32 [[NEW_A_VAL]] to i64 -// CHECK:
>> [[IDX2:%.+]] = sub nsw i64 [[NEW_A_VAL_I64]], 1  // CHECK: [[END1:%.+]] =
>> getelementptr inbounds i32, i32* [[END]], i64 [[IDX2]]  // CHECK:
>> [[END2:%.+]] = getelementptr i32, i32* [[END1]], i32 1  // CHECK:
>> [[START_INT:%.+]] = ptrtoint i32* [[START1]] to i64
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list