xref: /llvm-project/mlir/test/Target/LLVMIR/omptarget-llvm.mlir (revision d84d0caf28902843e0aae7ac435daed9aa04e3e2)
1// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
2
3llvm.func @_QPopenmp_target_data() {
4  %0 = llvm.mlir.constant(1 : i64) : i64
5  %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
6  %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
7  omp.target_data map_entries(%2 : !llvm.ptr) {
8    %3 = llvm.mlir.constant(99 : i32) : i32
9    llvm.store %3, %1 : i32, !llvm.ptr
10    omp.terminator
11  }
12  llvm.return
13}
14
15// CHECK:         @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4]
16// CHECK:         @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 3]
17// CHECK-LABEL: define void @_QPopenmp_target_data() {
18// CHECK:         %[[VAL_0:.*]] = alloca [1 x ptr], align 8
19// CHECK:         %[[VAL_1:.*]] = alloca [1 x ptr], align 8
20// CHECK:         %[[VAL_2:.*]] = alloca [1 x ptr], align 8
21// CHECK:         %[[VAL_3:.*]] = alloca i32, i64 1, align 4
22// CHECK:         br label %[[VAL_4:.*]]
23// CHECK:       entry:                                            ; preds = %[[VAL_5:.*]]
24// CHECK:         %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
25// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_6]], align 8
26// CHECK:         %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
27// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_7]], align 8
28// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0
29// CHECK:         store ptr null, ptr %[[VAL_8]], align 8
30// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
31// CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
32// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
33// CHECK:         store i32 99, ptr %[[VAL_3]], align 4
34// CHECK:         %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
35// CHECK:         %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
36// CHECK:         call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_11]], ptr %[[VAL_12]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
37// CHECK:         ret void
38
39// -----
40
41llvm.func @_QPopenmp_target_data_region(%0 : !llvm.ptr) {
42  %1 = llvm.mlir.constant(1023 : index) : i64
43  %2 = llvm.mlir.constant(0 : index) : i64
44  %3 = llvm.mlir.constant(1024 : index) : i64
45  %4 = llvm.mlir.constant(1 : index) : i64
46  %5 = omp.map.bounds   lower_bound(%2 : i64) upper_bound(%1 : i64) extent(%3 : i64) stride(%4 : i64) start_idx(%4 : i64)
47  %6 = omp.map.info var_ptr(%0 : !llvm.ptr, !llvm.array<1024 x i32>)   map_clauses(from) capture(ByRef) bounds(%5)  -> !llvm.ptr {name = ""}
48  omp.target_data map_entries(%6 : !llvm.ptr) {
49    %7 = llvm.mlir.constant(99 : i32) : i32
50    %8 = llvm.mlir.constant(1 : i64) : i64
51    %9 = llvm.mlir.constant(1 : i64) : i64
52    %10 = llvm.mlir.constant(0 : i64) : i64
53    %11 = llvm.getelementptr %0[0, %10] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<1024 x i32>
54    llvm.store %7, %11 : i32, !llvm.ptr
55    omp.terminator
56  }
57  llvm.return
58}
59
60// CHECK:         @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4096]
61// CHECK:         @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 2]
62// CHECK-LABEL: define void @_QPopenmp_target_data_region
63// CHECK:         (ptr %[[ARG_0:.*]]) {
64// CHECK:         %[[VAL_0:.*]] = alloca [1 x ptr], align 8
65// CHECK:         %[[VAL_1:.*]] = alloca [1 x ptr], align 8
66// CHECK:         %[[VAL_2:.*]] = alloca [1 x ptr], align 8
67// CHECK:         br label %[[VAL_3:.*]]
68// CHECK:       entry:                                            ; preds = %[[VAL_4:.*]]
69// CHECK:         %[[ARR_OFFSET:.*]] = getelementptr inbounds [1024 x i32], ptr %[[ARR_DATA:.*]], i64 0, i64 0
70// CHECK:         %[[VAL_5:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
71// CHECK:         store ptr %[[ARR_DATA]], ptr %[[VAL_5]], align 8
72// CHECK:         %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
73// CHECK:         store ptr %[[ARR_OFFSET]], ptr %[[VAL_6]], align 8
74// CHECK:         %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0
75// CHECK:         store ptr null, ptr %[[VAL_7]], align 8
76// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
77// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
78// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_8]], ptr %[[VAL_9]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
79// CHECK:         %[[VAL_10:.*]] = getelementptr [1024 x i32], ptr %[[ARR_DATA]], i32 0, i64 0
80// CHECK:         store i32 99, ptr %[[VAL_10]], align 4
81// CHECK:         %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
82// CHECK:         %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
83// CHECK:         call void @__tgt_target_data_end_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_11]], ptr %[[VAL_12]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
84// CHECK:         ret void
85
86// -----
87
88llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) {
89  %4 = llvm.mlir.constant(1 : i64) : i64
90  %5 = llvm.alloca %4 x i32 {bindc_name = "dvc", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_enter_exitEdvc"} : (i64) -> !llvm.ptr
91  %6 = llvm.mlir.constant(1 : i64) : i64
92  %7 = llvm.alloca %6 x i32 {bindc_name = "i", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_enter_exitEi"} : (i64) -> !llvm.ptr
93  %8 = llvm.mlir.constant(5 : i32) : i32
94  llvm.store %8, %7 : i32, !llvm.ptr
95  %9 = llvm.mlir.constant(2 : i32) : i32
96  llvm.store %9, %5 : i32, !llvm.ptr
97  %10 = llvm.load %7 : !llvm.ptr -> i32
98  %11 = llvm.mlir.constant(10 : i32) : i32
99  %12 = llvm.icmp "slt" %10, %11 : i32
100  %13 = llvm.load %5 : !llvm.ptr -> i32
101  %14 = llvm.mlir.constant(1023 : index) : i64
102  %15 = llvm.mlir.constant(0 : index) : i64
103  %16 = llvm.mlir.constant(1024 : index) : i64
104  %17 = llvm.mlir.constant(1 : index) : i64
105  %18 = omp.map.bounds   lower_bound(%15 : i64) upper_bound(%14 : i64) extent(%16 : i64) stride(%17 : i64) start_idx(%17 : i64)
106  %map1 = omp.map.info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>)   map_clauses(to) capture(ByRef) bounds(%18) -> !llvm.ptr {name = ""}
107  %19 = llvm.mlir.constant(511 : index) : i64
108  %20 = llvm.mlir.constant(0 : index) : i64
109  %21 = llvm.mlir.constant(512 : index) : i64
110  %22 = llvm.mlir.constant(1 : index) : i64
111  %23 = omp.map.bounds   lower_bound(%20 : i64) upper_bound(%19 : i64) extent(%21 : i64) stride(%22 : i64) start_idx(%22 : i64)
112  %map2 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%23) -> !llvm.ptr {name = ""}
113  omp.target_enter_data   if(%12) device(%13 : i32) map_entries(%map1, %map2 : !llvm.ptr, !llvm.ptr)
114  %24 = llvm.load %7 : !llvm.ptr -> i32
115  %25 = llvm.mlir.constant(10 : i32) : i32
116  %26 = llvm.icmp "sgt" %24, %25 : i32
117  %27 = llvm.load %5 : !llvm.ptr -> i32
118  %28 = llvm.mlir.constant(1023 : index) : i64
119  %29 = llvm.mlir.constant(0 : index) : i64
120  %30 = llvm.mlir.constant(1024 : index) : i64
121  %31 = llvm.mlir.constant(1 : index) : i64
122  %32 = omp.map.bounds   lower_bound(%29 : i64) upper_bound(%28 : i64) extent(%30 : i64) stride(%31 : i64) start_idx(%31 : i64)
123  %map3 = omp.map.info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>)   map_clauses(from) capture(ByRef) bounds(%32) -> !llvm.ptr {name = ""}
124  %33 = llvm.mlir.constant(511 : index) : i64
125  %34 = llvm.mlir.constant(0 : index) : i64
126  %35 = llvm.mlir.constant(512 : index) : i64
127  %36 = llvm.mlir.constant(1 : index) : i64
128  %37 = omp.map.bounds   lower_bound(%34 : i64) upper_bound(%33 : i64) extent(%35 : i64) stride(%36 : i64) start_idx(%36 : i64)
129  %map4 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%37) -> !llvm.ptr {name = ""}
130  omp.target_exit_data   if(%26) device(%27 : i32) map_entries(%map3, %map4 : !llvm.ptr, !llvm.ptr)
131  llvm.return
132}
133
134// CHECK:         @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 4096, i64 2048]
135// CHECK:         @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 1, i64 0]
136// CHECK:         @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4096, i64 2048]
137// CHECK:         @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 2, i64 0]
138// CHECK-LABEL: define void @_QPomp_target_enter_exit
139// CHECK:         (ptr %[[ARG_0:.*]], ptr %[[ARG_1:.*]]) {
140// CHECK:         %[[VAL_0:.*]] = alloca [2 x ptr], align 8
141// CHECK:         %[[VAL_1:.*]] = alloca [2 x ptr], align 8
142// CHECK:         %[[VAL_2:.*]] = alloca [2 x ptr], align 8
143// CHECK:         %[[VAL_3:.*]] = alloca [2 x ptr], align 8
144// CHECK:         %[[VAL_4:.*]] = alloca [2 x ptr], align 8
145// CHECK:         %[[VAL_5:.*]] = alloca [2 x ptr], align 8
146// CHECK:         %[[VAL_6:.*]] = alloca i32, i64 1, align 4
147// CHECK:         %[[VAL_7:.*]] = alloca i32, i64 1, align 4
148// CHECK:         store i32 5, ptr %[[VAL_7]], align 4
149// CHECK:         store i32 2, ptr %[[VAL_6]], align 4
150// CHECK:         %[[VAL_8:.*]] = load i32, ptr %[[VAL_7]], align 4
151// CHECK:         %[[VAL_9:.*]] = icmp slt i32 %[[VAL_8]], 10
152// CHECK:         %[[VAL_10:.*]] = load i32, ptr %[[VAL_6]], align 4
153// CHECK:         br label %[[VAL_11:.*]]
154// CHECK:       entry:                                            ; preds = %[[VAL_12:.*]]
155// CHECK:         br i1 %[[VAL_9]], label %[[VAL_13:.*]], label %[[VAL_14:.*]]
156// CHECK:       omp_if.then:                                      ; preds = %[[VAL_11]]
157// CHECK:         %[[ARR_OFFSET1:.*]] = getelementptr inbounds [1024 x i32], ptr %[[VAL_16:.*]], i64 0, i64 0
158// CHECK:         %[[ARR_OFFSET2:.*]] = getelementptr inbounds [512 x i32], ptr %[[VAL_20:.*]], i64 0, i64 0
159// CHECK:         %[[VAL_15:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 0
160// CHECK:         store ptr %[[VAL_16]], ptr %[[VAL_15]], align 8
161// CHECK:         %[[VAL_17:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 0
162// CHECK:         store ptr %[[ARR_OFFSET1]], ptr %[[VAL_17]], align 8
163// CHECK:         %[[VAL_18:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_5]], i64 0, i64 0
164// CHECK:         store ptr null, ptr %[[VAL_18]], align 8
165// CHECK:         %[[VAL_19:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 1
166// CHECK:         store ptr %[[VAL_20]], ptr %[[VAL_19]], align 8
167// CHECK:         %[[VAL_21:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 1
168// CHECK:         store ptr %[[ARR_OFFSET2]], ptr %[[VAL_21]], align 8
169// CHECK:         %[[VAL_22:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_5]], i64 0, i64 1
170// CHECK:         store ptr null, ptr %[[VAL_22]], align 8
171// CHECK:         %[[VAL_23:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 0
172// CHECK:         %[[VAL_24:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 0
173// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_23]], ptr %[[VAL_24]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
174// CHECK:         br label %[[VAL_25:.*]]
175// CHECK:       omp_if.else:                                      ; preds = %[[VAL_11]]
176// CHECK:         br label %[[VAL_25]]
177// CHECK:       omp_if.end:                                       ; preds = %[[VAL_14]], %[[VAL_13]]
178// CHECK:         %[[VAL_26:.*]] = load i32, ptr %[[VAL_7]], align 4
179// CHECK:         %[[VAL_27:.*]] = icmp sgt i32 %[[VAL_26]], 10
180// CHECK:         %[[VAL_28:.*]] = load i32, ptr %[[VAL_6]], align 4
181// CHECK:         br i1 %[[VAL_27]], label %[[VAL_29:.*]], label %[[VAL_30:.*]]
182// CHECK:       omp_if.then2:                                     ; preds = %[[VAL_25]]
183// CHECK:         %[[ARR_OFFSET3:.*]] = getelementptr inbounds [1024 x i32], ptr %[[VAL_16]], i64 0, i64 0
184// CHECK:         %[[ARR_OFFSET4:.*]] = getelementptr inbounds [512 x i32], ptr %[[VAL_20]], i64 0, i64 0
185// CHECK:         %[[VAL_31:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
186// CHECK:         store ptr %[[VAL_16]], ptr %[[VAL_31]], align 8
187// CHECK:         %[[VAL_32:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
188// CHECK:         store ptr %[[ARR_OFFSET3]], ptr %[[VAL_32]], align 8
189// CHECK:         %[[VAL_33:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0
190// CHECK:         store ptr null, ptr %[[VAL_33]], align 8
191// CHECK:         %[[VAL_34:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1
192// CHECK:         store ptr %[[VAL_20]], ptr %[[VAL_34]], align 8
193// CHECK:         %[[VAL_35:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1
194// CHECK:         store ptr %[[ARR_OFFSET4]], ptr %[[VAL_35]], align 8
195// CHECK:         %[[VAL_36:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1
196// CHECK:         store ptr null, ptr %[[VAL_36]], align 8
197// CHECK:         %[[VAL_37:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
198// CHECK:         %[[VAL_38:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
199// CHECK:         call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_37]], ptr %[[VAL_38]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr @.offload_mapnames.3, ptr null)
200// CHECK:         br label %[[VAL_39:.*]]
201// CHECK:       omp_if.else8:                                     ; preds = %[[VAL_25]]
202// CHECK:         br label %[[VAL_39]]
203// CHECK:       omp_if.end9:                                      ; preds = %[[VAL_30]], %[[VAL_29]]
204// CHECK:         ret void
205
206// -----
207
208llvm.func @_QPopenmp_target_use_dev_ptr() {
209  %0 = llvm.mlir.constant(1 : i64) : i64
210  %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr
211  %map1 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
212  %map2 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
213  omp.target_data  map_entries(%map1 : !llvm.ptr) use_device_ptr(%map2 -> %arg0 : !llvm.ptr)  {
214    %1 = llvm.mlir.constant(10 : i32) : i32
215    %2 = llvm.load %arg0 : !llvm.ptr -> !llvm.ptr
216    llvm.store %1, %2 : i32, !llvm.ptr
217    omp.terminator
218  }
219  llvm.return
220}
221
222// CHECK:         @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
223// CHECK:         @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 66]
224// CHECK-LABEL: define void @_QPopenmp_target_use_dev_ptr
225// CHECK:         %[[VAL_0:.*]] = alloca [1 x ptr], align 8
226// CHECK:         %[[VAL_1:.*]] = alloca [1 x ptr], align 8
227// CHECK:         %[[VAL_2:.*]] = alloca [1 x ptr], align 8
228// CHECK:         %[[VAL_3:.*]] = alloca ptr, align 8
229// CHECK:         %[[VAL_4:.*]] = alloca ptr, i64 1, align 8
230// CHECK:         br label %[[VAL_5:.*]]
231// CHECK:       entry:                                            ; preds = %[[VAL_6:.*]]
232// CHECK:         %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
233// CHECK:         store ptr %[[VAL_4]], ptr %[[VAL_7]], align 8
234// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
235// CHECK:         store ptr %[[VAL_4]], ptr %[[VAL_8]], align 8
236// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0
237// CHECK:         store ptr null, ptr %[[VAL_9]], align 8
238// CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
239// CHECK:         %[[VAL_11:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
240// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @{{.*}}, i64 -1, i32 1, ptr %[[VAL_10]], ptr %[[VAL_11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
241// CHECK:         %[[VAL_12:.*]] = load ptr, ptr %[[VAL_7]], align 8
242// CHECK:         store ptr %[[VAL_12]], ptr %[[VAL_3]], align 8
243// CHECK:         %[[VAL_13:.*]] = load ptr, ptr %[[VAL_3]], align 8
244// CHECK:         store i32 10, ptr %[[VAL_13]], align 4
245// CHECK:         %[[VAL_14:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
246// CHECK:         %[[VAL_15:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
247// CHECK:         call void @__tgt_target_data_end_mapper(ptr @{{.*}}, i64 -1, i32 1, ptr %[[VAL_14]], ptr %[[VAL_15]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
248// CHECK:         ret void
249
250// -----
251
252llvm.func @_QPopenmp_target_use_dev_addr() {
253  %0 = llvm.mlir.constant(1 : i64) : i64
254  %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr
255  %map = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
256  %map2 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
257  omp.target_data  map_entries(%map : !llvm.ptr) use_device_addr(%map2 -> %arg0 : !llvm.ptr)  {
258    %1 = llvm.mlir.constant(10 : i32) : i32
259    %2 = llvm.load %arg0 : !llvm.ptr -> !llvm.ptr
260    llvm.store %1, %2 : i32, !llvm.ptr
261    omp.terminator
262  }
263  llvm.return
264}
265
266// CHECK:         @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
267// CHECK:         @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 66]
268// CHECK-LABEL: define void @_QPopenmp_target_use_dev_addr
269// CHECK:         %[[VAL_0:.*]] = alloca [1 x ptr], align 8
270// CHECK:         %[[VAL_1:.*]] = alloca [1 x ptr], align 8
271// CHECK:         %[[VAL_2:.*]] = alloca [1 x ptr], align 8
272// CHECK:         %[[VAL_3:.*]] = alloca ptr, i64 1, align 8
273// CHECK:         br label %[[VAL_4:.*]]
274// CHECK:       entry:                                            ; preds = %[[VAL_5:.*]]
275// CHECK:         %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
276// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_6]], align 8
277// CHECK:         %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
278// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_7]], align 8
279// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0
280// CHECK:         store ptr null, ptr %[[VAL_8]], align 8
281// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
282// CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
283// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @{{.*}}, i64 -1, i32 1, ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
284// CHECK:         %[[VAL_11:.*]] = load ptr, ptr %[[VAL_6]], align 8
285// CHECK:         %[[VAL_12:.*]] = load ptr, ptr %[[VAL_11]], align 8
286// CHECK:         store i32 10, ptr %[[VAL_12]], align 4
287// CHECK:         %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
288// CHECK:         %[[VAL_14:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
289// CHECK:         call void @__tgt_target_data_end_mapper(ptr @{{.*}}, i64 -1, i32 1, ptr %[[VAL_13]], ptr %[[VAL_14]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
290// CHECK:         ret void
291
292// -----
293
294llvm.func @_QPopenmp_target_use_dev_addr_no_ptr() {
295  %0 = llvm.mlir.constant(1 : i64) : i64
296  %a = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr
297  %map = omp.map.info var_ptr(%a : !llvm.ptr, i32)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
298  %map2 = omp.map.info var_ptr(%a : !llvm.ptr, i32)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
299  omp.target_data  map_entries(%map : !llvm.ptr) use_device_addr(%map2 -> %arg0 : !llvm.ptr)  {
300    %1 = llvm.mlir.constant(10 : i32) : i32
301    llvm.store %1, %arg0 : i32, !llvm.ptr
302    omp.terminator
303  }
304  llvm.return
305}
306
307// CHECK:         @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4]
308// CHECK:         @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 67]
309// CHECK-LABEL: define void @_QPopenmp_target_use_dev_addr_no_ptr
310// CHECK:         %[[VAL_0:.*]] = alloca [1 x ptr], align 8
311// CHECK:         %[[VAL_1:.*]] = alloca [1 x ptr], align 8
312// CHECK:         %[[VAL_2:.*]] = alloca [1 x ptr], align 8
313// CHECK:         %[[VAL_3:.*]] = alloca i32, i64 1, align 4
314// CHECK:         br label %[[VAL_4:.*]]
315// CHECK:       entry:                                            ; preds = %[[VAL_5:.*]]
316// CHECK:         %[[VAL_6:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
317// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_6]], align 8
318// CHECK:         %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
319// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_7]], align 8
320// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0
321// CHECK:         store ptr null, ptr %[[VAL_8]], align 8
322// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
323// CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
324// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @{{.*}}, i64 -1, i32 1, ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
325// CHECK:         %[[VAL_11:.*]] = load ptr, ptr %[[VAL_6]], align 8
326// CHECK:         store i32 10, ptr %[[VAL_11]], align 4
327// CHECK:         %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0
328// CHECK:         %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0
329// CHECK:         call void @__tgt_target_data_end_mapper(ptr @{{.*}}, i64 -1, i32 1, ptr %[[VAL_12]], ptr %[[VAL_13]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
330// CHECK:         ret void
331
332// -----
333
334llvm.func @_QPopenmp_target_use_dev_addr_nomap() {
335  %0 = llvm.mlir.constant(1 : i64) : i64
336  %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr
337  %1 = llvm.mlir.constant(1 : i64) : i64
338  %b = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr
339  %map = omp.map.info var_ptr(%b : !llvm.ptr, !llvm.ptr)   map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
340  %map2 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
341  omp.target_data  map_entries(%map : !llvm.ptr) use_device_addr(%map2 -> %arg0 : !llvm.ptr)  {
342    %2 = llvm.mlir.constant(10 : i32) : i32
343    %3 = llvm.load %arg0 : !llvm.ptr -> !llvm.ptr
344    llvm.store %2, %3 : i32, !llvm.ptr
345    %4 = llvm.mlir.constant(20 : i32) : i32
346    %5 = llvm.load %b : !llvm.ptr -> !llvm.ptr
347    llvm.store %4, %5 : i32, !llvm.ptr
348    omp.terminator
349  }
350  llvm.return
351}
352
353// CHECK:         @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 8, i64 0]
354// CHECK:         @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 2, i64 64]
355// CHECK-LABEL: define void @_QPopenmp_target_use_dev_addr_nomap
356// CHECK:         %[[VAL_0:.*]] = alloca [2 x ptr], align 8
357// CHECK:         %[[VAL_1:.*]] = alloca [2 x ptr], align 8
358// CHECK:         %[[VAL_2:.*]] = alloca [2 x ptr], align 8
359// CHECK:         %[[VAL_3:.*]] = alloca ptr, i64 1, align 8
360// CHECK:         %[[VAL_4:.*]] = alloca ptr, i64 1, align 8
361// CHECK:         br label %[[VAL_5:.*]]
362// CHECK:       entry:                                            ; preds = %[[VAL_6:.*]]
363// CHECK:         %[[VAL_7:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
364// CHECK:         store ptr %[[VAL_4]], ptr %[[VAL_7]], align 8
365// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
366// CHECK:         store ptr %[[VAL_4]], ptr %[[VAL_8]], align 8
367// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0
368// CHECK:         store ptr null, ptr %[[VAL_9]], align 8
369// CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1
370// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_10]], align 8
371// CHECK:         %[[VAL_11:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1
372// CHECK:         store ptr %[[VAL_3]], ptr %[[VAL_11]], align 8
373// CHECK:         %[[VAL_12:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1
374// CHECK:         store ptr null, ptr %[[VAL_12]], align 8
375// CHECK:         %[[VAL_13:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
376// CHECK:         %[[VAL_14:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
377// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_13]], ptr %[[VAL_14]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
378// CHECK:         %[[VAL_15:.*]] = load ptr, ptr %[[VAL_10]], align 8
379// CHECK:         %[[VAL_16:.*]] = load ptr, ptr %[[VAL_15]], align 8
380// CHECK:         store i32 10, ptr %[[VAL_16]], align 4
381// CHECK:         %[[VAL_17:.*]] = load ptr, ptr %[[VAL_4]], align 8
382// CHECK:         store i32 20, ptr %[[VAL_17]], align 4
383// CHECK:         %[[VAL_18:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
384// CHECK:         %[[VAL_19:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
385// CHECK:         call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_18]], ptr %[[VAL_19]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
386// CHECK:         ret void
387
388// -----
389
390llvm.func @_QPopenmp_target_use_dev_both() {
391  %0 = llvm.mlir.constant(1 : i64) : i64
392  %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr
393  %1 = llvm.mlir.constant(1 : i64) : i64
394  %b = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr
395  %map = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
396  %map1 = omp.map.info var_ptr(%b : !llvm.ptr, !llvm.ptr)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
397  %map2 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
398  %map3 = omp.map.info var_ptr(%b : !llvm.ptr, !llvm.ptr)   map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
399  omp.target_data  map_entries(%map, %map1 : !llvm.ptr, !llvm.ptr) use_device_addr(%map3 -> %arg0 : !llvm.ptr) use_device_ptr(%map2 -> %arg1 : !llvm.ptr)  {
400    %2 = llvm.mlir.constant(10 : i32) : i32
401    %3 = llvm.load %arg1 : !llvm.ptr -> !llvm.ptr
402    llvm.store %2, %3 : i32, !llvm.ptr
403    %4 = llvm.mlir.constant(20 : i32) : i32
404    %5 = llvm.load %arg0 : !llvm.ptr -> !llvm.ptr
405    llvm.store %4, %5 : i32, !llvm.ptr
406    omp.terminator
407  }
408  llvm.return
409}
410
411// CHECK:         @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 8, i64 8]
412// CHECK:         @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 67, i64 67]
413// CHECK-LABEL: define void @_QPopenmp_target_use_dev_both
414// CHECK:         %[[VAL_0:.*]] = alloca [2 x ptr], align 8
415// CHECK:         %[[VAL_1:.*]] = alloca [2 x ptr], align 8
416// CHECK:         %[[VAL_2:.*]] = alloca [2 x ptr], align 8
417// CHECK:         %[[VAL_3:.*]] = alloca ptr, align 8
418// CHECK:         %[[VAL_4:.*]] = alloca ptr, i64 1, align 8
419// CHECK:         %[[VAL_5:.*]] = alloca ptr, i64 1, align 8
420// CHECK:         br label %[[VAL_6:.*]]
421// CHECK:       entry:                                            ; preds = %[[VAL_7:.*]]
422// CHECK:         %[[VAL_8:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
423// CHECK:         store ptr %[[VAL_4]], ptr %[[VAL_8]], align 8
424// CHECK:         %[[VAL_9:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
425// CHECK:         store ptr %[[VAL_4]], ptr %[[VAL_9]], align 8
426// CHECK:         %[[VAL_10:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0
427// CHECK:         store ptr null, ptr %[[VAL_10]], align 8
428// CHECK:         %[[VAL_11:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1
429// CHECK:         store ptr %[[VAL_5]], ptr %[[VAL_11]], align 8
430// CHECK:         %[[VAL_12:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1
431// CHECK:         store ptr %[[VAL_5]], ptr %[[VAL_12]], align 8
432// CHECK:         %[[VAL_13:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1
433// CHECK:         store ptr null, ptr %[[VAL_13]], align 8
434// CHECK:         %[[VAL_14:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
435// CHECK:         %[[VAL_15:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
436// CHECK:         call void @__tgt_target_data_begin_mapper(ptr @{{.*}}, i64 -1, i32 2, ptr %[[VAL_14]], ptr %[[VAL_15]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
437// CHECK:         %[[VAL_16:.*]] = load ptr, ptr %[[VAL_8]], align 8
438// CHECK:         store ptr %[[VAL_16]], ptr %[[VAL_3]], align 8
439// CHECK:         %[[VAL_17:.*]] = load ptr, ptr %[[VAL_11]], align 8
440// CHECK:         %[[VAL_18:.*]] = load ptr, ptr %[[VAL_3]], align 8
441// CHECK:         store i32 10, ptr %[[VAL_18]], align 4
442// CHECK:         %[[VAL_19:.*]] = load ptr, ptr %[[VAL_17]], align 8
443// CHECK:         store i32 20, ptr %[[VAL_19]], align 4
444// CHECK:         %[[VAL_20:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0
445// CHECK:         %[[VAL_21:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0
446// CHECK:         call void @__tgt_target_data_end_mapper(ptr @{{.*}}, i64 -1, i32 2, ptr %[[VAL_20]], ptr %[[VAL_21]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null)
447// CHECK:         ret void
448
449// -----
450
451llvm.func @_QPopenmp_target_data_update() {
452  %0 = llvm.mlir.constant(1 : i64) : i64
453  %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr
454  %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32)   map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
455  omp.target_data map_entries(%2 : !llvm.ptr) {
456    %3 = llvm.mlir.constant(99 : i32) : i32
457    llvm.store %3, %1 : i32, !llvm.ptr
458    omp.terminator
459  }
460
461  omp.target_update map_entries(%2 : !llvm.ptr)
462
463  llvm.return
464}
465
466// CHECK-LABEL: define void @_QPopenmp_target_data_update
467
468// CHECK-DAG:     %[[OFFLOAD_BASEPTRS:.*]] = alloca [1 x ptr], align 8
469// CHECK-DAG:     %[[OFFLOAD_PTRS:.*]] = alloca [1 x ptr], align 8
470// CHECK-DAG:     %[[INT_ALLOCA:.*]] = alloca i32, i64 1, align 4
471// CHECK-DAG:     %[[OFFLOAD_MAPPERS:.*]] = alloca [1 x ptr], align 8
472
473// CHECK:         call void @__tgt_target_data_begin_mapper
474// CHECK:         store i32 99, ptr %[[INT_ALLOCA]], align 4
475// CHECK:         call void @__tgt_target_data_end_mapper
476
477// CHECK:         %[[BASEPTRS_VAL:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_BASEPTRS]], i32 0, i32 0
478// CHECK:         store ptr %[[INT_ALLOCA]], ptr %[[BASEPTRS_VAL]], align 8
479// CHECK:         %[[PTRS_VAL:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_PTRS]], i32 0, i32 0
480// CHECK:         store ptr %[[INT_ALLOCA]], ptr %[[PTRS_VAL]], align 8
481// CHECK:         %[[MAPPERS_VAL:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_MAPPERS]], i64 0, i64 0
482// CHECK:         store ptr null, ptr %[[MAPPERS_VAL]], align 8
483// CHECK:         %[[BASEPTRS_VAL_2:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_BASEPTRS]], i32 0, i32 0
484// CHECK:         %[[PTRS_VAL_2:.*]] = getelementptr inbounds [1 x ptr], ptr %[[OFFLOAD_PTRS]], i32 0, i32 0
485// CHECK:         call void @__tgt_target_data_update_mapper(ptr @2, i64 -1, i32 1, ptr %[[BASEPTRS_VAL_2]], ptr %[[PTRS_VAL_2]], ptr @{{.*}}, ptr @{{.*}}, ptr @{{.*}}, ptr null)
486
487// CHECK:         ret void
488