forked from OSchip/llvm-project
[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. llvm-svn: 259776
This commit is contained in:
parent
e1649a7853
commit
31300ed0a5
|
@ -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]); }
|
||||
|
|
|
@ -4026,16 +4026,18 @@ unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
|
|||
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()))
|
||||
|
|
|
@ -1949,6 +1949,21 @@ LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr,
|
|||
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::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
|
|||
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::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
|
|||
} 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::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
|
|||
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::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
|
|||
}
|
||||
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())
|
||||
Idx = Builder.CreateMul(Idx, NumElements);
|
||||
else
|
||||
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
|
||||
ArrayLV = EmitLValue(Array);
|
||||
|
||||
if (getLangOpts().isSignedOverflowDefined())
|
||||
EltPtr = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
|
||||
else
|
||||
EltPtr = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
|
||||
// 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 {
|
||||
// The base must be a pointer, which is not an aggregate. Emit it.
|
||||
if (getLangOpts().isSignedOverflowDefined())
|
||||
EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
|
||||
else
|
||||
EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx, "arrayidx");
|
||||
Address Base = emitOMPArraySectionBase(*this, E->getBase(), AlignSource,
|
||||
BaseTy, ResultExprTy, IsLowerBound);
|
||||
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
|
||||
!getLangOpts().isSignedOverflowDefined());
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
LV.getQuals().setAddressSpace(BaseTy.getAddressSpace());
|
||||
|
||||
return LV;
|
||||
return MakeAddrLValue(EltPtr, ResultExprTy, AlignSource);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::
|
||||
|
|
|
@ -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, SourceLocation Loc,
|
|||
// 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 *emitDestructorsFunction(CodeGenModule &CGM,
|
|||
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(CodeGenModule &CGM, SourceLocation Loc,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -672,6 +672,54 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
|
|||
}
|
||||
}
|
||||
|
||||
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::EmitOMPReductionClauseInit(
|
|||
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::EmitOMPReductionClauseInit(
|
|||
});
|
||||
// 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::EmitOMPReductionClauseInit(
|
|||
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::EmitOMPReductionClauseInit(
|
|||
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::EmitOMPReductionClauseInit(
|
|||
});
|
||||
// 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::EmitOMPReductionClauseInit(
|
|||
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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -4146,12 +4146,18 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
|
|||
}
|
||||
if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
|
||||
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::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
|
|||
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);
|
||||
|
|
|
@ -7745,9 +7745,9 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
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::ActOnOpenMPReductionClause(
|
|||
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::ActOnOpenMPReductionClause(
|
|||
// 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(OpenMPDependClauseKind DepKind,
|
|||
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;
|
||||
|
|
|
@ -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]+}}*, ...)*, ...) @__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]+}}*, ...)*, ...) @__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]+}}*, ...)*, ...) @__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* @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]])
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue