cchen created this revision.
cchen added a reviewer: ABataev.
Herald added subscribers: cfe-commits, guansong, yaxunl.
Herald added a reviewer: jdoerfert.
Herald added a project: clang.
In order not to modify the `tgt_target_data_update` information but still be
able to pass the extra information for non-contiguous map item (offset,
count, and stride for each dimension), this patch overload `arg` when
the maptype is set as `OMP_MAP_DESCRIPTOR`. The origin `arg` is for
passing the pointer information, however, the overloaded `arg` is an
array of descriptor_dim:
struct descriptor_dim {
int64_t offset;
int64_t count;
int64_t stride
};
and the array size is the same as dimension size. In addition, since we
have count and stride information in descriptor_dim, we can replace/overload the
`arg_size` parameter by using dimension size.
More details can be found here:
https://github.com/chichunchen/openmp-50-design/blob/master/target_update_noncontiguous.pptx
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D79972
Files:
clang/include/clang/AST/OpenMPClause.h
clang/lib/AST/OpenMPClause.cpp
clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntime.h
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/OpenMP/target_update_ast_print.cpp
clang/test/OpenMP/target_update_codegen.cpp
Index: clang/test/OpenMP/target_update_codegen.cpp
===================================================================
--- clang/test/OpenMP/target_update_codegen.cpp
+++ clang/test/OpenMP/target_update_codegen.cpp
@@ -1059,5 +1059,142 @@
#pragma omp target update from(([sa][5])f)
}
+#endif
+
+///==========================================================================///
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-64
+// RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-64
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-32
+// RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK19 --check-prefix CK19-32
+
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// SIMD-ONLY19-NOT: {{__kmpc|__tgt}}
+#ifdef CK19
+
+// CK19: [[STRUCT_DESCRIPTOR:%.+]] = type { i64, i64, i64 }
+
+// CK19: [[MSIZE:@.+]] = {{.+}}constant [1 x i64] [i64 3]
+// CK19: [[MTYPE:@.+]] = {{.+}}constant [1 x i64] [i64 2081]
+
+// CK19-LABEL: _Z3foo
+void foo(int arg) {
+ int arr[3][4][5];
+
+ // CK19: [[DIMS:%.+]] = alloca [3 x [[STRUCT_DESCRIPTOR]]],
+ // CK19: [[ARRAY_IDX:%.+]] = getelementptr inbounds [3 x [4 x [5 x i32]]], [3 x [4 x [5 x i32]]]* [[ARR:%.+]], {{.+}} 0, {{.+}} 0
+ // CK19: [[ARRAY_DECAY:%.+]] = getelementptr inbounds [4 x [5 x i32]], [4 x [5 x i32]]* [[ARRAY_IDX]], {{.+}} 0, {{.+}} 0
+ // CK19: [[ARRAY_IDX_1:%.+]] = getelementptr inbounds [5 x i32], [5 x i32]* [[ARRAY_DECAY]], {{.+}}
+ // CK19: [[ARRAY_DECAY_2:%.+]] = getelementptr inbounds [5 x i32], [5 x i32]* [[ARRAY_IDX_1]], {{.+}} 0, {{.+}} 0
+ // CK19: [[ARRAY_IDX_3:%.+]] = getelementptr inbounds {{.+}}, {{.+}}* [[ARRAY_DECAY_2]], {{.+}} 1
+ // CK19: [[LEN:%.+]] = sub nuw i64 4, [[ARG_ADDR:%.+]]
+ // CK19: [[BP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP:%.+]], i{{.+}} 0, i{{.+}} 0
+ // CK19: [[P0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P:%.+]], i{{.+}} 0, i{{.+}} 0
+ // CK19: [[DIM_1:%.+]] = getelementptr inbounds [3 x [[STRUCT_DESCRIPTOR]]], [3 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]], {{.+}} 0, {{.+}} 0
+ // CK19: [[OFFSET:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_1]], {{.+}} 0, {{.+}} 0
+ // CK19: store i64 0, i64* [[OFFSET]],
+ // CK19: [[COUNT:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_1]], {{.+}} 0, {{.+}} 1
+ // CK19: store i64 2, i64* [[COUNT]],
+ // CK19: [[STRIDE:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_1]], {{.+}} 0, {{.+}} 2
+ // CK19: store i64 80, i64* [[STRIDE]],
+ // CK19: [[DIM_2:%.+]] = getelementptr inbounds [3 x [[STRUCT_DESCRIPTOR]]], [3 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]], {{.+}} 0, {{.+}} 1
+ // CK19: [[OFFSET_2:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_2]], {{.+}} 0, {{.+}} 0
+ // CK19: store i64 [[ARG:%.+]], i64* [[OFFSET_2]],
+ // CK19: [[COUNT_2:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_2]], {{.+}} 0, {{.+}} 1
+ // CK19: store i64 [[LEN]], i64* [[COUNT_2]],
+ // CK19: [[STRIDE_2:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_2]], {{.+}} 0, {{.+}} 2
+ // CK19: store i64 20, i64* [[STRIDE_2]],
+ // CK19: [[DIM_3:%.+]] = getelementptr inbounds [3 x [[STRUCT_DESCRIPTOR]]], [3 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]], {{.+}} 0, {{.+}} 2
+ // CK19: [[OFFSET_3:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_3]], {{.+}} 0, {{.+}} 0
+ // CK19: store i64 1, i64* [[OFFSET_3]],
+ // CK19: [[COUNT_3:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_3]], {{.+}} 0, {{.+}} 1
+ // CK19: store i64 4, i64* [[COUNT_3]],
+ // CK19: [[STRIDE_3:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_3]], {{.+}} 0, {{.+}} 2
+ // CK19: store i64 4, i64* [[STRIDE_3]],
+
+ // CK19-DAG: call void @__tgt_target_data_update(i64 -1, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MSIZE]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE]]{{.+}})
+ // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
+ // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK19-DAG: [[PC0:%.+]] = bitcast [3 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]] to i8*
+ // CK19-DAG: [[PTRS:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %.offload_ptrs, i32 0, i32 0
+ // CK19-DAG: store i8* [[PC0]], i8** [[PTRS]],
+
+#pragma omp target update to(arr[0:2][arg:][1:4])
+ {++arg;}
+}
+
+#endif
+///==========================================================================///
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-64
+// RUN: %clang_cc1 -DCK20 -fopenmp -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-64
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-32
+// RUN: %clang_cc1 -DCK20 -fopenmp -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK20 --check-prefix CK20-32
+
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK20 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK20 -verify -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// RUN: %clang_cc1 -DCK20 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY19 %s
+// SIMD-ONLY19-NOT: {{__kmpc|__tgt}}
+#ifdef CK20
+
+struct ST {
+ int a;
+ double *b;
+};
+
+// CK20: [[STRUCT_ST:%.+]] = type { i32, double* }
+// CK20: [[STRUCT_DESCRIPTOR:%.+]] = type { i64, i64, i64 }
+
+// CK20: [[MSIZE:@.+]] = {{.+}}constant [1 x i64] [i64 2]
+// CK20: [[MTYPE:@.+]] = {{.+}}constant [1 x i64] [i64 2081]
+
+// CK20-LABEL: _Z3foo
+void foo(int arg) {
+ ST arr[3][4];
+ // CK20: [[DIMS:%.+]] = alloca [2 x [[STRUCT_DESCRIPTOR]]],
+ // CK20: [[ARRAY_IDX:%.+]] = getelementptr inbounds [3 x [4 x [[STRUCT_ST]]]], [3 x [4 x [[STRUCT_ST]]]]* [[ARR:%.+]], {{.+}} 0, {{.+}} 0
+ // CK20: [[ARRAY_DECAY:%.+]] = getelementptr inbounds [4 x [[STRUCT_ST]]], [4 x [[STRUCT_ST]]]* [[ARRAY_IDX]], {{.+}} 0, {{.+}} 0
+ // CK20: [[ARRAY_IDX_1:%.+]] = getelementptr inbounds [[STRUCT_ST]], [[STRUCT_ST]]* [[ARRAY_DECAY]], {{.+}}
+ // CK20: [[BP0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[BP:%.+]], {{.+}} 0, {{.+}} 0
+ // CK20: [[BPC:%.+]] = bitcast i8** [[BP0]] to [3 x [4 x [[STRUCT_ST]]]]**
+ // CK20: store [3 x [4 x [[STRUCT_ST]]]]* [[ARR]], [3 x [4 x [[STRUCT_ST]]]]** [[BPC]],
+ // CK20: [[P0:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* [[P:%.+]], {{.+}} 0, {{.+}} 0
+ // CK20: [[PC:%.+]] = bitcast i8** [[P0]] to [[STRUCT_ST]]**
+ // CK20: store [[STRUCT_ST]]* [[ARRAY_IDX_1]], [[STRUCT_ST]]** [[PC]],
+ // CK20: [[DIM_1:%.+]] = getelementptr inbounds [2 x [[STRUCT_DESCRIPTOR]]], [2 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]], {{.+}} 0, {{.+}} 0
+ // CK20: [[OFFSET:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_1]], {{.+}} 0, {{.+}} 0
+ // CK20: store i64 0, i64* [[OFFSET]],
+ // CK20: [[COUNT:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_1]], {{.+}} 0, {{.+}} 1
+ // CK20: store i64 2, i64* [[COUNT]],
+ // CK20: [[STRIDE:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_1]], {{.+}} 0, {{.+}} 2
+ // CK20: store i64 {{32|64}}, i64* [[STRIDE]],
+ // CK20: [[DIM_2:%.+]] = getelementptr inbounds [2 x [[STRUCT_DESCRIPTOR]]], [2 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]], {{.+}} 0, {{.+}} 1
+ // CK20: [[OFFSET_2:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_2]], {{.+}} 0, {{.+}} 0
+ // CK20: store i64 1, i64* [[OFFSET_2]],
+ // CK20: [[COUNT_2:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_2]], {{.+}} 0, {{.+}} 1
+ // CK20: store i64 4, i64* [[COUNT_2]],
+ // CK20: [[STRIDE_2:%.+]] = getelementptr inbounds [[STRUCT_DESCRIPTOR]], [[STRUCT_DESCRIPTOR]]* [[DIM_2]], {{.+}} 0, {{.+}} 2
+ // CK20: store i64 {{8|16}}, i64* [[STRIDE_2]],
+ // CK20-DAG: call void @__tgt_target_data_update(i64 -1, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MSIZE]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE]]{{.+}})
+ // CK20-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
+ // CK20-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+ // CK20-DAG: [[PC0:%.+]] = bitcast [2 x [[STRUCT_DESCRIPTOR]]]* [[DIMS]] to i8*
+ // CK20-DAG: [[PTRS:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %.offload_ptrs, i32 0, i32 0
+ // CK20-DAG: store i8* [[PC0]], i8** [[PTRS]],
+
+#pragma omp target update to(arr[0:2][1:4])
+ {++arg;}
+}
+
#endif
#endif
Index: clang/test/OpenMP/target_update_ast_print.cpp
===================================================================
--- clang/test/OpenMP/target_update_ast_print.cpp
+++ clang/test/OpenMP/target_update_ast_print.cpp
@@ -5,6 +5,14 @@
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -DOMP5 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s --check-prefix=OMP5
+// RUN: %clang_cc1 -DOMP5 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix=OMP5
+
+// RUN: %clang_cc1 -DOMP5 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s --check-prefix=OMP5
+// RUN: %clang_cc1 -DOMP5 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -DOMP5 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s --check-prefix=OMP5
// expected-no-diagnostics
#ifndef HEADER
@@ -20,23 +28,64 @@
#pragma omp target update to(([a][targ])p, a) if(l>5) device(l) nowait depend(inout:l)
#pragma omp target update from(b, ([a][targ])p) if(l<5) device(l-1) nowait depend(inout:l)
+
+#ifdef OMP5
+ U marr[10][10][10];
+#pragma omp target update to(marr[2][0:2][0:2])
+
+#pragma omp target update from(marr[2][0:2][0:2])
+
+#pragma omp target update to(marr[:][0:2][0:2])
+
+#pragma omp target update from(marr[:][0:2][0:2])
+
+#pragma omp target update to(marr[:][:l][l:])
+
+#pragma omp target update from(marr[:][:l][l:])
+
+#pragma omp target update to(marr[:2][:1][:])
+
+#pragma omp target update from(marr[:2][:1][:])
+
+#pragma omp target update to(marr[:2][:][:1])
+
+#pragma omp target update from(marr[:2][:][:1])
+
+#pragma omp target update to(marr[:2][:][1:])
+
+#pragma omp target update from(marr[:2][:][1:])
+
+#pragma omp target update to(marr[:1][3:2][:2])
+
+#pragma omp target update from(marr[:1][3:2][:2])
+
+#pragma omp target update to(marr[:1][:2][0])
+
+#pragma omp target update from(marr[:1][:2][0])
+
+// OMP5: marr[10][10][10];
+// OMP5-NEXT: #pragma omp target update to(marr[2][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update from(marr[2][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update to(marr[:][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update from(marr[:][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update to(marr[:][:l][l:])
+// OMP5-NEXT: #pragma omp target update from(marr[:][:l][l:])
+// OMP5-NEXT: #pragma omp target update to(marr[:2][:1][:])
+// OMP5-NEXT: #pragma omp target update from(marr[:2][:1][:])
+// OMP5-NEXT: #pragma omp target update to(marr[:2][:][:1])
+// OMP5-NEXT: #pragma omp target update from(marr[:2][:][:1])
+// OMP5-NEXT: #pragma omp target update to(marr[:2][:][1:])
+// OMP5-NEXT: #pragma omp target update from(marr[:2][:][1:])
+// OMP5-NEXT: #pragma omp target update to(marr[:1][3:2][:2])
+// OMP5-NEXT: #pragma omp target update from(marr[:1][3:2][:2])
+// OMP5-NEXT: #pragma omp target update to(marr[:1][:2][0])
+// OMP5-NEXT: #pragma omp target update from(marr[:1][:2][0])
+#endif
+
return a + targ + (T)b;
}
// CHECK: static T a, *p;
// CHECK-NEXT: U b;
-// CHECK-NEXT: int l;
-// CHECK-NEXT: #pragma omp target update to(([a][targ])p,a) if(l > 5) device(l) nowait depend(inout : l){{$}}
-// CHECK-NEXT: #pragma omp target update from(b,([a][targ])p) if(l < 5) device(l - 1) nowait depend(inout : l)
-// CHECK: static int a, *p;
-// CHECK-NEXT: float b;
-// CHECK-NEXT: int l;
-// CHECK-NEXT: #pragma omp target update to(([a][targ])p,a) if(l > 5) device(l) nowait depend(inout : l)
-// CHECK-NEXT: #pragma omp target update from(b,([a][targ])p) if(l < 5) device(l - 1) nowait depend(inout : l)
-// CHECK: static char a, *p;
-// CHECK-NEXT: float b;
-// CHECK-NEXT: int l;
-// CHECK-NEXT: #pragma omp target update to(([a][targ])p,a) if(l > 5) device(l) nowait depend(inout : l)
-// CHECK-NEXT: #pragma omp target update from(b,([a][targ])p) if(l < 5) device(l - 1) nowait depend(inout : l)
int main(int argc, char **argv) {
static int a;
@@ -50,6 +99,40 @@
// CHECK-NEXT: #pragma omp target update to(a) if(f > 0.) device(n) nowait depend(in : n)
#pragma omp target update from(f) if(f<0.0) device(n+1) nowait depend(in:n)
// CHECK-NEXT: #pragma omp target update from(f) if(f < 0.) device(n + 1) nowait depend(in : n)
+
+#ifdef OMP5
+ float marr[10][10][10];
+// OMP5: marr[10][10][10];
+#pragma omp target update to(marr[2][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update to(marr[2][0:2][0:2])
+#pragma omp target update from(marr[2][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update from(marr[2][0:2][0:2])
+#pragma omp target update to(marr[:][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update to(marr[:][0:2][0:2])
+#pragma omp target update from(marr[:][0:2][0:2])
+// OMP5-NEXT: #pragma omp target update from(marr[:][0:2][0:2])
+#pragma omp target update to(marr[:][:n][n:])
+// OMP5: #pragma omp target update to(marr[:][:n][n:])
+#pragma omp target update from(marr[:2][:1][:])
+// OMP5-NEXT: #pragma omp target update from(marr[:2][:1][:])
+#pragma omp target update to(marr[:2][:][:1])
+// OMP5-NEXT: #pragma omp target update to(marr[:2][:][:1])
+#pragma omp target update from(marr[:2][:][:1])
+// OMP5-NEXT: #pragma omp target update from(marr[:2][:][:1])
+#pragma omp target update to(marr[:2][:][1:])
+// OMP5-NEXT: #pragma omp target update to(marr[:2][:][1:])
+#pragma omp target update from(marr[:2][:][1:])
+// OMP5-NEXT: #pragma omp target update from(marr[:2][:][1:])
+#pragma omp target update to(marr[:1][3:2][:2])
+// OMP5-NEXT: #pragma omp target update to(marr[:1][3:2][:2])
+#pragma omp target update from(marr[:1][3:2][:2])
+// OMP5-NEXT: #pragma omp target update from(marr[:1][3:2][:2])
+#pragma omp target update to(marr[:1][:2][0])
+// OMP5-NEXT: #pragma omp target update to(marr[:1][:2][0])
+#pragma omp target update from(marr[:1][:2][0])
+// OMP5-NEXT: #pragma omp target update from(marr[:1][:2][0])
+#endif
+
return foo(argc, f) + foo(argv[0][0], f) + a;
}
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -6511,6 +6511,8 @@
Record.AddStmt(M.getAssociatedExpression());
Record.AddDeclRef(M.getAssociatedDeclaration());
}
+ for (auto NC : C->non_contiguous_lists())
+ Record.push_back(NC);
}
void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {
@@ -6535,6 +6537,8 @@
Record.AddStmt(M.getAssociatedExpression());
Record.AddDeclRef(M.getAssociatedDeclaration());
}
+ for (auto NC : C->non_contiguous_lists())
+ Record.push_back(NC);
}
void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -12513,6 +12513,13 @@
AssociatedExpr, AssociatedDecl));
}
C->setComponents(Components, ListSizes);
+
+ SmallVector<bool, 16> ListNonContiguous;
+ ListNonContiguous.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i) {
+ ListNonContiguous.push_back(Record.readBool());
+ }
+ C->setNonContiguousLists(ListNonContiguous);
}
void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
@@ -12563,6 +12570,13 @@
AssociatedExpr, AssociatedDecl));
}
C->setComponents(Components, ListSizes);
+
+ SmallVector<bool, 16> ListNonContiguous;
+ ListNonContiguous.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i) {
+ ListNonContiguous.push_back(Record.readBool());
+ }
+ C->setNonContiguousLists(ListNonContiguous);
}
void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -47,7 +47,8 @@
static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
- OpenMPClauseKind CKind, bool NoDiagnose);
+ bool &IsNonContiguous, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
+ bool NoDiagnose);
namespace {
/// Default data sharing attributes, which can be applied to directive.
@@ -3395,7 +3396,10 @@
}
if (isOpenMPTargetExecutionDirective(DKind)) {
OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
- if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
+ bool IsNonContiguous = false;
+ if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents,
+ IsNonContiguous, OMPC_map,
+ Stack->getCurrentDirective(),
/*NoDiagnose=*/true))
return;
const auto *VD = cast<ValueDecl>(
@@ -16142,7 +16146,9 @@
class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
Sema &SemaRef;
OpenMPClauseKind CKind = OMPC_unknown;
+ OpenMPDirectiveKind DKind = OMPD_unknown;
OMPClauseMappableExprCommon::MappableExprComponentList &Components;
+ bool &IsNonContiguousRef;
bool NoDiagnose = false;
const Expr *RelevantExpr = nullptr;
bool AllowUnitySizeArraySection = true;
@@ -16320,6 +16326,9 @@
// pointer. Otherwise, only unitary sections are accepted.
if (NotWhole || IsPointer)
AllowWholeSizeArraySection = false;
+ } else if (DKind == OMPD_target_update &&
+ SemaRef.getLangOpts().OpenMP >= 50) {
+ IsNonContiguousRef = true;
} else if (AllowUnitySizeArraySection && NotUnity) {
// A unity or whole array section is not allowed and that is not
// compatible with the properties of the current array section.
@@ -16412,11 +16421,13 @@
return RelevantExpr;
}
explicit MapBaseChecker(
- Sema &SemaRef, OpenMPClauseKind CKind,
+ Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
OMPClauseMappableExprCommon::MappableExprComponentList &Components,
- bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
- : SemaRef(SemaRef), CKind(CKind), Components(Components),
- NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
+ bool &IsNonContiguousTargetUpdate, bool NoDiagnose, SourceLocation &ELoc,
+ SourceRange &ERange)
+ : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
+ IsNonContiguousRef(IsNonContiguousTargetUpdate), NoDiagnose(NoDiagnose),
+ ELoc(ELoc), ERange(ERange) {}
};
} // namespace
@@ -16427,11 +16438,12 @@
static const Expr *checkMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
- OpenMPClauseKind CKind, bool NoDiagnose) {
+ bool &IsNonContiguousTargetUpdate, OpenMPClauseKind CKind,
+ OpenMPDirectiveKind DKind, bool NoDiagnose) {
SourceLocation ELoc = E->getExprLoc();
SourceRange ERange = E->getSourceRange();
- MapBaseChecker Checker(SemaRef, CKind, CurComponents, NoDiagnose, ELoc,
- ERange);
+ MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents,
+ IsNonContiguousTargetUpdate, NoDiagnose, ELoc, ERange);
if (Checker.Visit(E->IgnoreParens()))
return Checker.getFoundBase();
return nullptr;
@@ -16809,6 +16821,8 @@
SmallVector<ValueDecl *, 16> VarBaseDeclarations;
// The reference to the user-defined mapper associated with every expression.
SmallVector<Expr *, 16> UDMapperList;
+ // The list of whether the expression is non-contiguous or not
+ SmallVector<bool, 16> IsNonContiguousList;
MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
// We have a list of components and base declarations for each entry in the
@@ -16905,12 +16919,15 @@
}
OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
+ bool IsNonContiguousTargetUpdate = false;
ValueDecl *CurDeclaration = nullptr;
// Obtain the array or member expression bases if required. Also, fill the
// components array with all the components identified in the process.
const Expr *BE = checkMapClauseExpressionBase(
- SemaRef, SimpleExpr, CurComponents, CKind, /*NoDiagnose=*/false);
+ SemaRef, SimpleExpr, CurComponents, IsNonContiguousTargetUpdate, CKind,
+ DSAS->getCurrentDirective(),
+ /*NoDiagnose=*/false);
if (!BE)
continue;
@@ -16933,6 +16950,7 @@
MVLI.VarComponents.back().append(CurComponents.begin(),
CurComponents.end());
MVLI.VarBaseDeclarations.push_back(nullptr);
+ MVLI.IsNonContiguousList.push_back(IsNonContiguousTargetUpdate);
continue;
}
@@ -17110,6 +17128,7 @@
CurComponents.end());
MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
: CurDeclaration);
+ MVLI.IsNonContiguousList.push_back(IsNonContiguousTargetUpdate);
}
}
@@ -17147,11 +17166,11 @@
// We need to produce a map clause even if we don't have variables so that
// other diagnostics related with non-existing map clauses are accurate.
- return OMPMapClause::Create(Context, Locs, MVLI.ProcessedVarList,
- MVLI.VarBaseDeclarations, MVLI.VarComponents,
- MVLI.UDMapperList, Modifiers, ModifiersLoc,
- MapperIdScopeSpec.getWithLocInContext(Context),
- MapperId, MapType, IsMapTypeImplicit, MapLoc);
+ return OMPMapClause::Create(
+ Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
+ MVLI.VarComponents, MVLI.IsNonContiguousList, MVLI.UDMapperList,
+ Modifiers, ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context),
+ MapperId, MapType, IsMapTypeImplicit, MapLoc);
}
QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
@@ -18063,7 +18082,7 @@
return OMPToClause::Create(
Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
- MVLI.VarComponents, MVLI.UDMapperList,
+ MVLI.VarComponents, MVLI.IsNonContiguousList, MVLI.UDMapperList,
MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
}
@@ -18080,7 +18099,7 @@
return OMPFromClause::Create(
Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
- MVLI.VarComponents, MVLI.UDMapperList,
+ MVLI.VarComponents, MVLI.IsNonContiguousList, MVLI.UDMapperList,
MapperIdScopeSpec.getWithLocInContext(Context), MapperId);
}
Index: clang/lib/CodeGen/CGOpenMPRuntime.h
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.h
+++ clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -1577,6 +1577,10 @@
llvm::Value *SizesArray = nullptr;
/// The array of map types passed to the runtime library.
llvm::Value *MapTypesArray = nullptr;
+ /// The array of array of dims passed to the runtime library.
+ llvm::Value *DimsArray = nullptr;
+ /// The array of array of descriptor passed to the runtime library.
+ llvm::Value *DescriptorsArray = nullptr;
/// The total number of pointers passed to the runtime library.
unsigned NumberOfPtrs = 0u;
/// Map between the a declaration of a capture and the corresponding base
@@ -1592,6 +1596,8 @@
PointersArray = nullptr;
SizesArray = nullptr;
MapTypesArray = nullptr;
+ DimsArray = nullptr;
+ DescriptorsArray = nullptr;
NumberOfPtrs = 0u;
}
/// Return true if the current target data information has valid arrays.
Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7643,6 +7643,10 @@
/// Close is a hint to the runtime to allocate memory close to
/// the target device.
OMP_MAP_CLOSE = 0x400,
+ /// Signal that the runtime library should use args as an array of
+ /// descriptor_dim pointers and use args_size as dims. Used when we have
+ /// non-contiguous list items in target update directive
+ OMP_MAP_DESCRIPTOR = 0x800,
/// The 16 MSBs of the flags indicate whether the entry is member of some
/// struct/class.
OMP_MAP_MEMBER_OF = 0xffff000000000000,
@@ -7678,6 +7682,8 @@
using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
+ using MapDimArrayTy = SmallVector<uint64_t, 4>;
+ using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>;
/// Map between a struct and the its lowest & highest elements which have been
/// mapped.
@@ -7699,15 +7705,17 @@
ArrayRef<OpenMPMapModifierKind> MapModifiers;
bool ReturnDevicePointer = false;
bool IsImplicit = false;
+ bool IsNonContiguous = false;
MapInfo() = default;
MapInfo(
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPMapClauseKind MapType,
- ArrayRef<OpenMPMapModifierKind> MapModifiers,
- bool ReturnDevicePointer, bool IsImplicit)
+ ArrayRef<OpenMPMapModifierKind> MapModifiers, bool ReturnDevicePointer,
+ bool IsImplicit, bool IsNonContiguous)
: Components(Components), MapType(MapType), MapModifiers(MapModifiers),
- ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
+ ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
+ IsNonContiguous(IsNonContiguous) {}
};
/// If use_device_ptr is used on a pointer which is a struct member and there
@@ -7821,9 +7829,11 @@
/// a flag marking the map as a pointer if requested. Add a flag marking the
/// map as the first one of a series of maps that relate to the same map
/// expression.
- OpenMPOffloadMappingFlags getMapTypeBits(
- OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
- bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
+ OpenMPOffloadMappingFlags
+ getMapTypeBits(OpenMPMapClauseKind MapType,
+ ArrayRef<OpenMPMapModifierKind> MapModifiers, bool IsImplicit,
+ bool AddPtrFlag, bool AddIsTargetParamFlag,
+ bool IsNonContiguous) const {
OpenMPOffloadMappingFlags Bits =
IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
switch (MapType) {
@@ -7859,6 +7869,8 @@
if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
!= MapModifiers.end())
Bits |= OMP_MAP_CLOSE;
+ if (IsNonContiguous)
+ Bits |= OMP_MAP_DESCRIPTOR;
return Bits;
}
@@ -7910,11 +7922,11 @@
ArrayRef<OpenMPMapModifierKind> MapModifiers,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
- MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
+ MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, MapDimArrayTy &Dims,
StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
bool IsImplicit,
ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
- OverlappedElements = llvm::None) const {
+ OverlappedElements = llvm::None, bool IsNonContiguous = false) const {
// The following summarizes what has to be generated for each map and the
// types below. The generated information is expressed in this order:
// base pointer, section pointer, size, flags
@@ -8161,6 +8173,9 @@
// whether we are dealing with a member of a declared struct.
const MemberExpr *EncounteredME = nullptr;
+ // Track for the total number of dimension.
+ uint64_t DimSize = 0;
+
for (; I != CE; ++I) {
// If the current component is member of a struct (parent struct) mark it.
if (!EncounteredME) {
@@ -8179,8 +8194,11 @@
// becomes the base address for the following components.
// A final array section, is one whose length can't be proved to be one.
+ // If the map item is non-contiguous then we don't treat any array section
+ // as final array section.
bool IsFinalArraySection =
- isFinalArraySectionExpression(I->getAssociatedExpression());
+ isFinalArraySectionExpression(I->getAssociatedExpression()) &&
+ (!IsNonContiguous);
// Get information on whether the element is a pointer. Have to do a
// special treatment for array sections given that they are built-in
@@ -8199,6 +8217,11 @@
I->getAssociatedExpression()->getType()->isAnyPointerType();
bool IsNonDerefPointer = IsPointer && !UO && !BO;
+ if (OASE || OAShE ||
+ dyn_cast<ArraySubscriptExpr>(I->getAssociatedExpression())) {
+ DimSize++;
+ }
+
if (Next == CE || IsNonDerefPointer || IsFinalArraySection) {
// If this is not the last component, we expect the pointer to be
// associated with an array expression or member expression.
@@ -8253,7 +8276,8 @@
OMP_MAP_MEMBER_OF |
getMapTypeBits(MapType, MapModifiers, IsImplicit,
/*AddPtrFlag=*/false,
- /*AddIsTargetParamFlag=*/false);
+ /*AddIsTargetParamFlag=*/false,
+ /*IsNonContiguous=*/IsNonContiguous);
LB = BP;
llvm::Value *Size = nullptr;
// Do bitcopy of all non-overlapped structure elements.
@@ -8277,6 +8301,7 @@
Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
/*isSigned=*/true));
Types.push_back(Flags);
+ Dims.push_back(IsNonContiguous ? DimSize : 0);
LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
}
BasePointers.push_back(BP.getPointer());
@@ -8288,6 +8313,7 @@
Sizes.push_back(
CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Types.push_back(Flags);
+ Dims.push_back(IsNonContiguous ? DimSize : 0);
break;
}
llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
@@ -8296,15 +8322,17 @@
Pointers.push_back(LB.getPointer());
Sizes.push_back(
CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
+ Dims.push_back(IsNonContiguous ? DimSize : 0);
// We need to add a pointer flag for each map that comes from the
// same expression except for the first one. We also need to signal
// this map is the first one that relates with the current capture
// (there is a set of entries for each capture).
- OpenMPOffloadMappingFlags Flags = getMapTypeBits(
- MapType, MapModifiers, IsImplicit,
- !IsExpressionFirstInfo || RequiresReference,
- IsCaptureFirstInfo && !RequiresReference);
+ OpenMPOffloadMappingFlags Flags =
+ getMapTypeBits(MapType, MapModifiers, IsImplicit,
+ !IsExpressionFirstInfo || RequiresReference,
+ IsCaptureFirstInfo && !RequiresReference,
+ /*IsNonContiguous=*/IsNonContiguous);
if (!IsExpressionFirstInfo) {
// If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
@@ -8359,6 +8387,154 @@
}
}
+ /// Generate the base pointers, section pointers, sizes , map type bits,
+ /// dimension size, offset, count, and strides for the provided map type, map
+ /// modifier, and expression components. \a IsFirstComponent should be set to
+ /// true if the provided set of components is the first associated with a
+ /// capture.
+ void generateInfoForTargetDataComponentList(
+ OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
+ MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
+ MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, MapDimArrayTy &Dims,
+ MapNonContiguousArrayTy &Offsets, MapNonContiguousArrayTy &Counts,
+ MapNonContiguousArrayTy &Strides, StructRangeInfoTy &PartialStruct,
+ bool IsFirstComponentList, bool IsImplicit,
+ ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
+ OverlappedElements = llvm::None) const {
+
+ generateInfoForComponentList(MapType, MapModifiers, Components,
+ BasePointers, Pointers, Sizes, Types, Dims,
+ PartialStruct, IsFirstComponentList,
+ IsImplicit, OverlappedElements, true);
+
+ const ASTContext &Context = CGF.getContext();
+
+ MapValuesArrayTy CurOffsets;
+ MapValuesArrayTy CurCounts;
+ MapValuesArrayTy CurStrides;
+ llvm::Value *CurStride = nullptr;
+
+ // Collect Size information for each dimension and get the element size as
+ // the first Stride. For example, for `int arr[10][10]`, the DimSizes
+ // should be [10, 10] and the first stride is 4 btyes.
+ SmallVector<llvm::Value *, 4> DimSizes;
+ for (const auto &Component : Components) {
+ const Expr *AssocExpr = Component.getAssociatedExpression();
+ const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
+ if (AE || OASE) {
+ QualType Ty;
+ if (OASE)
+ Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ else
+ Ty = AE->getType();
+ auto *CAT = Context.getAsConstantArrayType(Ty);
+ auto *VAT = Context.getAsVariableArrayType(Ty);
+ // Get element size if we CurStrides is empty.
+ if (CurStrides.empty()) {
+ const Type *ElementType = nullptr;
+ uint64_t ElementTypeSize;
+ if (CAT) {
+ ElementType = CAT->getElementType().getTypePtr();
+ ElementTypeSize =
+ Context.getTypeSizeInChars(ElementType).getQuantity();
+ } else {
+ assert(VAT && "Should be either ConstantArray or VariableArray");
+ ElementType = VAT->getElementType().getTypePtr();
+ ElementTypeSize =
+ Context.getTypeSizeInChars(ElementType).getQuantity();
+ }
+ CurStrides.push_back(
+ llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize));
+ }
+ // Get dimension value.
+ llvm::Value *SizeV = nullptr;
+ if (CAT) {
+ llvm::APInt Size = CAT->getSize();
+ SizeV = llvm::ConstantInt::get(CGF.SizeTy, Size);
+ } else {
+ assert(VAT && "Should be either ConstantArray or VariableArray");
+ const Expr *Size = VAT->getSizeExpr();
+ SizeV = CGF.EmitScalarExpr(Size);
+ }
+ SizeV = CGF.Builder.CreateIntCast(SizeV, CGF.Int64Ty,
+ /*IsSigned=*/false);
+ DimSizes.push_back(SizeV);
+ }
+ }
+
+ // Scan the components from the base to the complete expression.
+ auto CI = Components.begin();
+ auto CE = Components.end();
+ auto I = CI;
+ auto DI = DimSizes.begin();
+
+ // Collect info for non-contiguous. Notice that offset, count, and stride
+ // are only meaningful for array-section, so we insert a null for anything
+ // other than array-section.
+ // Also, the size of offset, count, and stride are not the same as pointers,
+ // base_pointers, sizes, or dims. Instead, the size of offset, count, and
+ // stride are the same as the number of non-contiguous declaration in target
+ // update to/from clause.
+ for (; I != CE; ++I) {
+ const Expr *AssocExpr = I->getAssociatedExpression();
+ const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
+
+ if (OASE || AE) {
+ // Offset
+ const Expr *OffsetExpr = nullptr;
+ if (OASE)
+ OffsetExpr = OASE->getLowerBound();
+ else
+ OffsetExpr = AE->getIdx();
+ llvm::Value *Offset = nullptr;
+ if (!OffsetExpr) {
+ // If offset is absent, then we just set it to zero.
+ Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0);
+ } else {
+ Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr),
+ CGF.Int64Ty,
+ /*isSigned=*/false);
+ }
+ CurOffsets.push_back(Offset);
+ // Count
+ const Expr *CountExpr = nullptr;
+ if (OASE)
+ CountExpr = OASE->getLength();
+ llvm::Value *Count = nullptr;
+ if (!CountExpr) {
+ // If length is absent then we calculate it as (Total length -
+ // lower_bound)
+ Count = CGF.Builder.CreateNUWSub(*DI, Offset);
+ } else {
+ Count = CGF.EmitScalarExpr(CountExpr);
+ }
+ Count =
+ CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false);
+ CurCounts.push_back(Count);
+ // Stride = previous stride * previous dimension size
+ // Take `int arr[5][10]` and `arr[0:2][0:2]` as an example:
+ // Dimension 1 Dimension 0
+ // Offset 0 0
+ // Count 2 2
+ // Stride 40 bytes (4x10) 4 bytes (int)
+ if (DI != DimSizes.begin()) {
+ CurStride =
+ CGF.Builder.CreateNUWMul(CurStrides.back(), *std::prev(DI, 1));
+ CurStrides.push_back(CurStride);
+ }
+
+ DI++;
+ }
+ }
+
+ Offsets.push_back(CurOffsets);
+ Counts.push_back(CurCounts);
+ Strides.push_back(CurStrides);
+ }
+
/// Return the adjusted map modifiers if the declaration a capture refers to
/// appears in a first-private clause. This is expected to be used only with
/// directives that start with 'target'.
@@ -8524,7 +8700,10 @@
/// index where it occurs is appended to the device pointers info array.
void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
- MapFlagsArrayTy &Types) const {
+ MapFlagsArrayTy &Types, MapDimArrayTy &Dims,
+ MapNonContiguousArrayTy &Offsets,
+ MapNonContiguousArrayTy &Counts,
+ MapNonContiguousArrayTy &Strides) const {
// We have to process the component lists that relate with the same
// declaration in a single chunk so that we can generate the map flags
// correctly. Therefore, we organize all lists in a map.
@@ -8537,11 +8716,12 @@
OMPClauseMappableExprCommon::MappableExprComponentListRef L,
OpenMPMapClauseKind MapType,
ArrayRef<OpenMPMapModifierKind> MapModifiers,
- bool ReturnDevicePointer, bool IsImplicit) {
+ bool ReturnDevicePointer, bool IsImplicit,
+ bool IsNonContiguous) {
const ValueDecl *VD =
D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
- IsImplicit);
+ IsImplicit, IsNonContiguous);
};
assert(CurDir.is<const OMPExecutableDirective *>() &&
@@ -8550,18 +8730,27 @@
for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
for (const auto L : C->component_lists()) {
InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
- /*ReturnDevicePointer=*/false, C->isImplicit());
+ /*ReturnDevicePointer=*/false, C->isImplicit(),
+ /*IsNonContiguous=*/false);
}
- for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
- for (const auto L : C->component_lists()) {
- InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
- /*ReturnDevicePointer=*/false, C->isImplicit());
+ for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) {
+ auto CI = C->component_lists_begin();
+ auto CE = C->component_lists_end();
+ auto NI = C->non_contiguous_list_begin();
+ for (; CI != CE; ++CI, ++NI) {
+ InfoGen((*CI).first, (*CI).second, OMPC_MAP_to, llvm::None,
+ /*ReturnDevicePointer=*/false, C->isImplicit(), *NI);
}
- for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
- for (const auto L : C->component_lists()) {
- InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
- /*ReturnDevicePointer=*/false, C->isImplicit());
+ }
+ for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) {
+ auto CI = C->component_lists_begin();
+ auto CE = C->component_lists_end();
+ auto NI = C->non_contiguous_list_begin();
+ for (; CI != CE; ++CI, ++NI) {
+ InfoGen((*CI).first, (*CI).second, OMPC_MAP_from, llvm::None,
+ /*ReturnDevicePointer=*/false, C->isImplicit(), *NI);
}
+ }
// Look at the use_device_ptr clause information and mark the existing map
// entries as such. If there is no map information for an entry in the
@@ -8588,7 +8777,8 @@
// Look for the first set of components that refer to it.
if (It != Info.end()) {
auto CI = std::find_if(
- It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
+ It->second.begin(), It->second.end(),
+ [VD](const MapInfo &MI) {
return MI.Components.back().getAssociatedDeclaration() == VD;
});
// If we found a map entry, signal that the pointer has to be returned
@@ -8611,7 +8801,8 @@
// the pointer into account for the calculation of the range of the
// partial struct.
InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
- /*ReturnDevicePointer=*/false, C->isImplicit());
+ /*ReturnDevicePointer=*/false, C->isImplicit(),
+ /*IsNonContiguous=*/false);
DeferredInfo[nullptr].emplace_back(IE, VD);
} else {
llvm::Value *Ptr =
@@ -8634,6 +8825,10 @@
MapValuesArrayTy CurPointers;
MapValuesArrayTy CurSizes;
MapFlagsArrayTy CurTypes;
+ MapDimArrayTy CurDims;
+ MapNonContiguousArrayTy CurOffsets;
+ MapNonContiguousArrayTy CurCounts;
+ MapNonContiguousArrayTy CurStrides;
StructRangeInfoTy PartialStruct;
for (const MapInfo &L : M.second) {
@@ -8642,10 +8837,18 @@
// Remember the current base pointer index.
unsigned CurrentBasePointersIdx = CurBasePointers.size();
- generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
- CurBasePointers, CurPointers, CurSizes,
- CurTypes, PartialStruct,
- IsFirstComponentList, L.IsImplicit);
+ if (L.IsNonContiguous) {
+ generateInfoForTargetDataComponentList(
+ L.MapType, L.MapModifiers, L.Components, CurBasePointers,
+ CurPointers, CurSizes, CurTypes, CurDims, CurOffsets, CurCounts,
+ CurStrides, PartialStruct, IsFirstComponentList, L.IsImplicit);
+ } else {
+ // Indicate that we do not do the special non-contiguous codegen
+ generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
+ CurBasePointers, CurPointers, CurSizes,
+ CurTypes, CurDims, PartialStruct,
+ IsFirstComponentList, L.IsImplicit);
+ }
// If this entry relates with a device pointer, set the relevant
// declaration and add the 'return pointer' flag.
@@ -8685,15 +8888,24 @@
// If there is an entry in PartialStruct it means we have a struct with
// individual members mapped. Emit an extra combined entry.
- if (PartialStruct.Base.isValid())
+ if (PartialStruct.Base.isValid()) {
+ // Make sure Dims have the same size as BP, P, Sizes, and Types.
+ // Put 0 here to make sure that `emitTargetDataOffloadingArrays` use it
+ // to skip this one.
+ CurDims.push_back(0);
emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
PartialStruct);
+ }
// We need to append the results of this capture to what we already have.
BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
Pointers.append(CurPointers.begin(), CurPointers.end());
Sizes.append(CurSizes.begin(), CurSizes.end());
Types.append(CurTypes.begin(), CurTypes.end());
+ Dims.append(CurDims.begin(), CurDims.end());
+ Offsets.append(CurOffsets.begin(), CurOffsets.end());
+ Counts.append(CurCounts.begin(), CurCounts.end());
+ Strides.append(CurStrides.begin(), CurStrides.end());
}
}
@@ -8722,7 +8934,7 @@
const ValueDecl *VD =
D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
- IsImplicit);
+ IsImplicit, /*IsNonContiguous=*/false);
};
for (const auto *C : CurMapperDir->clauselists()) {
@@ -8743,6 +8955,7 @@
MapValuesArrayTy CurPointers;
MapValuesArrayTy CurSizes;
MapFlagsArrayTy CurTypes;
+ MapDimArrayTy CurDims;
StructRangeInfoTy PartialStruct;
for (const MapInfo &L : M.second) {
@@ -8750,7 +8963,7 @@
"Not expecting declaration with no component lists.");
generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
CurBasePointers, CurPointers, CurSizes,
- CurTypes, PartialStruct,
+ CurTypes, CurDims, PartialStruct,
IsFirstComponentList, L.IsImplicit);
IsFirstComponentList = false;
}
@@ -8869,6 +9082,7 @@
MapBaseValuesArrayTy &BasePointers,
MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
+ MapDimArrayTy &Dims,
StructRangeInfoTy &PartialStruct) const {
assert(!Cap->capturesVariableArrayType() &&
"Not expecting to generate map info for a variable array type!");
@@ -9018,7 +9232,7 @@
OverlappedComponents = Pair.getSecond();
bool IsFirstComponentList = true;
generateInfoForComponentList(MapType, MapModifiers, Components,
- BasePointers, Pointers, Sizes, Types,
+ BasePointers, Pointers, Sizes, Types, Dims,
PartialStruct, IsFirstComponentList,
IsImplicit, OverlappedComponents);
}
@@ -9032,10 +9246,9 @@
std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
auto It = OverlappedData.find(&L);
if (It == OverlappedData.end())
- generateInfoForComponentList(MapType, MapModifiers, Components,
- BasePointers, Pointers, Sizes, Types,
- PartialStruct, IsFirstComponentList,
- IsImplicit);
+ generateInfoForComponentList(
+ MapType, MapModifiers, Components, BasePointers, Pointers, Sizes,
+ Types, Dims, PartialStruct, IsFirstComponentList, IsImplicit);
IsFirstComponentList = false;
}
}
@@ -9045,7 +9258,8 @@
void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes,
- MapFlagsArrayTy &Types) const {
+ MapFlagsArrayTy &Types,
+ MapDimArrayTy &Dims) const {
assert(CurDir.is<const OMPExecutableDirective *>() &&
"Expect a executable directive");
const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
@@ -9066,7 +9280,7 @@
StructRangeInfoTy PartialStruct;
generateInfoForComponentList(
C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
- Pointers, Sizes, Types, PartialStruct,
+ Pointers, Sizes, Types, Dims, PartialStruct,
/*IsFirstComponentList=*/true, C->isImplicit());
assert(!PartialStruct.Base.isValid() &&
"No partial structs for declare target link expected.");
@@ -9160,16 +9374,15 @@
};
} // anonymous namespace
-/// Emit the arrays used to pass the captures and map information to the
-/// offloading runtime library. If there is no map or capture information,
-/// return nullptr by reference.
static void
emitOffloadingArrays(CodeGenFunction &CGF,
MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
MappableExprsHandler::MapValuesArrayTy &Pointers,
MappableExprsHandler::MapValuesArrayTy &Sizes,
MappableExprsHandler::MapFlagsArrayTy &MapTypes,
- CGOpenMPRuntime::TargetDataInfo &Info) {
+ MappableExprsHandler::MapDimArrayTy &Dims,
+ CGOpenMPRuntime::TargetDataInfo &Info,
+ bool IsNonContiguous = false) {
CodeGenModule &CGM = CGF.CGM;
ASTContext &Ctx = CGF.getContext();
@@ -9212,8 +9425,14 @@
// We expect all the sizes to be constant, so we collect them to create
// a constant array.
SmallVector<llvm::Constant *, 16> ConstSizes;
- for (llvm::Value *S : Sizes)
- ConstSizes.push_back(cast<llvm::Constant>(S));
+ for (unsigned I = 0, E = Sizes.size(); I < E; ++I) {
+ if (IsNonContiguous &&
+ (MapTypes[I] & MappableExprsHandler::OMP_MAP_DESCRIPTOR)) {
+ ConstSizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, Dims[I]));
+ } else {
+ ConstSizes.push_back(cast<llvm::Constant>(Sizes[I]));
+ }
+ }
auto *SizesArrayInit = llvm::ConstantArray::get(
llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
@@ -9279,6 +9498,87 @@
}
}
+/// Emit the arrays used to pass the captures and map information to the
+/// offloading runtime library. If there is no map or capture information,
+/// return nullptr by reference.
+static void
+emitTargetDataOffloadingArrays(CodeGenFunction &CGF,
+ MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
+ MappableExprsHandler::MapValuesArrayTy &Pointers,
+ MappableExprsHandler::MapValuesArrayTy &Sizes,
+ MappableExprsHandler::MapFlagsArrayTy &MapTypes,
+ MappableExprsHandler::MapDimArrayTy &Dims,
+ MappableExprsHandler::MapNonContiguousArrayTy &Offsets,
+ MappableExprsHandler::MapNonContiguousArrayTy &Counts,
+ MappableExprsHandler::MapNonContiguousArrayTy &Strides,
+ CGOpenMPRuntime::TargetDataInfo &Info) {
+ emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Dims, Info,
+ true);
+
+ if (Offsets.empty()) return;
+
+ ASTContext &C = CGF.getContext();
+ CodeGenModule &CGM = CGF.CGM;
+
+ // Build an array of struct descriptor_dim and then assign it to offload_args.
+ if (Info.NumberOfPtrs) {
+ // Build struct descriptor_dim {
+ // int64_t offset;
+ // int64_t count;
+ // int64_t stride
+ // };
+ QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
+ RecordDecl *RD;
+ RD = C.buildImplicitRecord("descriptor_dim");
+ RD->startDefinition();
+ addFieldToRecordDecl(C, RD, Int64Ty);
+ addFieldToRecordDecl(C, RD, Int64Ty);
+ addFieldToRecordDecl(C, RD, Int64Ty);
+ RD->completeDefinition();
+ QualType DimTy = C.getRecordType(RD);
+
+ enum { OffsetFD = 0, CountFD, StrideFD };
+ // The reason we need two index variable here is because the size of "Dims"
+ // is the same as the size of Components, however, the size of offset, count
+ // , and stride is equal to the size of base declaration that is
+ // non-contiguous.
+ for (unsigned I = 0, L = 0, E = Info.NumberOfPtrs; I < E; ++I) {
+ if (Dims[I] == 0)
+ continue;
+ llvm::APInt Size(/*numBits=*/32, Dims[I]);
+ QualType ArrayTy =
+ C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0);
+ Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
+ for (unsigned II = 0, EE = Dims[I]; II < EE; ++II) {
+ unsigned RevIdx = EE - II - 1;
+ LValue DimsLVal = CGF.MakeAddrLValue(
+ CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy);
+ // Offset
+ LValue OffsetLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), OffsetFD));
+ CGF.EmitStoreOfScalar(Offsets[L][RevIdx], OffsetLVal);
+ // Count
+ LValue CountLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), CountFD));
+ CGF.EmitStoreOfScalar(Counts[L][RevIdx], CountLVal);
+ // Stride
+ LValue StrideLVal = CGF.EmitLValueForField(
+ DimsLVal, *std::next(RD->field_begin(), StrideFD));
+ CGF.EmitStoreOfScalar(Strides[L][RevIdx], StrideLVal);
+ }
+ // args[I] = &dims
+ Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ DimsAddr, CGM.Int8PtrTy);
+ llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
+ llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
+ Info.PointersArray, 0, I);
+ Address PAddr(P, C.getTypeAlignInChars(C.VoidPtrTy));
+ CGF.Builder.CreateStore(DAddr.getPointer(), PAddr);
+ ++L;
+ }
+ }
+}
+
/// Emit the arguments to be passed to the runtime library based on the
/// arrays of pointers, sizes and map types.
static void emitOffloadingArraysArgument(
@@ -9952,6 +10252,7 @@
MappableExprsHandler::MapValuesArrayTy Pointers;
MappableExprsHandler::MapValuesArrayTy Sizes;
MappableExprsHandler::MapFlagsArrayTy MapTypes;
+ MappableExprsHandler::MapDimArrayTy Dims;
// Get mappable expression information.
MappableExprsHandler MEHandler(D, CGF);
@@ -9966,6 +10267,7 @@
MappableExprsHandler::MapValuesArrayTy CurPointers;
MappableExprsHandler::MapValuesArrayTy CurSizes;
MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
+ MappableExprsHandler::MapDimArrayTy CurDims;
MappableExprsHandler::StructRangeInfoTy PartialStruct;
// VLA sizes are passed to the outlined region by copy and do not have map
@@ -9983,7 +10285,8 @@
// If we have any information in the map clause, we use it, otherwise we
// just do a default mapping.
MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
- CurSizes, CurMapTypes, PartialStruct);
+ CurSizes, CurMapTypes, CurDims,
+ PartialStruct);
if (CurBasePointers.empty())
MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
CurPointers, CurSizes, CurMapTypes);
@@ -10020,11 +10323,12 @@
// Map other list items in the map clause which are not captured variables
// but "declare target link" global variables.
MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
- MapTypes);
+ MapTypes, Dims);
TargetDataInfo Info;
// Fill up the arrays and create the arguments.
- emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
+ emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Dims,
+ Info);
emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
Info.PointersArray, Info.SizesArray,
Info.MapTypesArray, Info);
@@ -10621,13 +10925,19 @@
MappableExprsHandler::MapValuesArrayTy Pointers;
MappableExprsHandler::MapValuesArrayTy Sizes;
MappableExprsHandler::MapFlagsArrayTy MapTypes;
+ MappableExprsHandler::MapDimArrayTy Dims;
+ MappableExprsHandler::MapNonContiguousArrayTy Offsets;
+ MappableExprsHandler::MapNonContiguousArrayTy Counts;
+ MappableExprsHandler::MapNonContiguousArrayTy Strides;
// Get map clause information.
MappableExprsHandler MCHandler(D, CGF);
- MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
+ MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes, Dims,
+ Offsets, Counts, Strides);
// Fill up the arrays and create the arguments.
- emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
+ emitTargetDataOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes,
+ Dims, Offsets, Counts, Strides, Info);
llvm::Value *BasePointersArrayArg = nullptr;
llvm::Value *PointersArrayArg = nullptr;
@@ -10857,14 +11167,20 @@
MappableExprsHandler::MapValuesArrayTy Pointers;
MappableExprsHandler::MapValuesArrayTy Sizes;
MappableExprsHandler::MapFlagsArrayTy MapTypes;
+ MappableExprsHandler::MapDimArrayTy Dims;
+ MappableExprsHandler::MapNonContiguousArrayTy Offsets;
+ MappableExprsHandler::MapNonContiguousArrayTy Counts;
+ MappableExprsHandler::MapNonContiguousArrayTy Strides;
// Get map clause information.
MappableExprsHandler MEHandler(D, CGF);
- MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
+ MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes, Dims,
+ Offsets, Counts, Strides);
TargetDataInfo Info;
// Fill up the arrays and create the arguments.
- emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
+ emitTargetDataOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes,
+ Dims, Offsets, Counts, Strides, Info);
emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
Info.PointersArray, Info.SizesArray,
Info.MapTypesArray, Info);
Index: clang/lib/AST/OpenMPClause.cpp
===================================================================
--- clang/lib/AST/OpenMPClause.cpp
+++ clang/lib/AST/OpenMPClause.cpp
@@ -986,7 +986,8 @@
OMPMapClause *OMPMapClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
- MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
+ MappableExprComponentListsRef ComponentLists,
+ ArrayRef<bool> NonContiguousList, ArrayRef<Expr *> UDMapperRefs,
ArrayRef<OpenMPMapModifierKind> MapModifiers,
ArrayRef<SourceLocation> MapModifiersLoc,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId,
@@ -1002,15 +1003,17 @@
// user-defined mapper for each clause list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
+ // NumComponentLists x bool - number of non-contiguous attribute.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
OMPMapClause *Clause = new (Mem)
@@ -1019,7 +1022,7 @@
Clause->setVarRefs(Vars);
Clause->setUDMapperRefs(UDMapperRefs);
- Clause->setClauseInfo(Declarations, ComponentLists);
+ Clause->setClauseInfo(Declarations, ComponentLists, NonContiguousList);
Clause->setMapType(Type);
Clause->setMapLoc(TypeLoc);
return Clause;
@@ -1029,9 +1032,9 @@
OMPMapClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
- 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ 2 * Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumVars,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPMapClause(Sizes);
@@ -1040,7 +1043,8 @@
OMPToClause *OMPToClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
- MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
+ MappableExprComponentListsRef ComponentLists,
+ ArrayRef<bool> NonContiguousList, ArrayRef<Expr *> UDMapperRefs,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
@@ -1053,15 +1057,17 @@
// user-defined mapper for each clause list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
+ // NumComponentLists x bool - number of non-contiguous attribute.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
@@ -1069,16 +1075,18 @@
Clause->setVarRefs(Vars);
Clause->setUDMapperRefs(UDMapperRefs);
- Clause->setClauseInfo(Declarations, ComponentLists);
+ Clause->setClauseInfo(Declarations, ComponentLists, NonContiguousList);
+
return Clause;
}
OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPToClause(Sizes);
@@ -1087,7 +1095,9 @@
OMPFromClause *OMPFromClause::Create(
const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
- MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
+ MappableExprComponentListsRef ComponentLists,
+ ArrayRef<bool> NonContiguousList,
+ ArrayRef<Expr *> UDMapperRefs,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) {
OMPMappableExprListSizeTy Sizes;
Sizes.NumVars = Vars.size();
@@ -1100,15 +1110,17 @@
// user-defined mapper for each clause list entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
+ // NumComponentLists x bool - number of non-contiguous attribute.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
@@ -1117,7 +1129,8 @@
Clause->setVarRefs(Vars);
Clause->setUDMapperRefs(UDMapperRefs);
- Clause->setClauseInfo(Declarations, ComponentLists);
+ Clause->setClauseInfo(Declarations, ComponentLists, NonContiguousList);
+
return Clause;
}
@@ -1125,9 +1138,10 @@
OMPFromClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPFromClause(Sizes);
@@ -1161,15 +1175,17 @@
// list entry and an equal number of private copies and inits.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
+ // NumComponentLists x bool - number of non-contiguous attribute.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
3 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
@@ -1178,7 +1194,8 @@
Clause->setVarRefs(Vars);
Clause->setPrivateCopies(PrivateVars);
Clause->setInits(Inits);
- Clause->setClauseInfo(Declarations, ComponentLists);
+ SmallVector<bool, 4> NonContiguousList(Declarations.size(), false);
+ Clause->setClauseInfo(Declarations, ComponentLists, NonContiguousList);
return Clause;
}
@@ -1186,9 +1203,10 @@
OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
3 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPUseDevicePtrClause(Sizes);
@@ -1210,22 +1228,24 @@
// entry.
// NumUniqueDeclarations x ValueDecl* - unique base declarations associated
// with each component list.
+ // NumComponentLists x bool - number of non-contiguous attribute.
// (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
// number of lists for each unique declaration and the size of each component
// list.
// NumComponents x MappableComponent - the total of all the components in all
// the lists.
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
- Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(Locs, Sizes);
Clause->setVarRefs(Vars);
- Clause->setClauseInfo(Declarations, ComponentLists);
+ SmallVector<bool, 4> NonContiguousList(Declarations.size(), false);
+ Clause->setClauseInfo(Declarations, ComponentLists, NonContiguousList);
return Clause;
}
@@ -1233,9 +1253,9 @@
OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C,
const OMPMappableExprListSizeTy &Sizes) {
void *Mem = C.Allocate(
- totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ totalSizeToAlloc<Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent>(
- Sizes.NumVars, Sizes.NumUniqueDeclarations,
+ Sizes.NumVars, Sizes.NumUniqueDeclarations, Sizes.NumComponentLists,
Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
Sizes.NumComponents));
return new (Mem) OMPIsDevicePtrClause(Sizes);
Index: clang/include/clang/AST/OpenMPClause.h
===================================================================
--- clang/include/clang/AST/OpenMPClause.h
+++ clang/include/clang/AST/OpenMPClause.h
@@ -4886,10 +4886,35 @@
std::copy(Components.begin(), Components.end(), getComponentsRef().begin());
}
+ /// Get the non-contiguous attribute per declaration that are in the trailing
+ /// objects of the class.
+ MutableArrayRef<bool> getNonContiguousListsRef() {
+ return MutableArrayRef<bool>(
+ static_cast<T *>(this)->template getTrailingObjects<bool>(),
+ NumComponentLists);
+ }
+
+ /// Get the non-contiguous attribute per declaration that are in the trailing
+ /// objects of the class.
+ ArrayRef<bool> getNonContiguousListsRef() const {
+ return ArrayRef<bool>(
+ static_cast<const T *>(this)->template getTrailingObjects<bool>(),
+ NumComponentLists);
+ }
+
+ /// Set the non-contiguous attribute per declaration that are in the trailing
+ /// objects of the class.
+ void setNonContiguousLists(ArrayRef<bool> NLs) {
+ assert(NLs.size() == NumComponentLists &&
+ "Unexpected amount of list numbers.");
+ std::copy(NLs.begin(), NLs.end(), getNonContiguousListsRef().begin());
+ }
+
/// Fill the clause information from the list of declarations and
/// associated component lists.
void setClauseInfo(ArrayRef<ValueDecl *> Declarations,
- MappableExprComponentListsRef ComponentLists) {
+ MappableExprComponentListsRef ComponentLists,
+ ArrayRef<bool> NonContiguousList) {
// Perform some checks to make sure the data sizes are consistent with the
// information available when the clause was created.
assert(getUniqueDeclarationsTotalNumber(Declarations) ==
@@ -4901,6 +4926,8 @@
"Declaration and component lists size is not consistent!");
assert(Declarations.size() == NumComponentLists &&
"Unexpected declaration and component lists size!");
+ assert(NonContiguousList.size() == ComponentLists.size() &&
+ "Unexpected NonContiguousList size");
// Organize the components by declaration and retrieve the original
// expression. Original expressions are always the first component of the
@@ -4960,6 +4987,9 @@
CI = std::copy(C.begin(), C.end(), CI);
}
}
+
+ std::copy(NonContiguousList.begin(), NonContiguousList.end(),
+ getNonContiguousListsRef().begin());
}
/// Set the nested name specifier of associated user-defined mapper.
@@ -5221,6 +5251,34 @@
return const_all_components_range(A.begin(), A.end());
}
+ using non_contiguous_list_iterator = MutableArrayRef<bool>::iterator;
+ using non_contiguous_list_const_iterator = ArrayRef<bool>::iterator;
+ using non_contiguous_list_range =
+ llvm::iterator_range<non_contiguous_list_iterator>;
+ using non_contiguous_list_const_range =
+ llvm::iterator_range<non_contiguous_list_const_iterator>;
+
+ non_contiguous_list_iterator non_contiguous_list_begin() {
+ return getNonContiguousListsRef().begin();
+ }
+ non_contiguous_list_iterator non_contiguous_list_end() {
+ return getNonContiguousListsRef().end();
+ }
+ non_contiguous_list_const_iterator non_contiguous_list_begin() const {
+ return getNonContiguousListsRef().begin();
+ }
+ non_contiguous_list_const_iterator non_contiguous_list_end() const {
+ return getNonContiguousListsRef().end();
+ }
+ non_contiguous_list_range non_contiguous_lists() {
+ return non_contiguous_list_range(non_contiguous_list_begin(),
+ non_contiguous_list_end());
+ }
+ non_contiguous_list_const_range non_contiguous_lists() const {
+ return non_contiguous_list_const_range(non_contiguous_list_begin(),
+ non_contiguous_list_end());
+ }
+
using mapperlist_iterator = MutableArrayRef<Expr *>::iterator;
using mapperlist_const_iterator = ArrayRef<const Expr *>::iterator;
using mapperlist_range = llvm::iterator_range<mapperlist_iterator>;
@@ -5251,10 +5309,11 @@
/// \endcode
/// In this example directive '#pragma omp target' has clause 'map'
/// with the variables 'a' and 'b'.
-class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>,
- private llvm::TrailingObjects<
- OMPMapClause, Expr *, ValueDecl *, unsigned,
- OMPClauseMappableExprCommon::MappableComponent> {
+class OMPMapClause final
+ : public OMPMappableExprListClause<OMPMapClause>,
+ private llvm::TrailingObjects<
+ OMPMapClause, Expr *, ValueDecl *, bool, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent> {
friend class OMPClauseReader;
friend OMPMappableExprListClause;
friend OMPVarListClause;
@@ -5270,6 +5329,9 @@
size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
return getUniqueDeclarationsNum();
}
+ size_t numTrailingObjects(OverloadToken<bool>) const {
+ return getTotalComponentListNum();
+ }
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
@@ -5403,7 +5465,7 @@
Create(const ASTContext &C, const OMPVarListLocTy &Locs,
ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists,
- ArrayRef<Expr *> UDMapperRefs,
+ ArrayRef<bool> NonContiguousList, ArrayRef<Expr *> UDMapperRefs,
ArrayRef<OpenMPMapModifierKind> MapModifiers,
ArrayRef<SourceLocation> MapModifiersLoc,
NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId,
@@ -6206,7 +6268,7 @@
/// with the variables 'a' and 'b'.
class OMPToClause final : public OMPMappableExprListClause<OMPToClause>,
private llvm::TrailingObjects<
- OMPToClause, Expr *, ValueDecl *, unsigned,
+ OMPToClause, Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
friend class OMPClauseReader;
friend OMPMappableExprListClause;
@@ -6254,6 +6316,9 @@
size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
return getUniqueDeclarationsNum();
}
+ size_t numTrailingObjects(OverloadToken<bool>) const {
+ return getTotalComponentListNum();
+ }
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
@@ -6277,6 +6342,7 @@
ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists,
+ ArrayRef<bool> IsNonContiguousList,
ArrayRef<Expr *> UDMapperRefs,
NestedNameSpecifierLoc UDMQualifierLoc,
DeclarationNameInfo MapperId);
@@ -6325,7 +6391,7 @@
class OMPFromClause final
: public OMPMappableExprListClause<OMPFromClause>,
private llvm::TrailingObjects<
- OMPFromClause, Expr *, ValueDecl *, unsigned,
+ OMPFromClause, Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
friend class OMPClauseReader;
friend OMPMappableExprListClause;
@@ -6373,6 +6439,9 @@
size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
return getUniqueDeclarationsNum();
}
+ size_t numTrailingObjects(OverloadToken<bool>) const {
+ return getTotalComponentListNum();
+ }
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
@@ -6396,6 +6465,7 @@
ArrayRef<Expr *> Vars,
ArrayRef<ValueDecl *> Declarations,
MappableExprComponentListsRef ComponentLists,
+ ArrayRef<bool> NonContiguousList,
ArrayRef<Expr *> UDMapperRefs,
NestedNameSpecifierLoc UDMQualifierLoc,
DeclarationNameInfo MapperId);
@@ -6444,7 +6514,7 @@
class OMPUseDevicePtrClause final
: public OMPMappableExprListClause<OMPUseDevicePtrClause>,
private llvm::TrailingObjects<
- OMPUseDevicePtrClause, Expr *, ValueDecl *, unsigned,
+ OMPUseDevicePtrClause, Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
friend class OMPClauseReader;
friend OMPMappableExprListClause;
@@ -6485,6 +6555,9 @@
size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
return getUniqueDeclarationsNum();
}
+ size_t numTrailingObjects(OverloadToken<bool>) const {
+ return getTotalComponentListNum();
+ }
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
@@ -6608,7 +6681,7 @@
class OMPIsDevicePtrClause final
: public OMPMappableExprListClause<OMPIsDevicePtrClause>,
private llvm::TrailingObjects<
- OMPIsDevicePtrClause, Expr *, ValueDecl *, unsigned,
+ OMPIsDevicePtrClause, Expr *, ValueDecl *, bool, unsigned,
OMPClauseMappableExprCommon::MappableComponent> {
friend class OMPClauseReader;
friend OMPMappableExprListClause;
@@ -6648,6 +6721,9 @@
size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
return getUniqueDeclarationsNum();
}
+ size_t numTrailingObjects(OverloadToken<bool>) const {
+ return getTotalComponentListNum();
+ }
size_t numTrailingObjects(OverloadToken<unsigned>) const {
return getUniqueDeclarationsNum() + getTotalComponentListNum();
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits