diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 127 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 46 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
| -rw-r--r-- | clang/test/OpenMP/task_codegen.cpp | 93 |
4 files changed, 247 insertions, 22 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a0d004d315c..bf660b448c3 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -911,6 +911,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitUnaryOpLValue(cast<UnaryOperator>(E)); case Expr::ArraySubscriptExprClass: return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E)); + case Expr::OMPArraySectionExprClass: + return EmitOMPArraySectionExpr(cast<OMPArraySectionExpr>(E)); case Expr::ExtVectorElementExprClass: return EmitExtVectorElementExpr(cast<ExtVectorElementExpr>(E)); case Expr::MemberExprClass: @@ -2559,6 +2561,131 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, return LV; } +LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, + bool LowerBound) { + LValue Base; + if (auto *ASE = + dyn_cast<OMPArraySectionExpr>(E->getBase()->IgnoreParenImpCasts())) + Base = EmitOMPArraySectionExpr(ASE, LowerBound); + else + Base = EmitLValue(E->getBase()); + QualType BaseTy = Base.getType(); + llvm::Value *Idx; + QualType ResultExprTy; + if (auto *AT = getContext().getAsArrayType(BaseTy)) + ResultExprTy = AT->getElementType(); + else + ResultExprTy = BaseTy->getPointeeType(); + if (LowerBound) { + Idx = E->getLowerBound() + ? Builder.CreateIntCast(EmitScalarExpr(E->getLowerBound()), + IntPtrTy, + E->getLowerBound() + ->getType() + ->hasSignedIntegerRepresentation()) + : llvm::ConstantInt::getNullValue(IntPtrTy); + } else { + auto &C = CGM.getContext(); + auto *Length = E->getLength(); + if (Length || E->getColonLoc().isInvalid()) { + // Idx = LowerBound + Length - 1; + auto *One = llvm::ConstantInt::get(IntPtrTy, /*V=*/1); + if (Length) { + Idx = Builder.CreateIntCast( + EmitScalarExpr(Length), IntPtrTy, + Length->getType()->hasSignedIntegerRepresentation()); + } + auto *LowerBound = E->getLowerBound(); + llvm::APSInt ConstLowerBound; + if (LowerBound && LowerBound->isIntegerConstantExpr(ConstLowerBound, C)) + LowerBound = nullptr; + if (LowerBound && ConstLowerBound.getZExtValue() != 0) { + auto *LowerBoundVal = Builder.CreateIntCast( + EmitScalarExpr(LowerBound), IntPtrTy, + LowerBound->getType()->hasSignedIntegerRepresentation()); + if (E->getColonLoc().isValid()) { + if (getLangOpts().isSignedOverflowDefined()) + Idx = Builder.CreateAdd(Idx, LowerBoundVal); + else + Idx = Builder.CreateNSWAdd(Idx, LowerBoundVal); + } else + Idx = LowerBoundVal; + } + if (E->getColonLoc().isValid()) { + if (getLangOpts().isSignedOverflowDefined()) + Idx = Builder.CreateSub(Idx, One); + else + Idx = Builder.CreateNSWSub(Idx, One); + } + } else if (auto *VAT = C.getAsVariableArrayType(BaseTy)) { + // Idx = ArrSize - 1; + Length = VAT->getSizeExpr(); + Idx = Builder.CreateIntCast( + EmitScalarExpr(Length), IntPtrTy, + Length->getType()->hasSignedIntegerRepresentation()); + auto *One = llvm::ConstantInt::get(IntPtrTy, /*V=*/1); + if (getLangOpts().isSignedOverflowDefined()) + Idx = Builder.CreateSub(Idx, One); + else + Idx = Builder.CreateNSWSub(Idx, One); + } else { + // Idx = ArrSize - 1; + auto *CAT = C.getAsConstantArrayType(BaseTy); + Idx = llvm::ConstantInt::get(IntPtrTy, CAT->getSize().getZExtValue() - 1); + } + } + + llvm::Value *Address; + CharUnits ArrayAlignment; + if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) { + // The element count here is the total number of non-VLA elements. + 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); + Address = Builder.CreateGEP(Base.getAddress(), Idx, "arrayidx"); + } else { + Idx = Builder.CreateNSWMul(Idx, numElements); + Address = Builder.CreateInBoundsGEP(Base.getAddress(), Idx, "arrayidx"); + } + } else if (BaseTy->isConstantArrayType()) { + llvm::Value *ArrayPtr = Base.getAddress(); + llvm::Value *Zero = llvm::ConstantInt::getNullValue(IntPtrTy); + llvm::Value *Args[] = {Zero, Idx}; + + // Propagate the alignment from the array itself to the result. + ArrayAlignment = Base.getAlignment(); + + if (getLangOpts().isSignedOverflowDefined()) + Address = Builder.CreateGEP(ArrayPtr, Args, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx"); + } else { + // The base must be a pointer, which is not an aggregate. Emit it. + if (getLangOpts().isSignedOverflowDefined()) + Address = Builder.CreateGEP(Base.getAddress(), Idx, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(Base.getAddress(), Idx, "arrayidx"); + } + + // Limit the alignment to that of the result type. + LValue LV; + if (!ArrayAlignment.isZero()) { + CharUnits Align = getContext().getTypeAlignInChars(ResultExprTy); + ArrayAlignment = std::min(Align, ArrayAlignment); + LV = MakeAddrLValue(Address, ResultExprTy, ArrayAlignment); + } else + LV = MakeNaturalAlignAddrLValue(Address, ResultExprTy); + + LV.getQuals().setAddressSpace(BaseTy.getAddressSpace()); + + return LV; +} + LValue CodeGenFunction:: EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { // Emit the base vector as an l-value. diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index f734298360b..f4148db7519 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2091,6 +2091,27 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, return TaskPrivatesMap; } +llvm::Value *getTypeSize(CodeGenFunction &CGF, QualType Ty) { + auto &C = CGF.getContext(); + llvm::Value *Size; + auto SizeInChars = C.getTypeSizeInChars(Ty); + if (SizeInChars.isZero()) { + // getTypeSizeInChars() returns 0 for a VLA. + Size = nullptr; + while (auto *VAT = C.getAsVariableArrayType(Ty)) { + llvm::Value *ArraySize; + std::tie(ArraySize, Ty) = CGF.getVLASize(VAT); + Size = Size ? CGF.Builder.CreateNUWMul(Size, ArraySize) : ArraySize; + } + SizeInChars = C.getTypeSizeInChars(Ty); + assert(!SizeInChars.isZero()); + Size = CGF.Builder.CreateNUWMul( + Size, llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity())); + } else + Size = llvm::ConstantInt::get(CGF.SizeTy, SizeInChars.getQuantity()); + return Size; +} + static int array_pod_sort_comparator(const PrivateDataTy *P1, const PrivateDataTy *P2) { return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0); @@ -2328,19 +2349,30 @@ void CGOpenMPRuntime::emitTaskCall( // kmp_depend_info[<Dependences.size()>] deps; DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy); for (unsigned i = 0; i < DependencesNumber; ++i) { - auto Addr = CGF.EmitLValue(Dependences[i].second); - auto *Size = llvm::ConstantInt::get( - CGF.SizeTy, - C.getTypeSizeInChars(Dependences[i].second->getType()).getQuantity()); + auto *E = Dependences[i].second; + LValue Addr = CGF.EmitLValue(E); + llvm::Value *Size; + QualType Ty = E->getType(); + auto *DestAddr = Addr.getAddress(); + if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { + LValue UpAddrLVal = + CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); + llvm::Value *UpAddr = + CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getAddress(), /*Idx0=*/1); + llvm::Value *LowIntPtr = + CGF.Builder.CreatePtrToInt(DestAddr, CGM.SizeTy); + llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); + Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); + } else + Size = getTypeSize(CGF, Ty); auto Base = CGF.MakeNaturalAlignAddrLValue( CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i), KmpDependInfoTy); // deps[i].base_addr = &<Dependences[i].second>; auto BaseAddrLVal = CGF.EmitLValueForField( Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); - CGF.EmitStoreOfScalar( - CGF.Builder.CreatePtrToInt(Addr.getAddress(), CGF.IntPtrTy), - BaseAddrLVal); + CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(DestAddr, CGF.IntPtrTy), + BaseAddrLVal); // deps[i].len = sizeof(<Dependences[i].second>); auto LenLVal = CGF.EmitLValueForField( Base, *std::next(KmpDependInfoRD->field_begin(), Len)); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 26ce8e72afa..ca3d3c40dec 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -24,6 +24,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" #include "clang/Basic/CapturedStmt.h" @@ -2427,6 +2428,8 @@ public: LValue EmitUnaryOpLValue(const UnaryOperator *E); LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E, bool Accessed = false); + LValue EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, + bool LowerBound = true); LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E); LValue EmitMemberExpr(const MemberExpr *E); LValue EmitObjCIsaExpr(const ObjCIsaExpr *E); diff --git a/clang/test/OpenMP/task_codegen.cpp b/clang/test/OpenMP/task_codegen.cpp index 139ac505a9f..a91ec1837de 100644 --- a/clang/test/OpenMP/task_codegen.cpp +++ b/clang/test/OpenMP/task_codegen.cpp @@ -24,6 +24,7 @@ int main() { // CHECK: [[S:%.+]] = alloca [2 x [[STRUCT_S]]] char b; S s[2]; + int arr[10][a]; // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* @{{.+}}) // CHECK: [[B_REF:%.+]] = getelementptr inbounds [[STRUCT_SHAREDS]], [[STRUCT_SHAREDS]]* [[CAPTURES:%.+]], i32 0, i32 0 // CHECK: store i8* [[B]], i8** [[B_REF]] @@ -52,14 +53,14 @@ int main() { // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[SHAREDS_REF]], i8* [[BITCAST]], i64 8, i32 8, i1 false) // CHECK: [[DESTRUCTORS_REF_PTR:%.+]] = getelementptr inbounds [[KMP_TASK_T]], [[KMP_TASK_T]]* [[TASK_PTR]], i32 0, i32 3 // CHECK: store i32 (i32, i8*)* null, i32 (i32, i8*)** [[DESTRUCTORS_REF_PTR]] -// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: getelementptr inbounds [4 x [[KMP_DEPEND_INFO]]], [4 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: store i64 ptrtoint (i32* @{{.+}} to i64), i64* // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 1 // CHECK: store i64 4, i64* // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 // CHECK: store i8 1, i8* -// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 1 +// CHECK: getelementptr inbounds [4 x [[KMP_DEPEND_INFO]]], [4 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 1 // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: ptrtoint i8* [[B]] to i64 // CHECK: store i64 %{{[^,]+}}, i64* @@ -67,7 +68,7 @@ int main() { // CHECK: store i64 1, i64* // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 // CHECK: store i8 1, i8* -// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 2 +// CHECK: getelementptr inbounds [4 x [[KMP_DEPEND_INFO]]], [4 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 2 // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: ptrtoint [2 x [[STRUCT_S]]]* [[S]] to i64 // CHECK: store i64 %{{[^,]+}}, i64* @@ -75,10 +76,26 @@ int main() { // CHECK: store i64 8, i64* // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 // CHECK: store i8 1, i8* -// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: [[IDX1:%.+]] = mul nsw i64 0, [[A_VAL:%.+]] +// CHECK: [[START:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]] +// CHECK: [[IDX1:%.+]] = mul nsw i64 9, [[A_VAL]] +// CHECK: [[END:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]] +// CHECK: [[END1:%.+]] = getelementptr i32, i32* [[END]], i32 1 +// CHECK: [[START_INT:%.+]] = ptrtoint i32* [[START]] to i64 +// CHECK: [[END_INT:%.+]] = ptrtoint i32* [[END1]] to i64 +// CHECK: [[SIZEOF:%.+]] = sub nuw i64 [[END_INT]], [[START_INT]] +// CHECK: getelementptr inbounds [4 x [[KMP_DEPEND_INFO]]], [4 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 3 +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: ptrtoint i32* [[START]] to i64 +// CHECK: store i64 %{{[^,]+}}, i64* +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 1 +// CHECK: store i64 [[SIZEOF]], i64* +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 +// CHECK: store i8 1, i8* +// CHECK: getelementptr inbounds [4 x [[KMP_DEPEND_INFO]]], [4 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: bitcast [[KMP_DEPEND_INFO]]* %{{.+}} to i8* -// CHECK: call i32 @__kmpc_omp_task_with_deps([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]], i32 3, i8* %{{[^,]+}}, i32 0, i8* null) -#pragma omp task shared(a, s) depend(in : a, b, s) +// CHECK: call i32 @__kmpc_omp_task_with_deps([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]], i32 4, i8* %{{[^,]+}}, i32 0, i8* null) +#pragma omp task shared(a, s) depend(in : a, b, s, arr[:]) { a = 15; s[1].a = 10; @@ -95,7 +112,7 @@ int main() { // CHECK: [[DESTRUCTORS_REF_PTR:%.+]] = getelementptr inbounds [[KMP_TASK_T]]{{.*}}* {{%.+}}, i32 0, i32 3 // CHECK: store i32 (i32, i8*)* null, i32 (i32, i8*)** [[DESTRUCTORS_REF_PTR]] // CHECK: getelementptr inbounds [2 x [[STRUCT_S]]], [2 x [[STRUCT_S]]]* [[S]], i32 0, i64 0 -// CHECK: getelementptr inbounds [1 x [[KMP_DEPEND_INFO]]], [1 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: getelementptr inbounds [2 x [[KMP_DEPEND_INFO]]], [2 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: ptrtoint [[STRUCT_S]]* %{{.+}} to i64 // CHECK: store i64 %{{[^,]+}}, i64* @@ -103,17 +120,39 @@ int main() { // CHECK: store i64 4, i64* // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 // CHECK: store i8 2, i8* -// CHECK: getelementptr inbounds [1 x [[KMP_DEPEND_INFO]]], [1 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: [[IDX1:%.+]] = mul nsw i64 4, [[A_VAL]] +// CHECK: [[START:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]] +// 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 +// CHECK: [[END_INT:%.+]] = ptrtoint i32* [[END2]] to i64 +// CHECK: [[SIZEOF:%.+]] = sub nuw i64 [[END_INT]], [[START_INT]] +// CHECK: getelementptr inbounds [2 x [[KMP_DEPEND_INFO]]], [2 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 1 +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: ptrtoint i32* [[START1]] to i64 +// CHECK: store i64 %{{[^,]+}}, i64* +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 1 +// CHECK: store i64 [[SIZEOF]], i64* +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 +// CHECK: store i8 2, i8* +// CHECK: getelementptr inbounds [2 x [[KMP_DEPEND_INFO]]], [2 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: bitcast [[KMP_DEPEND_INFO]]* %{{.+}} to i8* -// CHECK: call i32 @__kmpc_omp_task_with_deps([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]], i32 1, i8* %{{[^,]+}}, i32 0, i8* null) -#pragma omp task untied depend(out : s[0]) +// CHECK: call i32 @__kmpc_omp_task_with_deps([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]], i32 2, i8* %{{[^,]+}}, i32 0, i8* null) +#pragma omp task untied depend(out : s[0], arr[4:][b]) { a = 1; } // CHECK: [[ORIG_TASK_PTR:%.+]] = call i8* @__kmpc_omp_task_alloc([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i32 3, i64 32, i64 1, // CHECK: [[DESTRUCTORS_REF_PTR:%.+]] = getelementptr inbounds [[KMP_TASK_T]]{{.*}}* {{%.+}}, i32 0, i32 3 // CHECK: store i32 (i32, i8*)* null, i32 (i32, i8*)** [[DESTRUCTORS_REF_PTR]] -// CHECK: getelementptr inbounds [2 x [[KMP_DEPEND_INFO]]], [2 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: store i64 ptrtoint (i32* @{{.+}} to i64), i64* // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 1 @@ -121,7 +160,7 @@ int main() { // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 // CHECK: store i8 3, i8* // CHECK: getelementptr inbounds [2 x [[STRUCT_S]]], [2 x [[STRUCT_S]]]* [[S]], i32 0, i64 1 -// CHECK: getelementptr inbounds [2 x [[KMP_DEPEND_INFO]]], [2 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 1 +// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 1 // CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: ptrtoint [[STRUCT_S]]* %{{.+}} to i64 // CHECK: store i64 %{{[^,]+}}, i64* @@ -129,10 +168,34 @@ 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: getelementptr inbounds [2 x [[KMP_DEPEND_INFO]]], [2 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: [[IDX1:%.+]] = mul nsw i64 0, [[A_VAL]] +// CHECK: [[START:%.+]] = getelementptr inbounds i32, i32* %{{.+}}, i64 [[IDX1]] +// 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: [[SUB:%.+]] = sub nsw i64 [[NEW_A_VAL_I64]], 1 +// 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 +// CHECK: [[END_INT:%.+]] = ptrtoint i32* [[END2]] to i64 +// CHECK: [[SIZEOF:%.+]] = sub nuw i64 [[END_INT]], [[START_INT]] +// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 2 +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 0 +// CHECK: ptrtoint i32* [[START1]] to i64 +// CHECK: store i64 %{{[^,]+}}, i64* +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 1 +// CHECK: store i64 [[SIZEOF]], i64* +// CHECK: getelementptr inbounds [[KMP_DEPEND_INFO]], [[KMP_DEPEND_INFO]]* %{{[^,]+}}, i32 0, i32 2 +// CHECK: store i8 3, i8* +// CHECK: getelementptr inbounds [3 x [[KMP_DEPEND_INFO]]], [3 x [[KMP_DEPEND_INFO]]]* %{{[^,]+}}, i32 0, i32 0 // CHECK: bitcast [[KMP_DEPEND_INFO]]* %{{.+}} to i8* -// CHECK: call i32 @__kmpc_omp_task_with_deps([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]], i32 2, i8* %{{[^,]+}}, i32 0, i8* null) -#pragma omp task final(true) depend(inout: a, s[1]) +// CHECK: call i32 @__kmpc_omp_task_with_deps([[IDENT_T]]* @{{.+}}, i32 [[GTID]], i8* [[ORIG_TASK_PTR]], i32 3, i8* %{{[^,]+}}, i32 0, i8* null) +#pragma omp task final(true) depend(inout: a, s[1], arr[:a][3:]) { a = 2; } |

