1// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
2
3// CHECK-LABEL: define void @test_stand_alone_directives()
4llvm.func @test_stand_alone_directives() {
5  // CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
6  // CHECK-NEXT:  call void @__kmpc_barrier(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD]])
7  omp.barrier
8
9  // CHECK: [[OMP_THREAD1:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
10  // CHECK-NEXT:  [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskwait(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD1]])
11  omp.taskwait
12
13  // CHECK: [[OMP_THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
14  // CHECK-NEXT:  [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskyield(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD2]], i32 0)
15  omp.taskyield
16
17  // CHECK-NEXT:    ret void
18  llvm.return
19}
20
21// CHECK-LABEL: define void @test_flush_construct(i32 %0)
22llvm.func @test_flush_construct(%arg0: !llvm.i32) {
23  // CHECK: call void @__kmpc_flush(%struct.ident_t* @{{[0-9]+}}
24  omp.flush
25
26  // CHECK: call void @__kmpc_flush(%struct.ident_t* @{{[0-9]+}}
27  omp.flush (%arg0 : !llvm.i32)
28
29  // CHECK: call void @__kmpc_flush(%struct.ident_t* @{{[0-9]+}}
30  omp.flush (%arg0, %arg0 : !llvm.i32, !llvm.i32)
31
32  %0 = llvm.mlir.constant(1 : i64) : !llvm.i64
33  //  CHECK: alloca {{.*}} align 4
34  %1 = llvm.alloca %0 x !llvm.i32 {in_type = i32, name = "a"} : (!llvm.i64) -> !llvm.ptr<i32>
35  // CHECK: call void @__kmpc_flush(%struct.ident_t* @{{[0-9]+}}
36  omp.flush
37  //  CHECK: load i32, i32*
38  %2 = llvm.load %1 : !llvm.ptr<i32>
39
40  // CHECK-NEXT:    ret void
41  llvm.return
42}
43
44// CHECK-LABEL: define void @test_omp_parallel_1()
45llvm.func @test_omp_parallel_1() -> () {
46  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_1:.*]] to {{.*}}
47  omp.parallel {
48    omp.barrier
49    omp.terminator
50  }
51
52  llvm.return
53}
54
55// CHECK: define internal void @[[OMP_OUTLINED_FN_1]]
56  // CHECK: call void @__kmpc_barrier
57
58llvm.func @body(!llvm.i64)
59
60// CHECK-LABEL: define void @test_omp_parallel_2()
61llvm.func @test_omp_parallel_2() -> () {
62  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_2:.*]] to {{.*}}
63  omp.parallel {
64    ^bb0:
65      %0 = llvm.mlir.constant(1 : index) : !llvm.i64
66      %1 = llvm.mlir.constant(42 : index) : !llvm.i64
67      llvm.call @body(%0) : (!llvm.i64) -> ()
68      llvm.call @body(%1) : (!llvm.i64) -> ()
69      llvm.br ^bb1
70
71    ^bb1:
72      %2 = llvm.add %0, %1 : !llvm.i64
73      llvm.call @body(%2) : (!llvm.i64) -> ()
74      omp.terminator
75  }
76  llvm.return
77}
78
79// CHECK: define internal void @[[OMP_OUTLINED_FN_2]]
80  // CHECK-LABEL: omp.par.region:
81  // CHECK: br label %omp.par.region1
82  // CHECK-LABEL: omp.par.region1:
83  // CHECK: call void @body(i64 1)
84  // CHECK: call void @body(i64 42)
85  // CHECK: br label %omp.par.region2
86  // CHECK-LABEL: omp.par.region2:
87  // CHECK: call void @body(i64 43)
88  // CHECK: br label %omp.par.pre_finalize
89
90// CHECK: define void @test_omp_parallel_num_threads_1(i32 %[[NUM_THREADS_VAR_1:.*]])
91llvm.func @test_omp_parallel_num_threads_1(%arg0: !llvm.i32) -> () {
92  // CHECK: %[[GTN_NUM_THREADS_VAR_1:.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GTN_SI_VAR_1:.*]])
93  // CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GTN_SI_VAR_1]], i32 %[[GTN_NUM_THREADS_VAR_1]], i32 %[[NUM_THREADS_VAR_1]])
94  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_1:.*]] to {{.*}}
95  omp.parallel num_threads(%arg0: !llvm.i32) {
96    omp.barrier
97    omp.terminator
98  }
99
100  llvm.return
101}
102
103// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_1]]
104  // CHECK: call void @__kmpc_barrier
105
106// CHECK: define void @test_omp_parallel_num_threads_2()
107llvm.func @test_omp_parallel_num_threads_2() -> () {
108  %0 = llvm.mlir.constant(4 : index) : !llvm.i32
109  // CHECK: %[[GTN_NUM_THREADS_VAR_2:.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GTN_SI_VAR_2:.*]])
110  // CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GTN_SI_VAR_2]], i32 %[[GTN_NUM_THREADS_VAR_2]], i32 4)
111  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_2:.*]] to {{.*}}
112  omp.parallel num_threads(%0: !llvm.i32) {
113    omp.barrier
114    omp.terminator
115  }
116
117  llvm.return
118}
119
120// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_2]]
121  // CHECK: call void @__kmpc_barrier
122
123// CHECK: define void @test_omp_parallel_num_threads_3()
124llvm.func @test_omp_parallel_num_threads_3() -> () {
125  %0 = llvm.mlir.constant(4 : index) : !llvm.i32
126  // CHECK: %[[GTN_NUM_THREADS_VAR_3_1:.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GTN_SI_VAR_3_1:.*]])
127  // CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GTN_SI_VAR_3_1]], i32 %[[GTN_NUM_THREADS_VAR_3_1]], i32 4)
128  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_3_1:.*]] to {{.*}}
129  omp.parallel num_threads(%0: !llvm.i32) {
130    omp.barrier
131    omp.terminator
132  }
133  %1 = llvm.mlir.constant(8 : index) : !llvm.i32
134  // CHECK: %[[GTN_NUM_THREADS_VAR_3_2:.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GTN_SI_VAR_3_2:.*]])
135  // CHECK: call void @__kmpc_push_num_threads(%struct.ident_t* @[[GTN_SI_VAR_3_2]], i32 %[[GTN_NUM_THREADS_VAR_3_2]], i32 8)
136  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_3_2:.*]] to {{.*}}
137  omp.parallel num_threads(%1: !llvm.i32) {
138    omp.barrier
139    omp.terminator
140  }
141
142  llvm.return
143}
144
145// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_3_2]]
146  // CHECK: call void @__kmpc_barrier
147
148// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_3_1]]
149  // CHECK: call void @__kmpc_barrier
150
151// CHECK: define void @test_omp_parallel_if_1(i32 %[[IF_VAR_1:.*]])
152llvm.func @test_omp_parallel_if_1(%arg0: !llvm.i32) -> () {
153
154// CHECK: %[[IF_COND_VAR_1:.*]] = icmp slt i32 %[[IF_VAR_1]], 0
155  %0 = llvm.mlir.constant(0 : index) : !llvm.i32
156  %1 = llvm.icmp "slt" %arg0, %0 : !llvm.i32
157
158// CHECK: %[[GTN_IF_1:.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[SI_VAR_IF_1:.*]])
159// CHECK: br i1 %[[IF_COND_VAR_1]], label %[[IF_COND_TRUE_BLOCK_1:.*]], label %[[IF_COND_FALSE_BLOCK_1:.*]]
160// CHECK: [[IF_COND_TRUE_BLOCK_1]]:
161// CHECK: br label %[[OUTLINED_CALL_IF_BLOCK_1:.*]]
162// CHECK: [[OUTLINED_CALL_IF_BLOCK_1]]:
163// CHECK: call void {{.*}} @__kmpc_fork_call(%struct.ident_t* @[[SI_VAR_IF_1]], {{.*}} @[[OMP_OUTLINED_FN_IF_1:.*]] to void
164// CHECK: br label %[[OUTLINED_EXIT_IF_1:.*]]
165// CHECK: [[OUTLINED_EXIT_IF_1]]:
166// CHECK: br label %[[OUTLINED_EXIT_IF_2:.*]]
167// CHECK: [[OUTLINED_EXIT_IF_2]]:
168// CHECK: br label %[[RETURN_BLOCK_IF_1:.*]]
169// CHECK: [[IF_COND_FALSE_BLOCK_1]]:
170// CHECK: call void @__kmpc_serialized_parallel(%struct.ident_t* @[[SI_VAR_IF_1]], i32 %[[GTN_IF_1]])
171// CHECK: call void @[[OMP_OUTLINED_FN_IF_1]]
172// CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* @[[SI_VAR_IF_1]], i32 %[[GTN_IF_1]])
173// CHECK: br label %[[RETURN_BLOCK_IF_1]]
174  omp.parallel if(%1 : !llvm.i1) {
175    omp.barrier
176    omp.terminator
177  }
178
179// CHECK: [[RETURN_BLOCK_IF_1]]:
180// CHECK: ret void
181  llvm.return
182}
183
184// CHECK: define internal void @[[OMP_OUTLINED_FN_IF_1]]
185  // CHECK: call void @__kmpc_barrier
186
187// CHECK-LABEL: define void @test_omp_parallel_3()
188llvm.func @test_omp_parallel_3() -> () {
189  // CHECK: [[OMP_THREAD_3_1:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
190  // CHECK: call void @__kmpc_push_proc_bind(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_1]], i32 2)
191  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_1:.*]] to {{.*}}
192  omp.parallel proc_bind(master) {
193    omp.barrier
194    omp.terminator
195  }
196  // CHECK: [[OMP_THREAD_3_2:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
197  // CHECK: call void @__kmpc_push_proc_bind(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_2]], i32 3)
198  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_2:.*]] to {{.*}}
199  omp.parallel proc_bind(close) {
200    omp.barrier
201    omp.terminator
202  }
203  // CHECK: [[OMP_THREAD_3_3:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
204  // CHECK: call void @__kmpc_push_proc_bind(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_3]], i32 4)
205  // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_3:.*]] to {{.*}}
206  omp.parallel proc_bind(spread) {
207    omp.barrier
208    omp.terminator
209  }
210
211  llvm.return
212}
213
214// CHECK: define internal void @[[OMP_OUTLINED_FN_3_3]]
215// CHECK: define internal void @[[OMP_OUTLINED_FN_3_2]]
216// CHECK: define internal void @[[OMP_OUTLINED_FN_3_1]]
217
218// CHECK-LABEL: define void @test_omp_parallel_4()
219llvm.func @test_omp_parallel_4() -> () {
220// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_4_1:.*]] to
221// CHECK: define internal void @[[OMP_OUTLINED_FN_4_1]]
222// CHECK: call void @__kmpc_barrier
223// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_4_1_1:.*]] to
224// CHECK: call void @__kmpc_barrier
225  omp.parallel {
226    omp.barrier
227
228// CHECK: define internal void @[[OMP_OUTLINED_FN_4_1_1]]
229// CHECK: call void @__kmpc_barrier
230    omp.parallel {
231      omp.barrier
232      omp.terminator
233    }
234
235    omp.barrier
236    omp.terminator
237  }
238  llvm.return
239}
240
241llvm.func @test_omp_parallel_5() -> () {
242// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1:.*]] to
243// CHECK: define internal void @[[OMP_OUTLINED_FN_5_1]]
244// CHECK: call void @__kmpc_barrier
245// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1_1:.*]] to
246// CHECK: call void @__kmpc_barrier
247  omp.parallel {
248    omp.barrier
249
250// CHECK: define internal void @[[OMP_OUTLINED_FN_5_1_1]]
251    omp.parallel {
252// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1_1_1:.*]] to
253// CHECK: define internal void @[[OMP_OUTLINED_FN_5_1_1_1]]
254// CHECK: call void @__kmpc_barrier
255      omp.parallel {
256        omp.barrier
257        omp.terminator
258      }
259      omp.terminator
260    }
261
262    omp.barrier
263    omp.terminator
264  }
265  llvm.return
266}
267
268// CHECK-LABEL: define void @test_omp_master()
269llvm.func @test_omp_master() -> () {
270// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @{{.*}} to
271// CHECK: omp.par.region1:
272  omp.parallel {
273    omp.master {
274// CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @{{[0-9]+}})
275// CHECK: {{[0-9]+}} = call i32 @__kmpc_master(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])
276// CHECK: omp.master.region
277// CHECK: call void @__kmpc_end_master(%struct.ident_t* @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])
278// CHECK: br label %omp_region.end
279      omp.terminator
280    }
281    omp.terminator
282  }
283  omp.parallel {
284    omp.parallel {
285      omp.master {
286        omp.terminator
287      }
288      omp.terminator
289    }
290    omp.terminator
291  }
292  llvm.return
293}
294