clauses.
Implemented codegen for array shaping operation in depend clauses. The
begin of the expression is the pointer itself, while the size of the
dependence data is the mukltiplacation of all dimensions in the array
shaping expression.
if (Dependencies[I].first == OMPC_DEPEND_depobj)
continue;
const Expr *E = Dependencies[I].second;
- LValue Addr = CGF.EmitLValue(E);
+ const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
+ LValue Addr;
+ if (OASE) {
+ const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
+ Addr =
+ CGF.EmitLoadOfPointerLValue(CGF.EmitLValue(Base).getAddress(CGF),
+ Base->getType()->castAs<PointerType>());
+ } else {
+ Addr = CGF.EmitLValue(E);
+ }
llvm::Value *Size;
QualType Ty = E->getType();
- if (const auto *ASE =
- dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
+ if (OASE) {
+ Size = llvm::ConstantInt::get(CGF.SizeTy,/*V=*/1);
+ for (const Expr *SE : OASE->getDimensions()) {
+ llvm::Value *Sz = CGF.EmitScalarExpr(SE);
+ Sz = CGF.EmitScalarConversion(Sz, SE->getType(),
+ CGF.getContext().getSizeType(),
+ SE->getExprLoc());
+ Size = CGF.Builder.CreateNUWMul(Size, Sz);
+ }
+ } else if (const auto *ASE =
+ dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
LValue UpAddrLVal =
CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
template <class T>
T tmain(T argc) {
static T a;
-#pragma omp depobj(a) depend(in:argc)
+ int *b;
+#pragma omp depobj(a) depend(in:argc, ([4][*b][4])b)
#pragma omp depobj(argc) destroy
#pragma omp depobj(argc) update(inout)
return argc;
}
// CHECK: static T a;
-// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}}
+// CHECK-NEXT: int *b;
+// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc,([4][*b][4])b){{$}}
// CHECK-NEXT: #pragma omp depobj (argc) destroy{{$}}
// CHECK-NEXT: #pragma omp depobj (argc) update(inout){{$}}
// CHECK: static void *a;
-// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}}
+// CHECK-NEXT: int *b;
+// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc,([4][*b][4])b){{$}}
// CHECK-NEXT: #pragma omp depobj (argc) destroy{{$}}
// CHECK-NEXT: #pragma omp depobj (argc) update(inout){{$}}
T tmain(T argc) {
static T a;
void *argv;
-#pragma omp depobj(a) depend(in:argv)
+#pragma omp depobj(a) depend(in:argv, ([3][*(int*)argv][4])argv)
#pragma omp depobj(argc) destroy
#pragma omp depobj(argc) update(inout)
return argc;
// CHECK-LABEL: tmain
// CHECK: [[ARGC_ADDR:%.+]] = alloca i8*,
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
-// CHECK: [[DEP_ADDR_VOID:%.+]] = call i8* @__kmpc_alloc(i32 [[GTID]], i64 48, i8* null)
-// CHECK: [[DEP_ADDR:%.+]] = bitcast i8* [[DEP_ADDR_VOID]] to [2 x %struct.kmp_depend_info]*
-// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[DEP_ADDR_VOID:%.+]] = call i8* @__kmpc_alloc(i32 [[GTID]], i64 72, i8* null)
+// CHECK: [[DEP_ADDR:%.+]] = bitcast i8* [[DEP_ADDR_VOID]] to [3 x %struct.kmp_depend_info]*
+// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 0
// CHECK: [[SZ_BASE:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 0
-// CHECK: store i64 1, i64* [[SZ_BASE]],
-// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 1
+// CHECK: store i64 2, i64* [[SZ_BASE]],
+// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 1
// CHECK: [[ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 0
// CHECK: store i64 %{{.+}}, i64* [[ADDR]],
// CHECK: [[SZ_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 1
// CHECK: store i64 8, i64* [[SZ_ADDR]],
// CHECK: [[FLAGS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 2
// CHECK: store i8 1, i8* [[FLAGS_ADDR]],
-// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 1
+// CHECK: [[SHAPE_ADDR:%.+]] = load i8*, i8** [[ARGV_ADDR:%.+]],
+// CHECK: [[SZ1:%.+]] = mul nuw i64 3, %{{.+}}
+// CHECK: [[SZ:%.+]] = mul nuw i64 [[SZ1]], 4
+// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 2
+// CHECK: [[ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[SHAPE:%.+]] = ptrtoint i8* [[SHAPE_ADDR]] to i64
+// CHECK: store i64 [[SHAPE]], i64* [[ADDR]],
+// CHECK: [[SZ_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 1
+// CHECK: store i64 [[SZ]], i64* [[SZ_ADDR]],
+// CHECK: [[FLAGS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 2
+// CHECK: store i8 1, i8* [[FLAGS_ADDR]],
+// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 1
// CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[BASE_ADDR]] to i8*
// CHECK: store i8* [[DEP]], i8** [[TMAIN_A]],
// CHECK: [[ARGC:%.+]] = load i8*, i8** [[ARGC_ADDR]],
int main() {
omp_depend_t d, x;
omp_event_handle_t evt;
- int a;
+ int a, *b;
// CHECK: [[D_ADDR:%.+]] = alloca i8*,
// CHECK: [[X_ADDR:%.+]] = alloca i8*,
// CHECK: [[EVT_ADDR:%.+]] = alloca i64,
// CHECK: [[X_DEP_BASE_SIZE:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[X_DEP_BASE]], i{{.+}} 0, i{{.+}} 0
// CHECK: [[SIZE2:%.+]] = load i64, i64* [[X_DEP_BASE_SIZE]],
// CHECK: [[SIZE3:%.+]] = add nuw i64 [[SIZE]], [[SIZE2]]
- // CHECK: [[SIZE:%.+]] = add nuw i64 [[SIZE3]], 1
+ // CHECK: [[SIZE:%.+]] = add nuw i64 [[SIZE3]], 2
// CHECK: [[SIZE32:%.+]] = trunc i64 [[SIZE]] to i32
// CHECK: [[SIZE64:%.+]] = zext i32 [[SIZE32]] to i64
// CHECK: [[SV:%.+]] = call i8* @llvm.stacksave()
// CHECK: store i64 4, i64* [[SIZE_ADDR]],
// CHECK: [[FLAGS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA0]], i{{.+}} 0, i{{.+}} 2
// CHECK: store i8 1, i8* [[FLAGS_ADDR]],
- // CHECK: [[VLA_D:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA]], i64 1
+ // CHECK: [[B_ADDR:%.+]] = load i32*, i32** %{{.+}},
+ // CHECK: [[A:%.+]] = load i32, i32* [[A_ADDR]],
+ // CHECK: [[A_CAST:%.+]] = sext i32 [[A]] to i64
+ // CHECK: [[SZ1:%.+]] = mul nuw i64 3, [[A_CAST]]
+ // CHECK: [[A:%.+]] = load i32, i32* [[A_ADDR]],
+ // CHECK: [[A_CAST:%.+]] = sext i32 [[A]] to i64
+ // CHECK: [[SZ:%.+]] = mul nuw i64 [[SZ1]], [[A_CAST]]
+ // CHECK: [[VLA1:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA]], i64 1
+ // CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA1]], i{{.+}} 0, i{{.+}} 0
+ // CHECK: [[B_ADDR_CAST:%.+]] = ptrtoint i32* [[B_ADDR]] to i64
+ // CHECK: store i64 [[B_ADDR_CAST]], i64* [[BASE_ADDR]],
+ // CHECK: [[SIZE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA1]], i{{.+}} 0, i{{.+}} 1
+ // CHECK: store i64 [[SZ]], i64* [[SIZE_ADDR]],
+ // CHECK: [[FLAGS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA1]], i{{.+}} 0, i{{.+}} 2
+ // CHECK: store i8 1, i8* [[FLAGS_ADDR]],
+ // CHECK: [[VLA_D:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA]], i64 2
// CHECK: [[D_SIZE:%.+]] = mul nuw i64 24, [[SIZE1]]
// CHECK: [[DEST:%.+]] = bitcast %struct.kmp_depend_info* [[VLA_D]] to i8*
// CHECK: [[SRC:%.+]] = bitcast %struct.kmp_depend_info* [[D_DEP]] to i8*
- // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[DEST]], i8* align 8 [[SRC]], i64 [[D_SIZE]], i1 false)
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align {{.+}} [[DEST]], i8* align {{.+}} [[SRC]], i64 [[D_SIZE]], i1 false)
// CHECK: [[VLA_X:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[VLA_D]], i64 [[SIZE1]]
// CHECK: [[X_SIZE:%.+]] = mul nuw i64 24, [[SIZE2]]
// CHECK: [[DEST:%.+]] = bitcast %struct.kmp_depend_info* [[VLA_X]] to i8*
// CHECK: call i32 @__kmpc_omp_task_with_deps(%struct.ident_t* @{{.+}}, i32 [[GTID]], i8* [[ALLOC]], i32 [[SIZE32]], i8* [[BC]], i32 0, i8* null)
// CHECK: [[SV:%.+]] = load i8*, i8** [[SV_ADDR]],
// CHECK: call void @llvm.stackrestore(i8* [[SV]])
-#pragma omp task depend(in: a) depend(depobj: d, x) detach(evt)
+#pragma omp task depend(in: a, ([3][a][a])b) depend(depobj: d, x) detach(evt)
{
#pragma omp taskgroup
{