3452 lines · plain
1// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s2 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(ptr @{{[0-9]+}})6 // CHECK-NEXT: call void @__kmpc_barrier(ptr @{{[0-9]+}}, i32 [[OMP_THREAD]])7 omp.barrier8 9 // CHECK: [[OMP_THREAD1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})10 // CHECK-NEXT: [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskwait(ptr @{{[0-9]+}}, i32 [[OMP_THREAD1]])11 omp.taskwait12 13 // CHECK: [[OMP_THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})14 // CHECK-NEXT: [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskyield(ptr @{{[0-9]+}}, i32 [[OMP_THREAD2]], i32 0)15 omp.taskyield16 17 // CHECK-NEXT: ret void18 llvm.return19}20 21// CHECK-LABEL: define void @test_flush_construct(ptr %{{[0-9]+}})22llvm.func @test_flush_construct(%arg0: !llvm.ptr) {23 // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}24 omp.flush25 26 // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}27 omp.flush (%arg0 : !llvm.ptr)28 29 // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}30 omp.flush (%arg0, %arg0 : !llvm.ptr, !llvm.ptr)31 32 %0 = llvm.mlir.constant(1 : i64) : i6433 // CHECK: alloca {{.*}} align 434 %1 = llvm.alloca %0 x i32 {in_type = i32, name = "a"} : (i64) -> !llvm.ptr35 // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}36 omp.flush37 // CHECK: load i32, ptr38 %2 = llvm.load %1 : !llvm.ptr -> i3239 40 // CHECK-NEXT: ret void41 llvm.return42}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:.*]])47 omp.parallel {48 omp.barrier49 omp.terminator50 }51 52 llvm.return53}54 55// CHECK: define internal void @[[OMP_OUTLINED_FN_1]]56 // CHECK: call void @__kmpc_barrier57 58llvm.func @body(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:.*]])63 omp.parallel {64 ^bb0:65 %0 = llvm.mlir.constant(1 : index) : i6466 %1 = llvm.mlir.constant(42 : index) : i6467 llvm.call @body(%0) : (i64) -> ()68 llvm.call @body(%1) : (i64) -> ()69 llvm.br ^bb170 71 ^bb1:72 %2 = llvm.add %0, %1 : i6473 llvm.call @body(%2) : (i64) -> ()74 omp.terminator75 }76 llvm.return77}78 79// CHECK: define internal void @[[OMP_OUTLINED_FN_2]]80 // CHECK-LABEL: omp.par.region:81 // CHECK: br label %omp.par.region182 // 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.region286 // CHECK-LABEL: omp.par.region2:87 // CHECK: call void @body(i64 43)88 // CHECK: br label %omp.par.pre_finalize89 90// CHECK: define void @test_omp_parallel_num_threads_1(i32 %[[NUM_THREADS_VAR_1:.*]])91llvm.func @test_omp_parallel_num_threads_1(%arg0: i32) -> () {92 // CHECK: %[[GTN_NUM_THREADS_VAR_1:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_1:.*]])93 // CHECK: call void @__kmpc_push_num_threads(ptr @[[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:.*]])95 omp.parallel num_threads(%arg0: i32) {96 omp.barrier97 omp.terminator98 }99 100 llvm.return101}102 103// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_1]]104 // CHECK: call void @__kmpc_barrier105 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) : i32109 // CHECK: %[[GTN_NUM_THREADS_VAR_2:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_2:.*]])110 // CHECK: call void @__kmpc_push_num_threads(ptr @[[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:.*]])112 omp.parallel num_threads(%0: i32) {113 omp.barrier114 omp.terminator115 }116 117 llvm.return118}119 120// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_2]]121 // CHECK: call void @__kmpc_barrier122 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) : i32126 // CHECK: %[[GTN_NUM_THREADS_VAR_3_1:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_3_1:.*]])127 // CHECK: call void @__kmpc_push_num_threads(ptr @[[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:.*]])129 omp.parallel num_threads(%0: i32) {130 omp.barrier131 omp.terminator132 }133 %1 = llvm.mlir.constant(8 : index) : i32134 // CHECK: %[[GTN_NUM_THREADS_VAR_3_2:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_3_2:.*]])135 // CHECK: call void @__kmpc_push_num_threads(ptr @[[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:.*]])137 omp.parallel num_threads(%1: i32) {138 omp.barrier139 omp.terminator140 }141 142 llvm.return143}144 145// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_3_2]]146 // CHECK: call void @__kmpc_barrier147 148// CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_3_1]]149 // CHECK: call void @__kmpc_barrier150 151// CHECK: define void @test_omp_parallel_if_1(i32 %[[IF_EXPR_1:.*]])152llvm.func @test_omp_parallel_if_1(%arg0: i32) -> () {153 154 %0 = llvm.mlir.constant(0 : index) : i32155 %1 = llvm.icmp "slt" %arg0, %0 : i32156// CHECK: %[[IF_COND_VAR_1:.*]] = icmp slt i32 %[[IF_EXPR_1]], 0157 158 159// CHECK: %[[GTN_IF_1:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[SI_VAR_IF_1:.*]])160// CHECK: br label %[[OUTLINED_CALL_IF_BLOCK_1:.*]]161// CHECK: [[OUTLINED_CALL_IF_BLOCK_1]]:162// CHECK: %[[I32_IF_COND_VAR_1:.*]] = sext i1 %[[IF_COND_VAR_1]] to i32163// CHECK: call void @__kmpc_fork_call_if(ptr @[[SI_VAR_IF_1]], i32 0, ptr @[[OMP_OUTLINED_FN_IF_1:.*]], i32 %[[I32_IF_COND_VAR_1]], ptr null)164// CHECK: br label %[[OUTLINED_EXIT_IF_1:.*]]165 omp.parallel if(%1) {166 omp.barrier167 omp.terminator168 }169 170// CHECK: [[OUTLINED_EXIT_IF_1]]:171// CHECK: ret void172 llvm.return173}174 175// CHECK: define internal void @[[OMP_OUTLINED_FN_IF_1]]176 // CHECK: call void @__kmpc_barrier177 178// -----179 180// CHECK-LABEL: define void @test_omp_parallel_attrs()181llvm.func @test_omp_parallel_attrs() -> () attributes {182 target_cpu = "x86-64",183 target_features = #llvm.target_features<["+mmx", "+sse"]>184} {185 // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN:.*]])186 omp.parallel {187 omp.barrier188 omp.terminator189 }190 191 llvm.return192}193 194// CHECK: define {{.*}} @[[OMP_OUTLINED_FN]]{{.*}} #[[ATTRS:[0-9]+]]195// CHECK: attributes #[[ATTRS]] = {196// CHECK-SAME: "target-cpu"="x86-64"197// CHECK-SAME: "target-features"="+mmx,+sse"198 199// -----200 201// CHECK-LABEL: define void @test_omp_parallel_3()202llvm.func @test_omp_parallel_3() -> () {203 // CHECK: [[OMP_THREAD_3_1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})204 // CHECK: call void @__kmpc_push_proc_bind(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_1]], i32 2)205 // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_1:.*]])206 omp.parallel proc_bind(master) {207 omp.barrier208 omp.terminator209 }210 // CHECK: [[OMP_THREAD_3_2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})211 // CHECK: call void @__kmpc_push_proc_bind(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_2]], i32 3)212 // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_2:.*]])213 omp.parallel proc_bind(close) {214 omp.barrier215 omp.terminator216 }217 // CHECK: [[OMP_THREAD_3_3:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})218 // CHECK: call void @__kmpc_push_proc_bind(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_3]], i32 4)219 // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_3:.*]])220 omp.parallel proc_bind(spread) {221 omp.barrier222 omp.terminator223 }224 225 llvm.return226}227 228// CHECK: define internal void @[[OMP_OUTLINED_FN_3_3]]229// CHECK: define internal void @[[OMP_OUTLINED_FN_3_2]]230// CHECK: define internal void @[[OMP_OUTLINED_FN_3_1]]231 232// CHECK-LABEL: define void @test_omp_parallel_4()233llvm.func @test_omp_parallel_4() -> () {234// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_4_1:.*]])235// CHECK: define internal void @[[OMP_OUTLINED_FN_4_1]]236// CHECK: call void @__kmpc_barrier237// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_4_1_1:.*]])238// CHECK: call void @__kmpc_barrier239 omp.parallel {240 omp.barrier241 242// CHECK: define internal void @[[OMP_OUTLINED_FN_4_1_1]]243// CHECK: call void @__kmpc_barrier244 omp.parallel {245 omp.barrier246 omp.terminator247 }248 249 omp.barrier250 omp.terminator251 }252 llvm.return253}254 255llvm.func @test_omp_parallel_5() -> () {256// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1:.*]])257// CHECK: define internal void @[[OMP_OUTLINED_FN_5_1]]258// CHECK: call void @__kmpc_barrier259// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1_1:.*]])260// CHECK: call void @__kmpc_barrier261 omp.parallel {262 omp.barrier263 264// CHECK: define internal void @[[OMP_OUTLINED_FN_5_1_1]]265 omp.parallel {266// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1_1_1:.*]])267// CHECK: define internal void @[[OMP_OUTLINED_FN_5_1_1_1]]268// CHECK: call void @__kmpc_barrier269 omp.parallel {270 omp.barrier271 omp.terminator272 }273 omp.terminator274 }275 276 omp.barrier277 omp.terminator278 }279 llvm.return280}281 282// CHECK-LABEL: define void @test_omp_master()283llvm.func @test_omp_master() -> () {284// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @{{.*}})285// CHECK: omp.par.region1:286 omp.parallel {287 omp.master {288// CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})289// CHECK: {{[0-9]+}} = call i32 @__kmpc_master(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])290// CHECK: omp.master.region291// CHECK: call void @__kmpc_end_master(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])292// CHECK: br label %omp_region.end293 omp.terminator294 }295 omp.terminator296 }297 omp.parallel {298 omp.parallel {299 omp.master {300 omp.terminator301 }302 omp.terminator303 }304 omp.terminator305 }306 llvm.return307}308 309// -----310 311// CHECK-LABEL: define void @test_omp_masked({{.*}})312llvm.func @test_omp_masked(%arg0: i32)-> () {313// CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @{{.*}})314// CHECK: omp.par.region1:315 omp.parallel {316 omp.masked filter(%arg0: i32) {317// CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})318// CHECK: {{[0-9]+}} = call i32 @__kmpc_masked(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]], i32 %{{[0-9]+}})319// CHECK: omp.masked.region320// CHECK: call void @__kmpc_end_masked(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])321// CHECK: br label %omp_region.end322 omp.terminator323 }324 omp.terminator325 }326 llvm.return327}328 329// -----330 331// CHECK: %struct.ident_t = type332// CHECK: @[[$loc:.*]] = private unnamed_addr constant {{.*}} c";unknown;unknown;{{[0-9]+}};{{[0-9]+}};;\00"333// CHECK: @[[$loc_struct:.*]] = private unnamed_addr constant %struct.ident_t {{.*}} @[[$loc]] {{.*}}334 335// CHECK-LABEL: @wsloop_simple336llvm.func @wsloop_simple(%arg0: !llvm.ptr) {337 %0 = llvm.mlir.constant(42 : index) : i64338 %1 = llvm.mlir.constant(10 : index) : i64339 %2 = llvm.mlir.constant(1 : index) : i64340 omp.parallel {341 "omp.wsloop"() ({342 omp.loop_nest (%arg1) : i64 = (%1) to (%0) step (%2) {343 // The form of the emitted IR is controlled by OpenMPIRBuilder and344 // tested there. Just check that the right functions are called.345 // CHECK: call i32 @__kmpc_global_thread_num346 // CHECK: call void @__kmpc_for_static_init_{{.*}}(ptr @[[$loc_struct]],347 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32348 %4 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, f32349 llvm.store %3, %4 : f32, !llvm.ptr350 omp.yield351 }352 // CHECK: call void @__kmpc_for_static_fini(ptr @[[$loc_struct]],353 }) : () -> ()354 omp.terminator355 }356 llvm.return357}358 359// -----360 361// CHECK-LABEL: @wsloop_inclusive_1362llvm.func @wsloop_inclusive_1(%arg0: !llvm.ptr) {363 %0 = llvm.mlir.constant(42 : index) : i64364 %1 = llvm.mlir.constant(10 : index) : i64365 %2 = llvm.mlir.constant(1 : index) : i64366 // CHECK: store i64 31, ptr %{{.*}}upperbound367 "omp.wsloop"() ({368 omp.loop_nest (%arg1) : i64 = (%1) to (%0) step (%2) {369 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32370 %4 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, f32371 llvm.store %3, %4 : f32, !llvm.ptr372 omp.yield373 }374 }) : () -> ()375 llvm.return376}377 378// -----379 380// CHECK-LABEL: @wsloop_inclusive_2381llvm.func @wsloop_inclusive_2(%arg0: !llvm.ptr) {382 %0 = llvm.mlir.constant(42 : index) : i64383 %1 = llvm.mlir.constant(10 : index) : i64384 %2 = llvm.mlir.constant(1 : index) : i64385 // CHECK: store i64 32, ptr %{{.*}}upperbound386 "omp.wsloop"() ({387 omp.loop_nest (%arg1) : i64 = (%1) to (%0) inclusive step (%2) {388 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32389 %4 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, f32390 llvm.store %3, %4 : f32, !llvm.ptr391 omp.yield392 }393 }) : () -> ()394 llvm.return395}396 397// -----398 399llvm.func @body(i32)400 401// CHECK-LABEL: @test_omp_wsloop_static_defchunk402llvm.func @test_omp_wsloop_static_defchunk(%lb : i32, %ub : i32, %step : i32) -> () {403 omp.wsloop schedule(static) {404 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {405 // CHECK: call void @__kmpc_for_static_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 34, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i32 1, i32 0)406 // CHECK: call void @__kmpc_for_static_fini407 llvm.call @body(%iv) : (i32) -> ()408 omp.yield409 }410 }411 llvm.return412}413 414// -----415 416llvm.func @body(i32)417 418// CHECK-LABEL: @test_omp_wsloop_static_1419llvm.func @test_omp_wsloop_static_1(%lb : i32, %ub : i32, %step : i32) -> () {420 %static_chunk_size = llvm.mlir.constant(1 : i32) : i32421 omp.wsloop schedule(static = %static_chunk_size : i32) {422 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {423 // CHECK: call void @__kmpc_for_static_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 33, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i32 1, i32 1)424 // CHECK: call void @__kmpc_for_static_fini425 llvm.call @body(%iv) : (i32) -> ()426 omp.yield427 }428 }429 llvm.return430}431 432// -----433 434llvm.func @body(i32)435 436// CHECK-LABEL: @test_omp_wsloop_static_2437llvm.func @test_omp_wsloop_static_2(%lb : i32, %ub : i32, %step : i32) -> () {438 %static_chunk_size = llvm.mlir.constant(2 : i32) : i32439 omp.wsloop schedule(static = %static_chunk_size : i32) {440 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {441 // CHECK: call void @__kmpc_for_static_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 33, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i32 1, i32 2)442 // CHECK: call void @__kmpc_for_static_fini443 llvm.call @body(%iv) : (i32) -> ()444 omp.yield445 }446 }447 llvm.return448}449 450// -----451 452llvm.func @body(i64)453 454llvm.func @test_omp_wsloop_dynamic(%lb : i64, %ub : i64, %step : i64) -> () {455 omp.wsloop schedule(dynamic) {456 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {457 // CHECK: call void @__kmpc_dispatch_init_8u458 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u459 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0460 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}461 llvm.call @body(%iv) : (i64) -> ()462 omp.yield463 }464 }465 llvm.return466}467 468// -----469 470llvm.func @body(i64)471 472llvm.func @test_omp_wsloop_dynamic_chunk_const(%lb : i64, %ub : i64, %step : i64) -> () {473 %chunk_size_const = llvm.mlir.constant(2 : i16) : i16474 omp.wsloop schedule(dynamic = %chunk_size_const : i16) {475 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {476 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i64 {{.*}}, i64 %{{.*}}, i64 {{.*}}, i64 2)477 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u478 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0479 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}480 llvm.call @body(%iv) : (i64) -> ()481 omp.yield482 }483 }484 llvm.return485}486 487// -----488 489llvm.func @body(i32)490 491llvm.func @test_omp_wsloop_dynamic_chunk_var(%lb : i32, %ub : i32, %step : i32) -> () {492 %1 = llvm.mlir.constant(1 : i64) : i64493 %chunk_size_alloca = llvm.alloca %1 x i16 {bindc_name = "chunk_size", in_type = i16, uniq_name = "_QFsub1Echunk_size"} : (i64) -> !llvm.ptr494 %chunk_size_var = llvm.load %chunk_size_alloca : !llvm.ptr -> i16495 omp.wsloop schedule(dynamic = %chunk_size_var : i16) {496 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {497 // CHECK: %[[CHUNK_SIZE:.*]] = sext i16 %{{.*}} to i32498 // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i32 {{.*}}, i32 %{{.*}}, i32 {{.*}}, i32 %[[CHUNK_SIZE]])499 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u500 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0501 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}502 llvm.call @body(%iv) : (i32) -> ()503 omp.yield504 }505 }506 llvm.return507}508 509// -----510 511llvm.func @body(i32)512 513llvm.func @test_omp_wsloop_dynamic_chunk_var2(%lb : i32, %ub : i32, %step : i32) -> () {514 %1 = llvm.mlir.constant(1 : i64) : i64515 %chunk_size_alloca = llvm.alloca %1 x i64 {bindc_name = "chunk_size", in_type = i64, uniq_name = "_QFsub1Echunk_size"} : (i64) -> !llvm.ptr516 %chunk_size_var = llvm.load %chunk_size_alloca : !llvm.ptr -> i64517 omp.wsloop schedule(dynamic = %chunk_size_var : i64) {518 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {519 // CHECK: %[[CHUNK_SIZE:.*]] = trunc i64 %{{.*}} to i32520 // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i32 {{.*}}, i32 %{{.*}}, i32 {{.*}}, i32 %[[CHUNK_SIZE]])521 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u522 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0523 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}524 llvm.call @body(%iv) : (i32) -> ()525 omp.yield526 }527 }528 llvm.return529}530 531// -----532 533llvm.func @body(i32)534 535llvm.func @test_omp_wsloop_dynamic_chunk_var3(%lb : i32, %ub : i32, %step : i32, %chunk_size : i32) -> () {536 omp.wsloop schedule(dynamic = %chunk_size : i32) {537 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {538 // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i32 {{.*}}, i32 %{{.*}}, i32 {{.*}}, i32 %{{.*}})539 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u540 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0541 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}542 llvm.call @body(%iv) : (i32) -> ()543 omp.yield544 }545 }546 llvm.return547}548 549// -----550 551llvm.func @body(i64)552 553llvm.func @test_omp_wsloop_auto(%lb : i64, %ub : i64, %step : i64) -> () {554 omp.wsloop schedule(auto) {555 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {556 // CHECK: call void @__kmpc_dispatch_init_8u557 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u558 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0559 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}560 llvm.call @body(%iv) : (i64) -> ()561 omp.yield562 }563 }564 llvm.return565}566 567// -----568 569llvm.func @body(i64)570 571llvm.func @test_omp_wsloop_runtime(%lb : i64, %ub : i64, %step : i64) -> () {572 omp.wsloop schedule(runtime) {573 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {574 // CHECK: call void @__kmpc_dispatch_init_8u575 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u576 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0577 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}578 llvm.call @body(%iv) : (i64) -> ()579 omp.yield580 }581 }582 llvm.return583}584 585// -----586 587llvm.func @body(i64)588 589llvm.func @test_omp_wsloop_guided(%lb : i64, %ub : i64, %step : i64) -> () {590 omp.wsloop schedule(guided) {591 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {592 // CHECK: call void @__kmpc_dispatch_init_8u593 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u594 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0595 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}596 llvm.call @body(%iv) : (i64) -> ()597 omp.yield598 }599 }600 llvm.return601}602 603// -----604 605llvm.func @body(i64)606 607llvm.func @test_omp_wsloop_dynamic_nonmonotonic(%lb : i64, %ub : i64, %step : i64) -> () {608 omp.wsloop schedule(dynamic, nonmonotonic) {609 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {610 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859611 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u612 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0613 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}614 llvm.call @body(%iv) : (i64) -> ()615 omp.yield616 }617 }618 llvm.return619}620 621// -----622 623llvm.func @body(i64)624 625llvm.func @test_omp_wsloop_dynamic_monotonic(%lb : i64, %ub : i64, %step : i64) -> () {626 omp.wsloop schedule(dynamic, monotonic) {627 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {628 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 536870947629 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u630 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0631 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}632 llvm.call @body(%iv) : (i64) -> ()633 omp.yield634 }635 }636 llvm.return637}638 639// -----640 641llvm.func @body(i64)642 643llvm.func @test_omp_wsloop_runtime_simd(%lb : i64, %ub : i64, %step : i64) -> () {644 omp.wsloop schedule(runtime, simd) {645 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {646 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741871647 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u648 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0649 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}650 llvm.call @body(%iv) : (i64) -> ()651 omp.yield652 }653 }654 llvm.return655}656 657// -----658 659llvm.func @body(i64)660 661llvm.func @test_omp_wsloop_guided_simd(%lb : i64, %ub : i64, %step : i64) -> () {662 omp.wsloop schedule(guided, simd) {663 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {664 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741870665 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u666 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0667 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}668 llvm.call @body(%iv) : (i64) -> ()669 omp.yield670 }671 }672 llvm.return673}674 675// -----676 677// CHECK-LABEL: @simd_simple678llvm.func @simd_simple(%lb : i64, %ub : i64, %step : i64, %arg0: !llvm.ptr) {679 "omp.simd" () ({680 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {681 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32682 // The form of the emitted IR is controlled by OpenMPIRBuilder and683 // tested there. Just check that the right metadata is added.684 // CHECK: llvm.access.group685 %4 = llvm.getelementptr %arg0[%iv] : (!llvm.ptr, i64) -> !llvm.ptr, f32686 llvm.store %3, %4 : f32, !llvm.ptr687 omp.yield688 }689 }) : () -> ()690 691 llvm.return692}693// CHECK: llvm.loop.parallel_accesses694// CHECK-NEXT: llvm.loop.vectorize.enable695 696// -----697 698// CHECK-LABEL: @simd_simple_multiple699llvm.func @simd_simple_multiple(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {700 omp.simd {701 omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) inclusive step (%step1, %step2) collapse(2) {702 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32703 // The form of the emitted IR is controlled by OpenMPIRBuilder and704 // tested there. Just check that the right metadata is added and collapsed705 // loop bound is generated (Collapse clause is represented as a loop with706 // list of indices, bounds and steps where the size of the list is equal707 // to the collapse value.)708 // CHECK: icmp slt i64709 // CHECK-COUNT-3: select710 // CHECK: %[[TRIPCOUNT0:.*]] = select711 // CHECK: br label %[[PREHEADER:.*]]712 // CHECK: [[PREHEADER]]:713 // CHECK: icmp slt i64714 // CHECK-COUNT-3: select715 // CHECK: %[[TRIPCOUNT1:.*]] = select716 // CHECK: mul nuw i64 %[[TRIPCOUNT0]], %[[TRIPCOUNT1]]717 // CHECK: br label %[[COLLAPSED_PREHEADER:.*]]718 // CHECK: [[COLLAPSED_PREHEADER]]:719 // CHECK: br label %[[COLLAPSED_HEADER:.*]]720 // CHECK: llvm.access.group721 // CHECK-NEXT: llvm.access.group722 %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32723 %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32724 llvm.store %3, %4 : f32, !llvm.ptr725 llvm.store %3, %5 : f32, !llvm.ptr726 omp.yield727 }728 }729 llvm.return730}731// CHECK: llvm.loop.parallel_accesses732// CHECK-NEXT: llvm.loop.vectorize.enable733 734// -----735 736// CHECK-LABEL: @simd_simple_multiple_simdlen737llvm.func @simd_simple_multiple_simdlen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {738 omp.simd simdlen(2) {739 omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) collapse(2) {740 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32741 // The form of the emitted IR is controlled by OpenMPIRBuilder and742 // tested there. Just check that the right metadata is added.743 // CHECK: llvm.access.group744 // CHECK-NEXT: llvm.access.group745 %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32746 %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32747 llvm.store %3, %4 : f32, !llvm.ptr748 llvm.store %3, %5 : f32, !llvm.ptr749 omp.yield750 }751 }752 llvm.return753}754// CHECK: llvm.loop.parallel_accesses755// CHECK-NEXT: llvm.loop.vectorize.enable756// CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2757 758// -----759 760// CHECK-LABEL: @simd_simple_multiple_safelen761llvm.func @simd_simple_multiple_safelen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {762 omp.simd safelen(2) {763 omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) collapse(2) {764 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32765 %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32766 %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32767 llvm.store %3, %4 : f32, !llvm.ptr768 llvm.store %3, %5 : f32, !llvm.ptr769 omp.yield770 }771 }772 llvm.return773}774// CHECK: llvm.loop.vectorize.enable775// CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2776 777// -----778 779// CHECK-LABEL: @simd_simple_multiple_simdlen_safelen780llvm.func @simd_simple_multiple_simdlen_safelen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {781 omp.simd simdlen(1) safelen(2) {782 omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) collapse(2) {783 %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32784 %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32785 %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32786 llvm.store %3, %4 : f32, !llvm.ptr787 llvm.store %3, %5 : f32, !llvm.ptr788 omp.yield789 }790 }791 llvm.return792}793// CHECK: llvm.loop.vectorize.enable794// CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 1795 796// -----797 798// CHECK-LABEL: @simd_if799llvm.func @simd_if(%arg0: !llvm.ptr {fir.bindc_name = "n"}, %arg1: !llvm.ptr {fir.bindc_name = "threshold"}) {800 %0 = llvm.mlir.constant(1 : i64) : i64801 %1 = llvm.alloca %0 x i32 {adapt.valuebyref, in_type = i32, operandSegmentSizes = array<i32: 0, 0>} : (i64) -> !llvm.ptr802 %2 = llvm.mlir.constant(1 : i64) : i64803 %3 = llvm.alloca %2 x i32 {bindc_name = "i", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFtest_simdEi"} : (i64) -> !llvm.ptr804 %4 = llvm.mlir.constant(0 : i32) : i32805 %5 = llvm.load %arg0 : !llvm.ptr -> i32806 %6 = llvm.mlir.constant(1 : i32) : i32807 %7 = llvm.load %arg0 : !llvm.ptr -> i32808 %8 = llvm.load %arg1 : !llvm.ptr -> i32809 %9 = llvm.icmp "sge" %7, %8 : i32810 omp.simd if(%9) {811 omp.loop_nest (%arg2) : i32 = (%4) to (%5) inclusive step (%6) {812 // The form of the emitted IR is controlled by OpenMPIRBuilder and813 // tested there. Just check that the right metadata is added.814 // CHECK: llvm.access.group815 llvm.store %arg2, %1 : i32, !llvm.ptr816 omp.yield817 }818 }819 llvm.return820}821// Be sure that llvm.loop.vectorize.enable metadata appears twice822// CHECK: llvm.loop.parallel_accesses823 824// -----825 826// CHECK-LABEL: @simd_order827llvm.func @simd_order() {828 %0 = llvm.mlir.constant(10 : i64) : i64829 %1 = llvm.mlir.constant(1 : i64) : i64830 %2 = llvm.alloca %1 x i64 : (i64) -> !llvm.ptr831 omp.simd order(concurrent) safelen(2) {832 omp.loop_nest (%arg0) : i64 = (%1) to (%0) inclusive step (%1) {833 llvm.store %arg0, %2 : i64, !llvm.ptr834 omp.yield835 }836 }837 llvm.return838}839// If clause order(concurrent) is specified then the memory instructions840// are marked parallel even if 'safelen' is finite.841// CHECK: llvm.loop.parallel_accesses842// CHECK-NEXT: llvm.loop.vectorize.enable843// CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2844// -----845 846llvm.func @body(i64)847 848llvm.func @test_omp_wsloop_ordered(%lb : i64, %ub : i64, %step : i64) -> () {849 omp.wsloop ordered(0) {850 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {851 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 66, i64 1, i64 %{{.*}}, i64 1, i64 1)852 // CHECK: call void @__kmpc_dispatch_fini_8u853 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u854 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0855 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}856 llvm.call @body(%iv) : (i64) -> ()857 omp.yield858 }859 }860 llvm.return861}862 863// -----864 865llvm.func @body(i64)866 867llvm.func @test_omp_wsloop_static_ordered(%lb : i64, %ub : i64, %step : i64) -> () {868 omp.wsloop schedule(static) ordered(0) {869 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {870 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 66, i64 1, i64 %{{.*}}, i64 1, i64 1)871 // CHECK: call void @__kmpc_dispatch_fini_8u872 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u873 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0874 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}875 llvm.call @body(%iv) : (i64) -> ()876 omp.yield877 }878 }879 llvm.return880}881 882// -----883 884llvm.func @body(i32)885 886llvm.func @test_omp_wsloop_static_chunk_ordered(%lb : i32, %ub : i32, %step : i32) -> () {887 %static_chunk_size = llvm.mlir.constant(1 : i32) : i32888 omp.wsloop schedule(static = %static_chunk_size : i32) ordered(0) {889 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {890 // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 65, i32 1, i32 %{{.*}}, i32 1, i32 1)891 // CHECK: call void @__kmpc_dispatch_fini_4u892 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u893 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0894 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}895 llvm.call @body(%iv) : (i32) -> ()896 omp.yield897 }898 }899 llvm.return900}901 902// -----903 904llvm.func @body(i64)905 906llvm.func @test_omp_wsloop_dynamic_ordered(%lb : i64, %ub : i64, %step : i64) -> () {907 omp.wsloop schedule(dynamic) ordered(0) {908 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {909 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 67, i64 1, i64 %{{.*}}, i64 1, i64 1)910 // CHECK: call void @__kmpc_dispatch_fini_8u911 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u912 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0913 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}914 llvm.call @body(%iv) : (i64) -> ()915 omp.yield916 }917 }918 llvm.return919}920 921// -----922 923llvm.func @body(i64)924 925llvm.func @test_omp_wsloop_auto_ordered(%lb : i64, %ub : i64, %step : i64) -> () {926 omp.wsloop schedule(auto) ordered(0) {927 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {928 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 70, i64 1, i64 %{{.*}}, i64 1, i64 1)929 // CHECK: call void @__kmpc_dispatch_fini_8u930 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u931 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0932 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}933 llvm.call @body(%iv) : (i64) -> ()934 omp.yield935 }936 }937 llvm.return938}939 940// -----941 942llvm.func @body(i64)943 944llvm.func @test_omp_wsloop_runtime_ordered(%lb : i64, %ub : i64, %step : i64) -> () {945 omp.wsloop schedule(runtime) ordered(0) {946 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {947 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 69, i64 1, i64 %{{.*}}, i64 1, i64 1)948 // CHECK: call void @__kmpc_dispatch_fini_8u949 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u950 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0951 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}952 llvm.call @body(%iv) : (i64) -> ()953 omp.yield954 }955 }956 llvm.return957}958 959// -----960 961llvm.func @body(i64)962 963llvm.func @test_omp_wsloop_guided_ordered(%lb : i64, %ub : i64, %step : i64) -> () {964 omp.wsloop schedule(guided) ordered(0) {965 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {966 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 68, i64 1, i64 %{{.*}}, i64 1, i64 1)967 // CHECK: call void @__kmpc_dispatch_fini_8u968 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u969 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0970 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}971 llvm.call @body(%iv) : (i64) -> ()972 omp.yield973 }974 }975 llvm.return976}977 978// -----979 980llvm.func @body(i64)981 982llvm.func @test_omp_wsloop_dynamic_nonmonotonic_ordered(%lb : i64, %ub : i64, %step : i64) -> () {983 omp.wsloop schedule(dynamic, nonmonotonic) ordered(0) {984 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {985 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741891, i64 1, i64 %{{.*}}, i64 1, i64 1)986 // CHECK: call void @__kmpc_dispatch_fini_8u987 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u988 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0989 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}990 llvm.call @body(%iv) : (i64) -> ()991 omp.yield992 }993 }994 llvm.return995}996 997// -----998 999llvm.func @body(i64)1000 1001llvm.func @test_omp_wsloop_dynamic_monotonic_ordered(%lb : i64, %ub : i64, %step : i64) -> () {1002 omp.wsloop schedule(dynamic, monotonic) ordered(0) {1003 omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {1004 // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 536870979, i64 1, i64 %{{.*}}, i64 1, i64 1)1005 // CHECK: call void @__kmpc_dispatch_fini_8u1006 // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u1007 // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 01008 // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}1009 llvm.call @body(%iv) : (i64) -> ()1010 omp.yield1011 }1012 }1013 llvm.return1014}1015 1016// -----1017 1018omp.critical.declare @mutex_none hint(none) // 01019omp.critical.declare @mutex_uncontended hint(uncontended) // 11020omp.critical.declare @mutex_contended hint(contended) // 21021omp.critical.declare @mutex_nonspeculative hint(nonspeculative) // 41022omp.critical.declare @mutex_nonspeculative_uncontended hint(nonspeculative, uncontended) // 51023omp.critical.declare @mutex_nonspeculative_contended hint(nonspeculative, contended) // 61024omp.critical.declare @mutex_speculative hint(speculative) // 81025omp.critical.declare @mutex_speculative_uncontended hint(speculative, uncontended) // 91026omp.critical.declare @mutex_speculative_contended hint(speculative, contended) // 101027 1028// CHECK-LABEL: @omp_critical1029llvm.func @omp_critical(%x : !llvm.ptr, %xval : i32) -> () {1030 // CHECK: call void @__kmpc_critical({{.*}}critical_user_.var{{.*}})1031 // CHECK: br label %omp.critical.region1032 // CHECK: omp.critical.region1033 omp.critical {1034 // CHECK: store1035 llvm.store %xval, %x : i32, !llvm.ptr1036 omp.terminator1037 }1038 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_.var{{.*}})1039 1040 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_none.var{{.*}}, i32 0)1041 // CHECK: br label %omp.critical.region1042 // CHECK: omp.critical.region1043 omp.critical(@mutex_none) {1044 // CHECK: store1045 llvm.store %xval, %x : i32, !llvm.ptr1046 omp.terminator1047 }1048 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_none.var{{.*}})1049 1050 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_uncontended.var{{.*}}, i32 1)1051 // CHECK: br label %omp.critical.region1052 // CHECK: omp.critical.region1053 omp.critical(@mutex_uncontended) {1054 // CHECK: store1055 llvm.store %xval, %x : i32, !llvm.ptr1056 omp.terminator1057 }1058 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_uncontended.var{{.*}})1059 1060 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_contended.var{{.*}}, i32 2)1061 // CHECK: br label %omp.critical.region1062 // CHECK: omp.critical.region1063 omp.critical(@mutex_contended) {1064 // CHECK: store1065 llvm.store %xval, %x : i32, !llvm.ptr1066 omp.terminator1067 }1068 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_contended.var{{.*}})1069 1070 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative.var{{.*}}, i32 4)1071 // CHECK: br label %omp.critical.region1072 // CHECK: omp.critical.region1073 omp.critical(@mutex_nonspeculative) {1074 // CHECK: store1075 llvm.store %xval, %x : i32, !llvm.ptr1076 omp.terminator1077 }1078 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative.var{{.*}})1079 1080 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative_uncontended.var{{.*}}, i32 5)1081 // CHECK: br label %omp.critical.region1082 // CHECK: omp.critical.region1083 omp.critical(@mutex_nonspeculative_uncontended) {1084 // CHECK: store1085 llvm.store %xval, %x : i32, !llvm.ptr1086 omp.terminator1087 }1088 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative_uncontended.var{{.*}})1089 1090 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative_contended.var{{.*}}, i32 6)1091 // CHECK: br label %omp.critical.region1092 // CHECK: omp.critical.region1093 omp.critical(@mutex_nonspeculative_contended) {1094 // CHECK: store1095 llvm.store %xval, %x : i32, !llvm.ptr1096 omp.terminator1097 }1098 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative_contended.var{{.*}})1099 1100 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative.var{{.*}}, i32 8)1101 // CHECK: br label %omp.critical.region1102 // CHECK: omp.critical.region1103 omp.critical(@mutex_speculative) {1104 // CHECK: store1105 llvm.store %xval, %x : i32, !llvm.ptr1106 omp.terminator1107 }1108 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative.var{{.*}})1109 1110 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative_uncontended.var{{.*}}, i32 9)1111 // CHECK: br label %omp.critical.region1112 // CHECK: omp.critical.region1113 omp.critical(@mutex_speculative_uncontended) {1114 // CHECK: store1115 llvm.store %xval, %x : i32, !llvm.ptr1116 omp.terminator1117 }1118 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_uncontended.var{{.*}})1119 1120 // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative_contended.var{{.*}}, i32 10)1121 // CHECK: br label %omp.critical.region1122 // CHECK: omp.critical.region1123 omp.critical(@mutex_speculative_contended) {1124 // CHECK: store1125 llvm.store %xval, %x : i32, !llvm.ptr1126 omp.terminator1127 }1128 // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_contended.var{{.*}})1129 llvm.return1130}1131 1132// -----1133 1134// Check that the loop bounds are emitted in the correct location in case of1135// collapse. This only checks the overall shape of the IR, detailed checking1136// is done by the OpenMPIRBuilder.1137 1138// CHECK-LABEL: @collapse_wsloop1139// CHECK: ptr noalias %[[TIDADDR:[0-9A-Za-z.]*]]1140// CHECK: load i32, ptr %[[TIDADDR]]1141// CHECK: store1142// CHECK: load1143// CHECK: %[[LB0:.*]] = load i321144// CHECK: %[[UB0:.*]] = load i321145// CHECK: %[[STEP0:.*]] = load i321146// CHECK: %[[LB1:.*]] = load i321147// CHECK: %[[UB1:.*]] = load i321148// CHECK: %[[STEP1:.*]] = load i321149// CHECK: %[[LB2:.*]] = load i321150// CHECK: %[[UB2:.*]] = load i321151// CHECK: %[[STEP2:.*]] = load i321152llvm.func @collapse_wsloop(1153 %0: i32, %1: i32, %2: i32,1154 %3: i32, %4: i32, %5: i32,1155 %6: i32, %7: i32, %8: i32,1156 %20: !llvm.ptr) {1157 omp.parallel {1158 // CHECK: icmp slt i32 %[[LB0]], 01159 // CHECK-COUNT-4: select1160 // CHECK: %[[TRIPCOUNT0:.*]] = select1161 // CHECK: br label %[[PREHEADER:.*]]1162 //1163 // CHECK: [[PREHEADER]]:1164 // CHECK: icmp slt i32 %[[LB1]], 01165 // CHECK-COUNT-4: select1166 // CHECK: %[[TRIPCOUNT1:.*]] = select1167 // CHECK: icmp slt i32 %[[LB2]], 01168 // CHECK-COUNT-4: select1169 // CHECK: %[[TRIPCOUNT2:.*]] = select1170 // CHECK: %[[PROD:.*]] = mul nuw i32 %[[TRIPCOUNT0]], %[[TRIPCOUNT1]]1171 // CHECK: %[[TOTAL:.*]] = mul nuw i32 %[[PROD]], %[[TRIPCOUNT2]]1172 // CHECK: br label %[[COLLAPSED_PREHEADER:.*]]1173 //1174 // CHECK: [[COLLAPSED_PREHEADER]]:1175 // CHECK: store i32 0, ptr1176 // CHECK: %[[TOTAL_SUB_1:.*]] = sub i32 %[[TOTAL]], 11177 // CHECK: store i32 %[[TOTAL_SUB_1]], ptr1178 // CHECK: call void @__kmpc_for_static_init_4u1179 omp.wsloop {1180 omp.loop_nest (%arg0, %arg1, %arg2) : i32 = (%0, %1, %2) to (%3, %4, %5) step (%6, %7, %8) collapse(3) {1181 %31 = llvm.load %20 : !llvm.ptr -> i321182 %32 = llvm.add %31, %arg0 : i321183 %33 = llvm.add %32, %arg1 : i321184 %34 = llvm.add %33, %arg2 : i321185 llvm.store %34, %20 : i32, !llvm.ptr1186 omp.yield1187 }1188 }1189 omp.terminator1190 }1191 llvm.return1192}1193 1194// -----1195 1196// Check that the loop bounds are emitted in the correct location in case of1197// collapse for dynamic schedule. This only checks the overall shape of the IR,1198// detailed checking is done by the OpenMPIRBuilder.1199 1200// CHECK-LABEL: @collapse_wsloop_dynamic1201// CHECK: ptr noalias %[[TIDADDR:[0-9A-Za-z.]*]]1202// CHECK: load i32, ptr %[[TIDADDR]]1203// CHECK: store1204// CHECK: load1205// CHECK: %[[LB0:.*]] = load i321206// CHECK: %[[UB0:.*]] = load i321207// CHECK: %[[STEP0:.*]] = load i321208// CHECK: %[[LB1:.*]] = load i321209// CHECK: %[[UB1:.*]] = load i321210// CHECK: %[[STEP1:.*]] = load i321211// CHECK: %[[LB2:.*]] = load i321212// CHECK: %[[UB2:.*]] = load i321213// CHECK: %[[STEP2:.*]] = load i321214 1215llvm.func @collapse_wsloop_dynamic(1216 %0: i32, %1: i32, %2: i32,1217 %3: i32, %4: i32, %5: i32,1218 %6: i32, %7: i32, %8: i32,1219 %20: !llvm.ptr) {1220 omp.parallel {1221 // CHECK: icmp slt i32 %[[LB0]], 01222 // CHECK-COUNT-4: select1223 // CHECK: %[[TRIPCOUNT0:.*]] = select1224 // CHECK: br label %[[PREHEADER:.*]]1225 //1226 // CHECK: [[PREHEADER]]:1227 // CHECK: icmp slt i32 %[[LB1]], 01228 // CHECK-COUNT-4: select1229 // CHECK: %[[TRIPCOUNT1:.*]] = select1230 // CHECK: icmp slt i32 %[[LB2]], 01231 // CHECK-COUNT-4: select1232 // CHECK: %[[TRIPCOUNT2:.*]] = select1233 // CHECK: %[[PROD:.*]] = mul nuw i32 %[[TRIPCOUNT0]], %[[TRIPCOUNT1]]1234 // CHECK: %[[TOTAL:.*]] = mul nuw i32 %[[PROD]], %[[TRIPCOUNT2]]1235 // CHECK: br label %[[COLLAPSED_PREHEADER:.*]]1236 //1237 // CHECK: [[COLLAPSED_PREHEADER]]:1238 // CHECK: store i32 1, ptr1239 // CHECK: store i32 %[[TOTAL]], ptr1240 // CHECK: call void @__kmpc_dispatch_init_4u1241 omp.wsloop schedule(dynamic) {1242 omp.loop_nest (%arg0, %arg1, %arg2) : i32 = (%0, %1, %2) to (%3, %4, %5) step (%6, %7, %8) collapse(3) {1243 %31 = llvm.load %20 : !llvm.ptr -> i321244 %32 = llvm.add %31, %arg0 : i321245 %33 = llvm.add %32, %arg1 : i321246 %34 = llvm.add %33, %arg2 : i321247 llvm.store %34, %20 : i32, !llvm.ptr1248 omp.yield1249 }1250 }1251 omp.terminator1252 }1253 llvm.return1254}1255 1256// -----1257 1258// CHECK-LABEL: @omp_ordered1259llvm.func @omp_ordered(%arg0 : i32, %arg1 : i32, %arg2 : i32, %arg3 : i64,1260 %arg4: i64, %arg5: i64, %arg6: i64) -> () {1261 // CHECK: [[ADDR9:%.*]] = alloca [2 x i64], align 81262 // CHECK: [[ADDR7:%.*]] = alloca [2 x i64], align 81263 // CHECK: [[ADDR5:%.*]] = alloca [2 x i64], align 81264 // CHECK: [[ADDR3:%.*]] = alloca [1 x i64], align 81265 // CHECK: [[ADDR:%.*]] = alloca [1 x i64], align 81266 1267 // CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]])1268 // CHECK-NEXT: call void @__kmpc_ordered(ptr @[[GLOB1]], i32 [[OMP_THREAD]])1269 omp.ordered.region {1270 omp.terminator1271 // CHECK: call void @__kmpc_end_ordered(ptr @[[GLOB1]], i32 [[OMP_THREAD]])1272 }1273 1274 omp.wsloop ordered(0) {1275 omp.loop_nest (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) {1276 // CHECK: call void @__kmpc_ordered(ptr @[[GLOB3:[0-9]+]], i32 [[OMP_THREAD2:%.*]])1277 omp.ordered.region {1278 omp.terminator1279 // CHECK: call void @__kmpc_end_ordered(ptr @[[GLOB3]], i32 [[OMP_THREAD2]])1280 }1281 omp.yield1282 }1283 }1284 1285 omp.wsloop ordered(1) {1286 omp.loop_nest (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) {1287 // CHECK: [[TMP:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR]], i64 0, i64 01288 // CHECK: store i64 [[ARG0:%.*]], ptr [[TMP]], align 81289 // CHECK: [[TMP2:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR]], i64 0, i64 01290 // CHECK: [[OMP_THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB3:[0-9]+]])1291 // CHECK: call void @__kmpc_doacross_wait(ptr @[[GLOB3]], i32 [[OMP_THREAD2]], ptr [[TMP2]])1292 omp.ordered depend_type(dependsink) depend_vec(%arg3 : i64) {doacross_num_loops = 1 : i64}1293 1294 // CHECK: [[TMP3:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR3]], i64 0, i64 01295 // CHECK: store i64 [[ARG0]], ptr [[TMP3]], align 81296 // CHECK: [[TMP4:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR3]], i64 0, i64 01297 // CHECK: [[OMP_THREAD4:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB5:[0-9]+]])1298 // CHECK: call void @__kmpc_doacross_post(ptr @[[GLOB5]], i32 [[OMP_THREAD4]], ptr [[TMP4]])1299 omp.ordered depend_type(dependsource) depend_vec(%arg3 : i64) {doacross_num_loops = 1 : i64}1300 1301 omp.yield1302 }1303 }1304 1305 omp.wsloop ordered(2) {1306 omp.loop_nest (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) {1307 // CHECK: [[TMP5:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR5]], i64 0, i64 01308 // CHECK: store i64 [[ARG0]], ptr [[TMP5]], align 81309 // CHECK: [[TMP6:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR5]], i64 0, i64 11310 // CHECK: store i64 [[ARG1:%.*]], ptr [[TMP6]], align 81311 // CHECK: [[TMP7:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR5]], i64 0, i64 01312 // CHECK: [[OMP_THREAD6:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB7:[0-9]+]])1313 // CHECK: call void @__kmpc_doacross_wait(ptr @[[GLOB7]], i32 [[OMP_THREAD6]], ptr [[TMP7]])1314 // CHECK: [[TMP8:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR7]], i64 0, i64 01315 // CHECK: store i64 [[ARG2:%.*]], ptr [[TMP8]], align 81316 // CHECK: [[TMP9:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR7]], i64 0, i64 11317 // CHECK: store i64 [[ARG3:%.*]], ptr [[TMP9]], align 81318 // CHECK: [[TMP10:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR7]], i64 0, i64 01319 // CHECK: [[OMP_THREAD8:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB7]])1320 // CHECK: call void @__kmpc_doacross_wait(ptr @[[GLOB7]], i32 [[OMP_THREAD8]], ptr [[TMP10]])1321 omp.ordered depend_type(dependsink) depend_vec(%arg3, %arg4, %arg5, %arg6 : i64, i64, i64, i64) {doacross_num_loops = 2 : i64}1322 1323 // CHECK: [[TMP11:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR9]], i64 0, i64 01324 // CHECK: store i64 [[ARG0]], ptr [[TMP11]], align 81325 // CHECK: [[TMP12:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR9]], i64 0, i64 11326 // CHECK: store i64 [[ARG1]], ptr [[TMP12]], align 81327 // CHECK: [[TMP13:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR9]], i64 0, i64 01328 // CHECK: [[OMP_THREAD10:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB9:[0-9]+]])1329 // CHECK: call void @__kmpc_doacross_post(ptr @[[GLOB9]], i32 [[OMP_THREAD10]], ptr [[TMP13]])1330 omp.ordered depend_type(dependsource) depend_vec(%arg3, %arg4 : i64, i64) {doacross_num_loops = 2 : i64}1331 1332 omp.yield1333 }1334 }1335 1336 llvm.return1337}1338 1339// -----1340 1341// CHECK-LABEL: @omp_atomic_read1342// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])1343llvm.func @omp_atomic_read(%arg0 : !llvm.ptr, %arg1 : !llvm.ptr) -> () {1344 1345 // CHECK: %[[X1:.*]] = load atomic i32, ptr %[[ARG0]] monotonic, align 41346 // CHECK: store i32 %[[X1]], ptr %[[ARG1]], align 41347 omp.atomic.read %arg1 = %arg0 : !llvm.ptr, !llvm.ptr, i321348 1349 // CHECK: %[[X2:.*]] = load atomic i32, ptr %[[ARG0]] seq_cst, align 41350 // CHECK: call void @__kmpc_flush(ptr @{{.*}})1351 // CHECK: store i32 %[[X2]], ptr %[[ARG1]], align 41352 omp.atomic.read %arg1 = %arg0 memory_order(seq_cst) : !llvm.ptr, !llvm.ptr, i321353 1354 // CHECK: %[[X3:.*]] = load atomic i32, ptr %[[ARG0]] acquire, align 41355 // CHECK: call void @__kmpc_flush(ptr @{{.*}})1356 // CHECK: store i32 %[[X3]], ptr %[[ARG1]], align 41357 omp.atomic.read %arg1 = %arg0 memory_order(acquire) : !llvm.ptr, !llvm.ptr, i321358 1359 // CHECK: %[[X4:.*]] = load atomic i32, ptr %[[ARG0]] monotonic, align 41360 // CHECK: store i32 %[[X4]], ptr %[[ARG1]], align 41361 omp.atomic.read %arg1 = %arg0 memory_order(relaxed) : !llvm.ptr, !llvm.ptr, i321362 llvm.return1363}1364 1365// -----1366 1367// CHECK-LABEL: @omp_atomic_read_implicit_cast1368llvm.func @omp_atomic_read_implicit_cast () {1369//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = alloca { float, float }, align 81370//CHECK: %[[Z:.*]] = alloca float, i64 1, align 41371//CHECK: %[[Y:.*]] = alloca double, i64 1, align 81372//CHECK: %[[X:.*]] = alloca [2 x { float, float }], i64 1, align 81373//CHECK: %[[W:.*]] = alloca i32, i64 1, align 41374//CHECK: %[[X_ELEMENT:.*]] = getelementptr { float, float }, ptr %3, i64 01375 %0 = llvm.mlir.constant(1 : i64) : i641376 %1 = llvm.alloca %0 x f32 {bindc_name = "z"} : (i64) -> !llvm.ptr1377 %2 = llvm.mlir.constant(1 : i64) : i641378 %3 = llvm.alloca %2 x f64 {bindc_name = "y"} : (i64) -> !llvm.ptr1379 %4 = llvm.mlir.constant(1 : i64) : i641380 %5 = llvm.alloca %4 x !llvm.array<2 x struct<(f32, f32)>> {bindc_name = "x"} : (i64) -> !llvm.ptr1381 %6 = llvm.mlir.constant(1 : i64) : i641382 %7 = llvm.alloca %6 x i32 {bindc_name = "w"} : (i64) -> !llvm.ptr1383 %8 = llvm.mlir.constant(1 : index) : i641384 %9 = llvm.mlir.constant(2 : index) : i641385 %10 = llvm.mlir.constant(1 : i64) : i641386 %11 = llvm.mlir.constant(0 : i64) : i641387 %12 = llvm.sub %8, %10 overflow<nsw> : i641388 %13 = llvm.mul %12, %10 overflow<nsw> : i641389 %14 = llvm.mul %13, %10 overflow<nsw> : i641390 %15 = llvm.add %14, %11 overflow<nsw> : i641391 %16 = llvm.mul %10, %9 overflow<nsw> : i641392 %17 = llvm.getelementptr %5[%15] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(f32, f32)>1393 1394 1395//CHECK: call void @__atomic_load(i64 8, ptr %[[X_ELEMENT]], ptr %[[ATOMIC_LOAD_TEMP]], i32 0)1396//CHECK: %[[LOAD:.*]] = load { float, float }, ptr %[[ATOMIC_LOAD_TEMP]], align 81397//CHECK: store { float, float } %[[LOAD]], ptr %[[Y]], align 41398 omp.atomic.read %3 = %17 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>1399 1400//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[Z]] monotonic, align 41401//CHECK: %[[CAST:.*]] = bitcast i32 %[[ATOMIC_LOAD_TEMP]] to float1402//CHECK: store float %[[CAST]], ptr %[[Y]], align 41403 omp.atomic.read %3 = %1 : !llvm.ptr, !llvm.ptr, f321404 1405//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[W]] monotonic, align 41406//CHECK: store i32 %[[ATOMIC_LOAD_TEMP]], ptr %[[Y]], align 41407 omp.atomic.read %3 = %7 : !llvm.ptr, !llvm.ptr, i321408 1409//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i64, ptr %[[Y]] monotonic, align 41410//CHECK: %[[CAST:.*]] = bitcast i64 %[[ATOMIC_LOAD_TEMP]] to double1411//CHECK: store double %[[CAST]], ptr %[[Z]], align 81412 omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, f641413 1414//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[W]] monotonic, align 41415//CHECK: store i32 %[[ATOMIC_LOAD_TEMP]], ptr %[[Z]], align 41416 omp.atomic.read %1 = %7 : !llvm.ptr, !llvm.ptr, i321417 1418//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i64, ptr %[[Y]] monotonic, align 41419//CHECK: %[[CAST:.*]] = bitcast i64 %[[ATOMIC_LOAD_TEMP]] to double1420//CHECK: store double %[[CAST]], ptr %[[W]], align 81421 omp.atomic.read %7 = %3 : !llvm.ptr, !llvm.ptr, f641422 1423//CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[Z]] monotonic, align 41424//CHECK: %[[CAST:.*]] = bitcast i32 %[[ATOMIC_LOAD_TEMP]] to float1425//CHECK: store float %[[CAST]], ptr %[[W]], align 41426 omp.atomic.read %7 = %1 : !llvm.ptr, !llvm.ptr, f321427 llvm.return1428}1429 1430// -----1431 1432// CHECK-LABEL: @omp_atomic_write1433// CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])1434llvm.func @omp_atomic_write(%x: !llvm.ptr, %expr: i32) -> () {1435 // CHECK: store atomic i32 %[[expr]], ptr %[[x]] monotonic, align 41436 omp.atomic.write %x = %expr : !llvm.ptr, i321437 // CHECK: store atomic i32 %[[expr]], ptr %[[x]] seq_cst, align 41438 // CHECK: call void @__kmpc_flush(ptr @{{.*}})1439 omp.atomic.write %x = %expr memory_order(seq_cst) : !llvm.ptr, i321440 // CHECK: store atomic i32 %[[expr]], ptr %[[x]] release, align 41441 // CHECK: call void @__kmpc_flush(ptr @{{.*}})1442 omp.atomic.write %x = %expr memory_order(release) : !llvm.ptr, i321443 // CHECK: store atomic i32 %[[expr]], ptr %[[x]] monotonic, align 41444 omp.atomic.write %x = %expr memory_order(relaxed) : !llvm.ptr, i321445 llvm.return1446}1447 1448// -----1449 1450// Checking simple atomicrmw and cmpxchg based translation. This also checks for1451// ambigous alloca insert point by putting llvm.mul as the first update operation.1452// CHECK-LABEL: @omp_atomic_update1453// CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]], ptr %[[xbool:.*]], i1 %[[exprbool:.*]])1454llvm.func @omp_atomic_update(%x:!llvm.ptr, %expr: i32, %xbool: !llvm.ptr, %exprbool: i1) {1455 // CHECK: %[[t1:.*]] = mul i32 %[[x_old:.*]], %[[expr]]1456 // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]1457 // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]1458 // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]1459 omp.atomic.update %x : !llvm.ptr {1460 ^bb0(%xval: i32):1461 %newval = llvm.mul %xval, %expr : i321462 omp.yield(%newval : i32)1463 }1464 // CHECK: atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic1465 omp.atomic.update %x : !llvm.ptr {1466 ^bb0(%xval: i32):1467 %newval = llvm.add %xval, %expr : i321468 omp.yield(%newval : i32)1469 }1470 llvm.return1471}1472 1473// -----1474 1475// CHECK-LABEL: @omp_atomic_write1476llvm.func @omp_atomic_write() {1477// CHECK: %[[ALLOCA0:.*]] = alloca { float, float }, align 81478// CHECK: %[[ALLOCA1:.*]] = alloca { float, float }, align 81479// CHECK: %[[X:.*]] = alloca float, i64 1, align 41480// CHECK: %[[R1:.*]] = alloca float, i64 1, align 41481// CHECK: %[[ALLOCA:.*]] = alloca { float, float }, i64 1, align 81482// CHECK: %[[LOAD:.*]] = load float, ptr %[[R1]], align 41483// CHECK: %[[IDX1:.*]] = insertvalue { float, float } undef, float %[[LOAD]], 01484// CHECK: %[[IDX2:.*]] = insertvalue { float, float } %[[IDX1]], float 0.000000e+00, 11485// CHECK: br label %entry1486 1487// CHECK: entry:1488// CHECK: store { float, float } %[[IDX2]], ptr %[[ALLOCA1]], align 41489// CHECK: call void @__atomic_store(i64 8, ptr %[[ALLOCA]], ptr %[[ALLOCA1]], i32 0)1490// CHECK: store { float, float } { float 1.000000e+00, float 1.000000e+00 }, ptr %[[ALLOCA0]], align 41491// CHECK: call void @__atomic_store(i64 8, ptr %[[ALLOCA]], ptr %[[ALLOCA0]], i32 0)1492 1493 %0 = llvm.mlir.constant(1 : i64) : i641494 %1 = llvm.alloca %0 x f32 {bindc_name = "x"} : (i64) -> !llvm.ptr1495 %2 = llvm.mlir.constant(1 : i64) : i641496 %3 = llvm.alloca %2 x f32 {bindc_name = "r1"} : (i64) -> !llvm.ptr1497 %4 = llvm.mlir.constant(1 : i64) : i641498 %5 = llvm.alloca %4 x !llvm.struct<(f32, f32)> {bindc_name = "c1"} : (i64) -> !llvm.ptr1499 %6 = llvm.mlir.constant(1.000000e+00 : f32) : f321500 %7 = llvm.mlir.constant(0.000000e+00 : f32) : f321501 %8 = llvm.mlir.constant(1 : i64) : i641502 %9 = llvm.mlir.constant(1 : i64) : i641503 %10 = llvm.mlir.constant(1 : i64) : i641504 %11 = llvm.load %3 : !llvm.ptr -> f321505 %12 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1506 %13 = llvm.insertvalue %11, %12[0] : !llvm.struct<(f32, f32)>1507 %14 = llvm.insertvalue %7, %13[1] : !llvm.struct<(f32, f32)>1508 omp.atomic.write %5 = %14 : !llvm.ptr, !llvm.struct<(f32, f32)>1509 %15 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1510 %16 = llvm.insertvalue %6, %15[0] : !llvm.struct<(f32, f32)>1511 %17 = llvm.insertvalue %6, %16[1] : !llvm.struct<(f32, f32)>1512 omp.atomic.write %5 = %17 : !llvm.ptr, !llvm.struct<(f32, f32)>1513 llvm.return1514}1515 1516// -----1517 1518//CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 81519//CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 81520//CHECK: {{.*}} = alloca { float, float }, i64 1, align 81521//CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 81522 1523//CHECK: br label %entry1524 1525//CHECK: entry:1526//CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)1527//CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 81528//CHECK: br label %.atomic.cont1529 1530//CHECK: .atomic.cont1531//CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ]1532//CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 01533//CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 11534//CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+001535//CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+001536//CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 01537//CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 11538//CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 41539//CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]], i32 2, i32 2)1540//CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 41541//CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont1542 1543llvm.func @_QPomp_atomic_update_complex() {1544 %0 = llvm.mlir.constant(1 : i64) : i641545 %1 = llvm.alloca %0 x !llvm.struct<(f32, f32)> {bindc_name = "ib"} : (i64) -> !llvm.ptr1546 %2 = llvm.mlir.constant(1 : i64) : i641547 %3 = llvm.alloca %2 x !llvm.struct<(f32, f32)> {bindc_name = "ia"} : (i64) -> !llvm.ptr1548 %4 = llvm.mlir.constant(1.000000e+00 : f32) : f321549 %5 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1550 %6 = llvm.insertvalue %4, %5[0] : !llvm.struct<(f32, f32)>1551 %7 = llvm.insertvalue %4, %6[1] : !llvm.struct<(f32, f32)>1552 omp.atomic.update %3 : !llvm.ptr {1553 ^bb0(%arg0: !llvm.struct<(f32, f32)>):1554 %8 = llvm.extractvalue %arg0[0] : !llvm.struct<(f32, f32)>1555 %9 = llvm.extractvalue %arg0[1] : !llvm.struct<(f32, f32)>1556 %10 = llvm.extractvalue %7[0] : !llvm.struct<(f32, f32)>1557 %11 = llvm.extractvalue %7[1] : !llvm.struct<(f32, f32)>1558 %12 = llvm.fadd %8, %10 {fastmathFlags = #llvm.fastmath<contract>} : f321559 %13 = llvm.fadd %9, %11 {fastmathFlags = #llvm.fastmath<contract>} : f321560 %14 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1561 %15 = llvm.insertvalue %12, %14[0] : !llvm.struct<(f32, f32)>1562 %16 = llvm.insertvalue %13, %15[1] : !llvm.struct<(f32, f32)>1563 omp.yield(%16 : !llvm.struct<(f32, f32)>)1564 }1565 llvm.return1566}1567 1568// -----1569 1570//CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 81571//CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 81572//CHECK: %[[VAL_1:.*]] = alloca { float, float }, i64 1, align 81573//CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 81574//CHECK: store { float, float } { float 2.000000e+00, float 2.000000e+00 }, ptr %[[ORIG_VAL]], align 41575//CHECK: br label %entry1576 1577//CHECK: entry: ; preds = %01578//CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)1579//CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 81580//CHECK: br label %.atomic.cont1581 1582//CHECK: .atomic.cont1583//CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ]1584//CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 01585//CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 11586//CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+001587//CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+001588//CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 01589//CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 11590//CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 4 1591//CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]], i32 2, i32 2)1592//CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 41593//CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont1594//CHECK: .atomic.exit1595//CHECK: store { float, float } %[[VAL_10]], ptr %[[VAL_1]], align 41596 1597llvm.func @_QPomp_atomic_capture_complex() {1598 %0 = llvm.mlir.constant(1 : i64) : i641599 %1 = llvm.alloca %0 x !llvm.struct<(f32, f32)> {bindc_name = "ib"} : (i64) -> !llvm.ptr1600 %2 = llvm.mlir.constant(1 : i64) : i641601 %3 = llvm.alloca %2 x !llvm.struct<(f32, f32)> {bindc_name = "ia"} : (i64) -> !llvm.ptr1602 %4 = llvm.mlir.constant(1.000000e+00 : f32) : f321603 %5 = llvm.mlir.constant(2.000000e+00 : f32) : f321604 %6 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1605 %7 = llvm.insertvalue %5, %6[0] : !llvm.struct<(f32, f32)>1606 %8 = llvm.insertvalue %5, %7[1] : !llvm.struct<(f32, f32)>1607 llvm.store %8, %3 : !llvm.struct<(f32, f32)>, !llvm.ptr1608 %9 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1609 %10 = llvm.insertvalue %4, %9[0] : !llvm.struct<(f32, f32)>1610 %11 = llvm.insertvalue %4, %10[1] : !llvm.struct<(f32, f32)>1611 omp.atomic.capture {1612 omp.atomic.update %3 : !llvm.ptr {1613 ^bb0(%arg0: !llvm.struct<(f32, f32)>):1614 %12 = llvm.extractvalue %arg0[0] : !llvm.struct<(f32, f32)>1615 %13 = llvm.extractvalue %arg0[1] : !llvm.struct<(f32, f32)>1616 %14 = llvm.extractvalue %11[0] : !llvm.struct<(f32, f32)>1617 %15 = llvm.extractvalue %11[1] : !llvm.struct<(f32, f32)>1618 %16 = llvm.fadd %12, %14 {fastmathFlags = #llvm.fastmath<contract>} : f321619 %17 = llvm.fadd %13, %15 {fastmathFlags = #llvm.fastmath<contract>} : f321620 %18 = llvm.mlir.undef : !llvm.struct<(f32, f32)>1621 %19 = llvm.insertvalue %16, %18[0] : !llvm.struct<(f32, f32)>1622 %20 = llvm.insertvalue %17, %19[1] : !llvm.struct<(f32, f32)>1623 omp.yield(%20 : !llvm.struct<(f32, f32)>)1624 }1625 omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>1626 }1627 llvm.return1628}1629 1630// -----1631 1632// CHECK-LABEL: define void @omp_atomic_read_complex() {1633llvm.func @omp_atomic_read_complex(){1634 1635// CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 81636// CHECK: %[[a:.*]] = alloca { float, float }, i64 1, align 81637// CHECK: %[[b:.*]] = alloca { float, float }, i64 1, align 81638// CHECK: call void @__atomic_load(i64 8, ptr %[[b]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)1639// CHECK: %[[LOADED_VAL:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 81640// CHECK: store { float, float } %[[LOADED_VAL]], ptr %[[a]], align 41641// CHECK: ret void1642// CHECK: }1643 1644 %0 = llvm.mlir.constant(1 : i64) : i641645 %1 = llvm.alloca %0 x !llvm.struct<(f32, f32)> {bindc_name = "ib"} : (i64) -> !llvm.ptr1646 %2 = llvm.mlir.constant(1 : i64) : i641647 %3 = llvm.alloca %2 x !llvm.struct<(f32, f32)> {bindc_name = "ia"} : (i64) -> !llvm.ptr1648 omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>1649 llvm.return1650}1651 1652// -----1653 1654// Checking an order-dependent operation when the order is `expr binop x`1655// CHECK-LABEL: @omp_atomic_update_ordering1656// CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])1657llvm.func @omp_atomic_update_ordering(%x:!llvm.ptr, %expr: i32) {1658 // CHECK: %[[t1:.*]] = shl i32 %[[expr]], %[[x_old:[^ ,]*]]1659 // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]1660 // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]1661 // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]1662 omp.atomic.update %x : !llvm.ptr {1663 ^bb0(%xval: i32):1664 %newval = llvm.shl %expr, %xval : i321665 omp.yield(%newval : i32)1666 }1667 llvm.return1668}1669 1670// -----1671 1672// Checking an order-dependent operation when the order is `x binop expr`1673// CHECK-LABEL: @omp_atomic_update_ordering1674// CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])1675llvm.func @omp_atomic_update_ordering(%x:!llvm.ptr, %expr: i32) {1676 // CHECK: %[[t1:.*]] = shl i32 %[[x_old:.*]], %[[expr]]1677 // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]1678 // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]1679 // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]] monotonic1680 omp.atomic.update %x : !llvm.ptr {1681 ^bb0(%xval: i32):1682 %newval = llvm.shl %xval, %expr : i321683 omp.yield(%newval : i32)1684 }1685 llvm.return1686}1687 1688// -----1689 1690// Checking intrinsic translation.1691// CHECK-LABEL: @omp_atomic_update_intrinsic1692// CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])1693llvm.func @omp_atomic_update_intrinsic(%x:!llvm.ptr, %expr: i32) {1694 // CHECK: %[[t1:.*]] = call i32 @llvm.smax.i32(i32 %[[x_old:.*]], i32 %[[expr]])1695 // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]1696 // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]1697 // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]1698 omp.atomic.update %x : !llvm.ptr {1699 ^bb0(%xval: i32):1700 %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i321701 omp.yield(%newval : i32)1702 }1703 // CHECK: %[[t1:.*]] = call i32 @llvm.umax.i32(i32 %[[x_old:.*]], i32 %[[expr]])1704 // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]1705 // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]1706 // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]1707 omp.atomic.update %x : !llvm.ptr {1708 ^bb0(%xval: i32):1709 %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i321710 omp.yield(%newval : i32)1711 }1712 llvm.return1713}1714 1715// -----1716 1717// CHECK-LABEL: @atomic_update_cmpxchg1718// CHECK-SAME: (ptr %[[X:.*]], ptr %[[EXPR:.*]]) {1719// CHECK: %[[AT_LOAD_VAL:.*]] = load atomic i32, ptr %[[X]] monotonic, align 41720// CHECK: %[[LOAD_VAL_PHI:.*]] = phi i32 [ %[[AT_LOAD_VAL]], %entry ], [ %[[LOAD_VAL:.*]], %.atomic.cont ]1721// CHECK: %[[VAL_SUCCESS:.*]] = cmpxchg ptr %[[X]], i32 %[[LOAD_VAL_PHI]], i32 %{{.*}} monotonic monotonic, align 41722// CHECK: %[[LOAD_VAL]] = extractvalue { i32, i1 } %[[VAL_SUCCESS]], 01723// CHECK: br i1 %{{.*}}, label %.atomic.exit, label %.atomic.cont1724 1725llvm.func @atomic_update_cmpxchg(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {1726 %0 = llvm.load %arg1 : !llvm.ptr -> f321727 omp.atomic.update %arg0 : !llvm.ptr {1728 ^bb0(%arg2: i32):1729 %1 = llvm.sitofp %arg2 : i32 to f321730 %2 = llvm.fadd %1, %0 : f321731 %3 = llvm.fptosi %2 : f32 to i321732 omp.yield(%3 : i32)1733 }1734 llvm.return1735}1736 1737// -----1738 1739// CHECK-LABEL: @omp_atomic_capture_prefix_update1740// CHECK-SAME: (ptr %[[x:.*]], ptr %[[v:.*]], i32 %[[expr:.*]], ptr %[[xf:.*]], ptr %[[vf:.*]], float %[[exprf:.*]])1741llvm.func @omp_atomic_capture_prefix_update(1742 %x: !llvm.ptr, %v: !llvm.ptr, %expr: i32,1743 %xf: !llvm.ptr, %vf: !llvm.ptr, %exprf: f32) -> () {1744 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic1745 // CHECK-NEXT: %[[newval:.*]] = add i32 %[[res]], %[[expr]]1746 // CHECK: store i32 %[[newval]], ptr %[[v]]1747 omp.atomic.capture {1748 omp.atomic.update %x : !llvm.ptr {1749 ^bb0(%xval: i32):1750 %newval = llvm.add %xval, %expr : i321751 omp.yield(%newval : i32)1752 }1753 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321754 }1755 1756 // CHECK: %[[res:.*]] = atomicrmw sub ptr %[[x]], i32 %[[expr]] monotonic1757 // CHECK-NEXT: %[[newval:.*]] = sub i32 %[[res]], %[[expr]]1758 // CHECK: store i32 %[[newval]], ptr %[[v]]1759 omp.atomic.capture {1760 omp.atomic.update %x : !llvm.ptr {1761 ^bb0(%xval: i32):1762 %newval = llvm.sub %xval, %expr : i321763 omp.yield(%newval : i32)1764 }1765 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321766 }1767 1768 // CHECK: %[[res:.*]] = atomicrmw and ptr %[[x]], i32 %[[expr]] monotonic1769 // CHECK-NEXT: %[[newval:.*]] = and i32 %[[res]], %[[expr]]1770 // CHECK: store i32 %[[newval]], ptr %[[v]]1771 omp.atomic.capture {1772 omp.atomic.update %x : !llvm.ptr {1773 ^bb0(%xval: i32):1774 %newval = llvm.and %xval, %expr : i321775 omp.yield(%newval : i32)1776 }1777 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321778 }1779 1780 // CHECK: %[[res:.*]] = atomicrmw or ptr %[[x]], i32 %[[expr]] monotonic1781 // CHECK-NEXT: %[[newval:.*]] = or i32 %[[res]], %[[expr]]1782 // CHECK: store i32 %[[newval]], ptr %[[v]]1783 omp.atomic.capture {1784 omp.atomic.update %x : !llvm.ptr {1785 ^bb0(%xval: i32):1786 %newval = llvm.or %xval, %expr : i321787 omp.yield(%newval : i32)1788 }1789 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321790 }1791 1792 // CHECK: %[[res:.*]] = atomicrmw xor ptr %[[x]], i32 %[[expr]] monotonic1793 // CHECK-NEXT: %[[newval:.*]] = xor i32 %[[res]], %[[expr]]1794 // CHECK: store i32 %[[newval]], ptr %[[v]]1795 omp.atomic.capture {1796 omp.atomic.update %x : !llvm.ptr {1797 ^bb0(%xval: i32):1798 %newval = llvm.xor %xval, %expr : i321799 omp.yield(%newval : i32)1800 }1801 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321802 }1803 1804 // CHECK: %[[xval:.*]] = phi i321805 // CHECK-NEXT: %[[newval:.*]] = mul i32 %[[xval]], %[[expr]]1806 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1807 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1808 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1809 // CHECK: store i32 %[[newval]], ptr %[[v]]1810 omp.atomic.capture {1811 omp.atomic.update %x : !llvm.ptr {1812 ^bb0(%xval: i32):1813 %newval = llvm.mul %xval, %expr : i321814 omp.yield(%newval : i32)1815 }1816 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321817 }1818 1819 // CHECK: %[[xval:.*]] = phi i321820 // CHECK-NEXT: %[[newval:.*]] = sdiv i32 %[[xval]], %[[expr]]1821 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1822 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1823 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1824 // CHECK: store i32 %[[newval]], ptr %[[v]]1825 omp.atomic.capture {1826 omp.atomic.update %x : !llvm.ptr {1827 ^bb0(%xval: i32):1828 %newval = llvm.sdiv %xval, %expr : i321829 omp.yield(%newval : i32)1830 }1831 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321832 }1833 1834 // CHECK: %[[xval:.*]] = phi i321835 // CHECK-NEXT: %[[newval:.*]] = udiv i32 %[[xval]], %[[expr]]1836 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1837 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1838 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1839 // CHECK: store i32 %[[newval]], ptr %[[v]]1840 omp.atomic.capture {1841 omp.atomic.update %x : !llvm.ptr {1842 ^bb0(%xval: i32):1843 %newval = llvm.udiv %xval, %expr : i321844 omp.yield(%newval : i32)1845 }1846 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321847 }1848 1849 // CHECK: %[[xval:.*]] = phi i321850 // CHECK-NEXT: %[[newval:.*]] = shl i32 %[[xval]], %[[expr]]1851 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1852 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1853 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1854 // CHECK: store i32 %[[newval]], ptr %[[v]]1855 omp.atomic.capture {1856 omp.atomic.update %x : !llvm.ptr {1857 ^bb0(%xval: i32):1858 %newval = llvm.shl %xval, %expr : i321859 omp.yield(%newval : i32)1860 }1861 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321862 }1863 1864 // CHECK: %[[xval:.*]] = phi i321865 // CHECK-NEXT: %[[newval:.*]] = lshr i32 %[[xval]], %[[expr]]1866 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1867 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1868 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1869 // CHECK: store i32 %[[newval]], ptr %[[v]]1870 omp.atomic.capture {1871 omp.atomic.update %x : !llvm.ptr {1872 ^bb0(%xval: i32):1873 %newval = llvm.lshr %xval, %expr : i321874 omp.yield(%newval : i32)1875 }1876 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321877 }1878 1879 // CHECK: %[[xval:.*]] = phi i321880 // CHECK-NEXT: %[[newval:.*]] = ashr i32 %[[xval]], %[[expr]]1881 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1882 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1883 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1884 // CHECK: store i32 %[[newval]], ptr %[[v]]1885 omp.atomic.capture {1886 omp.atomic.update %x : !llvm.ptr {1887 ^bb0(%xval: i32):1888 %newval = llvm.ashr %xval, %expr : i321889 omp.yield(%newval : i32)1890 }1891 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321892 }1893 1894 // CHECK: %[[xval:.*]] = phi i321895 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smax.i32(i32 %[[xval]], i32 %[[expr]])1896 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1897 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1898 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1899 // CHECK: store i32 %[[newval]], ptr %[[v]]1900 omp.atomic.capture {1901 omp.atomic.update %x : !llvm.ptr {1902 ^bb0(%xval: i32):1903 %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i321904 omp.yield(%newval : i32)1905 }1906 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321907 }1908 1909 // CHECK: %[[xval:.*]] = phi i321910 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smin.i32(i32 %[[xval]], i32 %[[expr]])1911 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1912 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1913 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1914 // CHECK: store i32 %[[newval]], ptr %[[v]]1915 omp.atomic.capture {1916 omp.atomic.update %x : !llvm.ptr {1917 ^bb0(%xval: i32):1918 %newval = "llvm.intr.smin"(%xval, %expr) : (i32, i32) -> i321919 omp.yield(%newval : i32)1920 }1921 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321922 }1923 1924 // CHECK: %[[xval:.*]] = phi i321925 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umax.i32(i32 %[[xval]], i32 %[[expr]])1926 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1927 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1928 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1929 // CHECK: store i32 %[[newval]], ptr %[[v]]1930 omp.atomic.capture {1931 omp.atomic.update %x : !llvm.ptr {1932 ^bb0(%xval: i32):1933 %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i321934 omp.yield(%newval : i32)1935 }1936 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321937 }1938 1939 // CHECK: %[[xval:.*]] = phi i321940 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umin.i32(i32 %[[xval]], i32 %[[expr]])1941 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}1942 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}1943 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1944 // CHECK: store i32 %[[newval]], ptr %[[v]]1945 omp.atomic.capture {1946 omp.atomic.update %x : !llvm.ptr {1947 ^bb0(%xval: i32):1948 %newval = "llvm.intr.umin"(%xval, %expr) : (i32, i32) -> i321949 omp.yield(%newval : i32)1950 }1951 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321952 }1953 1954 // CHECK: %[[xval:.*]] = phi i321955 // CHECK: %[[newval:.*]] = fadd float %{{.*}}, %[[exprf]]1956 // CHECK: store float %[[newval]], ptr %{{.*}}1957 // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}1958 // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1959 // CHECK: store float %[[newval]], ptr %[[vf]]1960 omp.atomic.capture {1961 omp.atomic.update %xf : !llvm.ptr {1962 ^bb0(%xval: f32):1963 %newval = llvm.fadd %xval, %exprf : f321964 omp.yield(%newval : f32)1965 }1966 omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f321967 }1968 1969 // CHECK: %[[xval:.*]] = phi i321970 // CHECK: %[[newval:.*]] = fsub float %{{.*}}, %[[exprf]]1971 // CHECK: store float %[[newval]], ptr %{{.*}}1972 // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}1973 // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic1974 // CHECK: store float %[[newval]], ptr %[[vf]]1975 omp.atomic.capture {1976 omp.atomic.update %xf : !llvm.ptr {1977 ^bb0(%xval: f32):1978 %newval = llvm.fsub %xval, %exprf : f321979 omp.yield(%newval : f32)1980 }1981 omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f321982 }1983 1984 llvm.return1985}1986 1987// -----1988 1989// CHECK-LABEL: @omp_atomic_capture_postfix_update1990// CHECK-SAME: (ptr %[[x:.*]], ptr %[[v:.*]], i32 %[[expr:.*]], ptr %[[xf:.*]], ptr %[[vf:.*]], float %[[exprf:.*]])1991llvm.func @omp_atomic_capture_postfix_update(1992 %x: !llvm.ptr, %v: !llvm.ptr, %expr: i32,1993 %xf: !llvm.ptr, %vf: !llvm.ptr, %exprf: f32) -> () {1994 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic1995 // CHECK: store i32 %[[res]], ptr %[[v]]1996 omp.atomic.capture {1997 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i321998 omp.atomic.update %x : !llvm.ptr {1999 ^bb0(%xval: i32):2000 %newval = llvm.add %xval, %expr : i322001 omp.yield(%newval : i32)2002 }2003 }2004 2005 // CHECK: %[[res:.*]] = atomicrmw sub ptr %[[x]], i32 %[[expr]] monotonic2006 // CHECK: store i32 %[[res]], ptr %[[v]]2007 omp.atomic.capture {2008 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322009 omp.atomic.update %x : !llvm.ptr {2010 ^bb0(%xval: i32):2011 %newval = llvm.sub %xval, %expr : i322012 omp.yield(%newval : i32)2013 }2014 }2015 2016 // CHECK: %[[res:.*]] = atomicrmw and ptr %[[x]], i32 %[[expr]] monotonic2017 // CHECK: store i32 %[[res]], ptr %[[v]]2018 omp.atomic.capture {2019 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322020 omp.atomic.update %x : !llvm.ptr {2021 ^bb0(%xval: i32):2022 %newval = llvm.and %xval, %expr : i322023 omp.yield(%newval : i32)2024 }2025 }2026 2027 // CHECK: %[[res:.*]] = atomicrmw or ptr %[[x]], i32 %[[expr]] monotonic2028 // CHECK: store i32 %[[res]], ptr %[[v]]2029 omp.atomic.capture {2030 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322031 omp.atomic.update %x : !llvm.ptr {2032 ^bb0(%xval: i32):2033 %newval = llvm.or %xval, %expr : i322034 omp.yield(%newval : i32)2035 }2036 }2037 2038 // CHECK: %[[res:.*]] = atomicrmw xor ptr %[[x]], i32 %[[expr]] monotonic2039 // CHECK: store i32 %[[res]], ptr %[[v]]2040 omp.atomic.capture {2041 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322042 omp.atomic.update %x : !llvm.ptr {2043 ^bb0(%xval: i32):2044 %newval = llvm.xor %xval, %expr : i322045 omp.yield(%newval : i32)2046 }2047 }2048 2049 // CHECK: %[[xval:.*]] = phi i322050 // CHECK-NEXT: %[[newval:.*]] = mul i32 %[[xval]], %[[expr]]2051 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2052 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2053 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2054 // CHECK: store i32 %[[xval]], ptr %[[v]]2055 omp.atomic.capture {2056 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322057 omp.atomic.update %x : !llvm.ptr {2058 ^bb0(%xval: i32):2059 %newval = llvm.mul %xval, %expr : i322060 omp.yield(%newval : i32)2061 }2062 }2063 2064 // CHECK: %[[xval:.*]] = phi i322065 // CHECK-NEXT: %[[newval:.*]] = sdiv i32 %[[xval]], %[[expr]]2066 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2067 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2068 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2069 // CHECK: store i32 %[[xval]], ptr %[[v]]2070 omp.atomic.capture {2071 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322072 omp.atomic.update %x : !llvm.ptr {2073 ^bb0(%xval: i32):2074 %newval = llvm.sdiv %xval, %expr : i322075 omp.yield(%newval : i32)2076 }2077 }2078 2079 // CHECK: %[[xval:.*]] = phi i322080 // CHECK-NEXT: %[[newval:.*]] = udiv i32 %[[xval]], %[[expr]]2081 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2082 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2083 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2084 // CHECK: store i32 %[[xval]], ptr %[[v]]2085 omp.atomic.capture {2086 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322087 omp.atomic.update %x : !llvm.ptr {2088 ^bb0(%xval: i32):2089 %newval = llvm.udiv %xval, %expr : i322090 omp.yield(%newval : i32)2091 }2092 }2093 2094 // CHECK: %[[xval:.*]] = phi i322095 // CHECK-NEXT: %[[newval:.*]] = shl i32 %[[xval]], %[[expr]]2096 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2097 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2098 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2099 // CHECK: store i32 %[[xval]], ptr %[[v]]2100 omp.atomic.capture {2101 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322102 omp.atomic.update %x : !llvm.ptr {2103 ^bb0(%xval: i32):2104 %newval = llvm.shl %xval, %expr : i322105 omp.yield(%newval : i32)2106 }2107 }2108 2109 // CHECK: %[[xval:.*]] = phi i322110 // CHECK-NEXT: %[[newval:.*]] = lshr i32 %[[xval]], %[[expr]]2111 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2112 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2113 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2114 // CHECK: store i32 %[[xval]], ptr %[[v]]2115 omp.atomic.capture {2116 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322117 omp.atomic.update %x : !llvm.ptr {2118 ^bb0(%xval: i32):2119 %newval = llvm.lshr %xval, %expr : i322120 omp.yield(%newval : i32)2121 }2122 }2123 2124 // CHECK: %[[xval:.*]] = phi i322125 // CHECK-NEXT: %[[newval:.*]] = ashr i32 %[[xval]], %[[expr]]2126 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2127 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2128 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2129 // CHECK: store i32 %[[xval]], ptr %[[v]]2130 omp.atomic.capture {2131 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322132 omp.atomic.update %x : !llvm.ptr {2133 ^bb0(%xval: i32):2134 %newval = llvm.ashr %xval, %expr : i322135 omp.yield(%newval : i32)2136 }2137 }2138 2139 // CHECK: %[[xval:.*]] = phi i322140 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smax.i32(i32 %[[xval]], i32 %[[expr]])2141 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2142 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2143 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2144 // CHECK: store i32 %[[xval]], ptr %[[v]]2145 omp.atomic.capture {2146 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322147 omp.atomic.update %x : !llvm.ptr {2148 ^bb0(%xval: i32):2149 %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i322150 omp.yield(%newval : i32)2151 }2152 }2153 2154 // CHECK: %[[xval:.*]] = phi i322155 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smin.i32(i32 %[[xval]], i32 %[[expr]])2156 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2157 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2158 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2159 // CHECK: store i32 %[[xval]], ptr %[[v]]2160 omp.atomic.capture {2161 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322162 omp.atomic.update %x : !llvm.ptr {2163 ^bb0(%xval: i32):2164 %newval = "llvm.intr.smin"(%xval, %expr) : (i32, i32) -> i322165 omp.yield(%newval : i32)2166 }2167 }2168 2169 // CHECK: %[[xval:.*]] = phi i322170 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umax.i32(i32 %[[xval]], i32 %[[expr]])2171 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2172 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2173 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2174 // CHECK: store i32 %[[xval]], ptr %[[v]]2175 omp.atomic.capture {2176 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322177 omp.atomic.update %x : !llvm.ptr {2178 ^bb0(%xval: i32):2179 %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i322180 omp.yield(%newval : i32)2181 }2182 }2183 2184 // CHECK: %[[xval:.*]] = phi i322185 // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umin.i32(i32 %[[xval]], i32 %[[expr]])2186 // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}2187 // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}2188 // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2189 // CHECK: store i32 %[[xval]], ptr %[[v]]2190 omp.atomic.capture {2191 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322192 omp.atomic.update %x : !llvm.ptr {2193 ^bb0(%xval: i32):2194 %newval = "llvm.intr.umin"(%xval, %expr) : (i32, i32) -> i322195 omp.yield(%newval : i32)2196 }2197 }2198 2199 // CHECK: %[[xval:.*]] = phi i322200 // CHECK: %[[xvalf:.*]] = bitcast i32 %[[xval]] to float2201 // CHECK: %[[newval:.*]] = fadd float %{{.*}}, %[[exprf]]2202 // CHECK: store float %[[newval]], ptr %{{.*}}2203 // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}2204 // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2205 // CHECK: store float %[[xvalf]], ptr %[[vf]]2206 omp.atomic.capture {2207 omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f322208 omp.atomic.update %xf : !llvm.ptr {2209 ^bb0(%xval: f32):2210 %newval = llvm.fadd %xval, %exprf : f322211 omp.yield(%newval : f32)2212 }2213 }2214 2215 // CHECK: %[[xval:.*]] = phi i322216 // CHECK: %[[xvalf:.*]] = bitcast i32 %[[xval]] to float2217 // CHECK: %[[newval:.*]] = fsub float %{{.*}}, %[[exprf]]2218 // CHECK: store float %[[newval]], ptr %{{.*}}2219 // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}2220 // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2221 // CHECK: store float %[[xvalf]], ptr %[[vf]]2222 omp.atomic.capture {2223 omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f322224 omp.atomic.update %xf : !llvm.ptr {2225 ^bb0(%xval: f32):2226 %newval = llvm.fsub %xval, %exprf : f322227 omp.yield(%newval : f32)2228 }2229 }2230 2231 llvm.return2232}2233 2234// -----2235// CHECK-LABEL: @omp_atomic_capture_misc2236// CHECK-SAME: (ptr %[[x:.*]], ptr %[[v:.*]], i32 %[[expr:.*]], ptr %[[xf:.*]], ptr %[[vf:.*]], float %[[exprf:.*]])2237llvm.func @omp_atomic_capture_misc(2238 %x: !llvm.ptr, %v: !llvm.ptr, %expr: i32,2239 %xf: !llvm.ptr, %vf: !llvm.ptr, %exprf: f32) -> () {2240 // CHECK: %[[xval:.*]] = atomicrmw xchg ptr %[[x]], i32 %[[expr]] monotonic2241 // CHECK: store i32 %[[xval]], ptr %[[v]]2242 omp.atomic.capture{2243 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322244 omp.atomic.write %x = %expr : !llvm.ptr, i322245 }2246 2247 // CHECK: %[[xval:.*]] = phi i322248 // CHECK: %[[xvalf:.*]] = bitcast i32 %[[xval]] to float2249 // CHECK: store float %[[exprf]], ptr %{{.*}}2250 // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}2251 // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic2252 // CHECK: store float %[[xvalf]], ptr %[[vf]]2253 omp.atomic.capture{2254 omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f322255 omp.atomic.write %xf = %exprf : !llvm.ptr, f322256 }2257 2258 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] seq_cst2259 // CHECK: store i32 %[[res]], ptr %[[v]]2260 omp.atomic.capture memory_order(seq_cst) {2261 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322262 omp.atomic.update %x : !llvm.ptr {2263 ^bb0(%xval: i32):2264 %newval = llvm.add %xval, %expr : i322265 omp.yield(%newval : i32)2266 }2267 }2268 2269 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] acquire2270 // CHECK: store i32 %[[res]], ptr %[[v]]2271 omp.atomic.capture memory_order(acquire) {2272 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322273 omp.atomic.update %x : !llvm.ptr {2274 ^bb0(%xval: i32):2275 %newval = llvm.add %xval, %expr : i322276 omp.yield(%newval : i32)2277 }2278 }2279 2280 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] release2281 // CHECK: store i32 %[[res]], ptr %[[v]]2282 omp.atomic.capture memory_order(release) {2283 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322284 omp.atomic.update %x : !llvm.ptr {2285 ^bb0(%xval: i32):2286 %newval = llvm.add %xval, %expr : i322287 omp.yield(%newval : i32)2288 }2289 }2290 2291 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic2292 // CHECK: store i32 %[[res]], ptr %[[v]]2293 omp.atomic.capture memory_order(relaxed) {2294 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322295 omp.atomic.update %x : !llvm.ptr {2296 ^bb0(%xval: i32):2297 %newval = llvm.add %xval, %expr : i322298 omp.yield(%newval : i32)2299 }2300 }2301 2302 // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] acq_rel2303 // CHECK: store i32 %[[res]], ptr %[[v]]2304 omp.atomic.capture memory_order(acq_rel) {2305 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i322306 omp.atomic.update %x : !llvm.ptr {2307 ^bb0(%xval: i32):2308 %newval = llvm.add %xval, %expr : i322309 omp.yield(%newval : i32)2310 }2311 }2312 2313 llvm.return2314}2315 2316// -----2317 2318// CHECK-LABEL: @omp_sections_empty2319llvm.func @omp_sections_empty() -> () {2320 omp.sections {2321 omp.terminator2322 }2323 // CHECK-NEXT: br label %entry2324 // CHECK: entry:2325 // CHECK-NEXT: ret void2326 llvm.return2327}2328 2329// -----2330 2331// Check IR generation for simple empty sections. This only checks the overall2332// shape of the IR, detailed checking is done by the OpenMPIRBuilder.2333 2334// CHECK-LABEL: @omp_sections_trivial2335llvm.func @omp_sections_trivial() -> () {2336 // CHECK: br label %[[ENTRY:[a-zA-Z_.]+]]2337 2338 // CHECK: [[ENTRY]]:2339 // CHECK: br label %[[PREHEADER:.*]]2340 2341 // CHECK: [[PREHEADER]]:2342 // CHECK: %{{.*}} = call i32 @__kmpc_global_thread_num({{.*}})2343 // CHECK: call void @__kmpc_for_static_init_4u({{.*}})2344 // CHECK: br label %[[HEADER:.*]]2345 2346 // CHECK: [[HEADER]]:2347 // CHECK: br label %[[COND:.*]]2348 2349 // CHECK: [[COND]]:2350 // CHECK: br i1 %{{.*}}, label %[[BODY:.*]], label %[[EXIT:.*]]2351 // CHECK: [[BODY]]:2352 // CHECK: switch i32 %{{.*}}, label %[[INC:.*]] [2353 // CHECK-NEXT: i32 0, label %[[SECTION1:.*]]2354 // CHECK-NEXT: i32 1, label %[[SECTION2:.*]]2355 // CHECK-NEXT: ]2356 2357 omp.sections {2358 omp.section {2359 // CHECK: [[SECTION1]]:2360 // CHECK-NEXT: br label %[[SECTION1_REGION1:[^ ,]*]]2361 // CHECK-EMPTY:2362 // CHECK-NEXT: [[SECTION1_REGION1]]:2363 // CHECK-NEXT: br label %[[SECTION1_REGION2:[^ ,]*]]2364 // CHECK-EMPTY:2365 // CHECK-NEXT: [[SECTION1_REGION2]]:2366 // CHECK-NEXT: br label %[[INC]]2367 omp.terminator2368 }2369 omp.section {2370 // CHECK: [[SECTION2]]:2371 // CHECK: br label %[[INC]]2372 omp.terminator2373 }2374 omp.terminator2375 }2376 2377 // CHECK: [[INC]]:2378 // CHECK: %{{.*}} = add {{.*}}, 12379 // CHECK: br label %[[HEADER]]2380 2381 // CHECK: [[EXIT]]:2382 // CHECK: call void @__kmpc_for_static_fini({{.*}})2383 // CHECK: call void @__kmpc_barrier({{.*}})2384 // CHECK: br label %[[AFTER:.*]]2385 2386 // CHECK: [[AFTER]]:2387 // CHECK: ret void2388 llvm.return2389}2390 2391// -----2392 2393// CHECK: declare void @foo()2394llvm.func @foo()2395 2396// CHECK: declare void @bar(i32)2397llvm.func @bar(%arg0 : i32)2398 2399// CHECK-LABEL: @omp_sections2400llvm.func @omp_sections(%arg0 : i32, %arg1 : i32, %arg2 : !llvm.ptr) -> () {2401 2402 // CHECK: switch i32 %{{.*}}, label %{{.*}} [2403 // CHECK-NEXT: i32 0, label %[[SECTION1:.*]]2404 // CHECK-NEXT: i32 1, label %[[SECTION2:.*]]2405 // CHECK-NEXT: i32 2, label %[[SECTION3:.*]]2406 // CHECK-NEXT: ]2407 omp.sections {2408 omp.section {2409 // CHECK: [[SECTION1]]:2410 // CHECK: br label %[[REGION1:[^ ,]*]]2411 // CHECK: [[REGION1]]:2412 // CHECK: call void @foo()2413 // CHECK: br label %{{.*}}2414 llvm.call @foo() : () -> ()2415 omp.terminator2416 }2417 omp.section {2418 // CHECK: [[SECTION2]]:2419 // CHECK: br label %[[REGION2:[^ ,]*]]2420 // CHECK: [[REGION2]]:2421 // CHECK: call void @bar(i32 %{{.*}})2422 // CHECK: br label %{{.*}}2423 llvm.call @bar(%arg0) : (i32) -> ()2424 omp.terminator2425 }2426 omp.section {2427 // CHECK: [[SECTION3]]:2428 // CHECK: br label %[[REGION3:[^ ,]*]]2429 // CHECK: [[REGION3]]:2430 // CHECK: %11 = add i32 %{{.*}}, %{{.*}}2431 %add = llvm.add %arg0, %arg1 : i322432 // CHECK: store i32 %{{.*}}, ptr %{{.*}}, align 42433 // CHECK: br label %{{.*}}2434 llvm.store %add, %arg2 : i32, !llvm.ptr2435 omp.terminator2436 }2437 omp.terminator2438 }2439 llvm.return2440}2441 2442// -----2443 2444llvm.func @foo()2445 2446// CHECK-LABEL: @omp_sections_with_clauses2447llvm.func @omp_sections_with_clauses() -> () {2448 // CHECK-NOT: call void @__kmpc_barrier2449 omp.sections nowait {2450 omp.section {2451 llvm.call @foo() : () -> ()2452 omp.terminator2453 }2454 omp.section {2455 llvm.call @foo() : () -> ()2456 omp.terminator2457 }2458 omp.terminator2459 }2460 llvm.return2461}2462 2463// -----2464 2465// Check that translation doesn't crash in presence of repeated successor2466// blocks with different arguments within OpenMP operations: LLVM cannot2467// represent this and a dummy block will be introduced for forwarding. The2468// introduction mechanism itself is tested elsewhere.2469// CHECK-LABEL: @repeated_successor2470llvm.func @repeated_successor(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) {2471 omp.wsloop {2472 omp.loop_nest (%arg4) : i64 = (%arg0) to (%arg1) step (%arg2) {2473 llvm.cond_br %arg3, ^bb1(%arg0 : i64), ^bb1(%arg1 : i64)2474 ^bb1(%0: i64): // 2 preds: ^bb0, ^bb02475 omp.yield2476 }2477 }2478 llvm.return2479}2480 2481// -----2482 2483// CHECK-LABEL: @single2484// CHECK-SAME: (i32 %[[x:.*]], i32 %[[y:.*]], ptr %[[zaddr:.*]])2485llvm.func @single(%x: i32, %y: i32, %zaddr: !llvm.ptr) {2486 // CHECK: %[[a:.*]] = sub i32 %[[x]], %[[y]]2487 %a = llvm.sub %x, %y : i322488 // CHECK: store i32 %[[a]], ptr %[[zaddr]]2489 llvm.store %a, %zaddr : i32, !llvm.ptr2490 // CHECK: call i32 @__kmpc_single2491 omp.single {2492 // CHECK: %[[z:.*]] = add i32 %[[x]], %[[y]]2493 %z = llvm.add %x, %y : i322494 // CHECK: store i32 %[[z]], ptr %[[zaddr]]2495 llvm.store %z, %zaddr : i32, !llvm.ptr2496 // CHECK: call void @__kmpc_end_single2497 // CHECK: call void @__kmpc_barrier2498 omp.terminator2499 }2500 // CHECK: %[[b:.*]] = mul i32 %[[x]], %[[y]]2501 %b = llvm.mul %x, %y : i322502 // CHECK: store i32 %[[b]], ptr %[[zaddr]]2503 llvm.store %b, %zaddr : i32, !llvm.ptr2504 // CHECK: ret void2505 llvm.return2506}2507 2508// -----2509 2510// CHECK-LABEL: @single_nowait2511// CHECK-SAME: (i32 %[[x:.*]], i32 %[[y:.*]], ptr %[[zaddr:.*]])2512llvm.func @single_nowait(%x: i32, %y: i32, %zaddr: !llvm.ptr) {2513 // CHECK: %[[a:.*]] = sub i32 %[[x]], %[[y]]2514 %a = llvm.sub %x, %y : i322515 // CHECK: store i32 %[[a]], ptr %[[zaddr]]2516 llvm.store %a, %zaddr : i32, !llvm.ptr2517 // CHECK: call i32 @__kmpc_single2518 omp.single nowait {2519 // CHECK: %[[z:.*]] = add i32 %[[x]], %[[y]]2520 %z = llvm.add %x, %y : i322521 // CHECK: store i32 %[[z]], ptr %[[zaddr]]2522 llvm.store %z, %zaddr : i32, !llvm.ptr2523 // CHECK: call void @__kmpc_end_single2524 // CHECK-NOT: call void @__kmpc_barrier2525 omp.terminator2526 }2527 // CHECK: %[[t:.*]] = mul i32 %[[x]], %[[y]]2528 %t = llvm.mul %x, %y : i322529 // CHECK: store i32 %[[t]], ptr %[[zaddr]]2530 llvm.store %t, %zaddr : i32, !llvm.ptr2531 // CHECK: ret void2532 llvm.return2533}2534 2535// -----2536 2537llvm.func @copy_i32(!llvm.ptr, !llvm.ptr)2538llvm.func @copy_f32(!llvm.ptr, !llvm.ptr)2539 2540// CHECK-LABEL: @single_copyprivate2541// CHECK-SAME: (ptr %[[ip:.*]], ptr %[[fp:.*]])2542llvm.func @single_copyprivate(%ip: !llvm.ptr, %fp: !llvm.ptr) {2543 // CHECK: %[[didit_addr:.*]] = alloca i322544 // CHECK: store i32 0, ptr %[[didit_addr]]2545 // CHECK: call i32 @__kmpc_single2546 omp.single copyprivate(%ip -> @copy_i32 : !llvm.ptr, %fp -> @copy_f32 : !llvm.ptr) {2547 // CHECK: %[[i:.*]] = load i32, ptr %[[ip]]2548 %i = llvm.load %ip : !llvm.ptr -> i322549 // CHECK: %[[i2:.*]] = add i32 %[[i]], %[[i]]2550 %i2 = llvm.add %i, %i : i322551 // CHECK: store i32 %[[i2]], ptr %[[ip]]2552 llvm.store %i2, %ip : i32, !llvm.ptr2553 // CHECK: %[[f:.*]] = load float, ptr %[[fp]]2554 %f = llvm.load %fp : !llvm.ptr -> f322555 // CHECK: %[[f2:.*]] = fadd float %[[f]], %[[f]]2556 %f2 = llvm.fadd %f, %f : f322557 // CHECK: store float %[[f2]], ptr %[[fp]]2558 llvm.store %f2, %fp : f32, !llvm.ptr2559 // CHECK: store i32 1, ptr %[[didit_addr]]2560 // CHECK: call void @__kmpc_end_single2561 // CHECK: %[[didit:.*]] = load i32, ptr %[[didit_addr]]2562 // CHECK: call void @__kmpc_copyprivate({{.*}}, ptr %[[ip]], ptr @copy_i32, i32 %[[didit]])2563 // CHECK: %[[didit2:.*]] = load i32, ptr %[[didit_addr]]2564 // CHECK: call void @__kmpc_copyprivate({{.*}}, ptr %[[fp]], ptr @copy_f32, i32 %[[didit2]])2565 // CHECK-NOT: call void @__kmpc_barrier2566 omp.terminator2567 }2568 // CHECK: ret void2569 llvm.return2570}2571 2572// -----2573 2574// CHECK: @_QFsubEx = internal global i32 undef2575// CHECK: @_QFsubEx.cache = common global ptr null2576 2577// CHECK-LABEL: @omp_threadprivate2578llvm.func @omp_threadprivate() {2579// CHECK: [[THREAD:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB:[0-9]+]])2580// CHECK: [[TMP1:%.*]] = call ptr @__kmpc_threadprivate_cached(ptr @[[GLOB]], i32 [[THREAD]], ptr @_QFsubEx, i64 4, ptr @_QFsubEx.cache)2581// CHECK: store i32 1, ptr [[TMP1]], align 42582// CHECK: store i32 3, ptr [[TMP1]], align 42583 2584// CHECK-LABEL: omp.par.region{{.*}}2585// CHECK: [[THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:[0-9]+]])2586// CHECK: [[TMP3:%.*]] = call ptr @__kmpc_threadprivate_cached(ptr @[[GLOB2]], i32 [[THREAD2]], ptr @_QFsubEx, i64 4, ptr @_QFsubEx.cache)2587// CHECK: store i32 2, ptr [[TMP3]], align 42588 2589 %0 = llvm.mlir.constant(1 : i32) : i322590 %1 = llvm.mlir.constant(2 : i32) : i322591 %2 = llvm.mlir.constant(3 : i32) : i322592 2593 %3 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr2594 %4 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr2595 2596 llvm.store %0, %4 : i32, !llvm.ptr2597 2598 omp.parallel {2599 %5 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr2600 llvm.store %1, %5 : i32, !llvm.ptr2601 omp.terminator2602 }2603 2604 llvm.store %2, %4 : i32, !llvm.ptr2605 llvm.return2606}2607 2608llvm.mlir.global internal @_QFsubEx() : i322609 2610// -----2611 2612// CHECK-LABEL: define void @omp_task_detach2613// CHECK-SAME: (ptr %[[event_handle:.*]])2614llvm.func @omp_task_detach(%event_handle : !llvm.ptr){2615 // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})2616 // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc2617 // CHECK: %[[return_val:.*]] = call ptr @__kmpc_task_allow_completion_event(ptr {{.*}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])2618 // CHECK: %[[conv:.*]] = ptrtoint ptr %[[return_val]] to i642619 // CHECK: store i64 %[[conv]], ptr %[[event_handle]], align 42620 // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])2621 omp.task detach(%event_handle : !llvm.ptr){2622 omp.terminator2623 }2624 llvm.return2625}2626 2627// -----2628 2629// CHECK-LABEL: define void @omp_task2630// CHECK-SAME: (i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])2631llvm.func @omp_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {2632 // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})2633 // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc2634 // CHECK-SAME: (ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40,2635 // CHECK-SAME: i64 0, ptr @[[outlined_fn:.+]])2636 // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])2637 omp.task {2638 %n = llvm.mlir.constant(1 : i64) : i642639 %valaddr = llvm.alloca %n x i32 : (i64) -> !llvm.ptr2640 %val = llvm.load %valaddr : !llvm.ptr -> i322641 %double = llvm.add %val, %val : i322642 llvm.store %double, %valaddr : i32, !llvm.ptr2643 omp.terminator2644 }2645 llvm.return2646}2647 2648// CHECK: define internal void @[[outlined_fn]](i32 %[[global_tid:[^ ,]+]])2649// CHECK: task.alloca{{.*}}:2650// CHECK: br label %[[task_body:[^, ]+]]2651// CHECK: [[task_body]]:2652// CHECK: br label %[[task_region:[^, ]+]]2653// CHECK: [[task_region]]:2654// CHECK: %[[alloca:.+]] = alloca i32, i64 12655// CHECK: %[[val:.+]] = load i32, ptr %[[alloca]]2656// CHECK: %[[newval:.+]] = add i32 %[[val]], %[[val]]2657// CHECK: store i32 %[[newval]], ptr %{{[^, ]+}}2658// CHECK: br label %[[exit_stub:[^, ]+]]2659// CHECK: [[exit_stub]]:2660// CHECK: ret void2661 2662// -----2663 2664// CHECK-LABEL: define void @omp_task_attrs()2665llvm.func @omp_task_attrs() -> () attributes {2666 target_cpu = "x86-64",2667 target_features = #llvm.target_features<["+mmx", "+sse"]>2668} {2669 // CHECK: %[[task_data:.*]] = call {{.*}}@__kmpc_omp_task_alloc{{.*}}@[[outlined_fn:.*]])2670 // CHECK: call {{.*}}@__kmpc_omp_task(2671 // CHECK-SAME: ptr %[[task_data]]2672 omp.task {2673 omp.terminator2674 }2675 2676 llvm.return2677}2678 2679// CHECK: define {{.*}} @[[outlined_fn]]{{.*}} #[[attrs:[0-9]+]]2680// CHECK: attributes #[[attrs]] = {2681// CHECK-SAME: "target-cpu"="x86-64"2682// CHECK-SAME: "target-features"="+mmx,+sse"2683 2684// -----2685 2686// CHECK-LABEL: define void @omp_task_with_deps2687// CHECK-SAME: (ptr %[[zaddr:.+]])2688// CHECK: %[[dep_arr_addr:.+]] = alloca [1 x %struct.kmp_dep_info], align 82689// CHECK: %[[DEP_ARR_ADDR1:.+]] = alloca [1 x %struct.kmp_dep_info], align 82690// CHECK: %[[DEP_ARR_ADDR2:.+]] = alloca [1 x %struct.kmp_dep_info], align 82691// CHECK: %[[DEP_ARR_ADDR3:.+]] = alloca [1 x %struct.kmp_dep_info], align 82692// CHECK: %[[DEP_ARR_ADDR4:.+]] = alloca [1 x %struct.kmp_dep_info], align 82693 2694// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})2695// CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc2696// CHECK-SAME: (ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40,2697// CHECK-SAME: i64 0, ptr @[[outlined_fn:.+]])2698 2699// CHECK: %[[dep_arr_addr_0:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[dep_arr_addr]], i64 0, i64 02700// CHECK: %[[dep_arr_addr_0_val:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[dep_arr_addr_0]], i32 0, i32 02701// CHECK: %[[dep_arr_addr_0_val_int:.+]] = ptrtoint ptr %0 to i642702// CHECK: store i64 %[[dep_arr_addr_0_val_int]], ptr %[[dep_arr_addr_0_val]], align 42703// CHECK: %[[dep_arr_addr_0_size:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[dep_arr_addr_0]], i32 0, i32 12704// CHECK: store i64 8, ptr %[[dep_arr_addr_0_size]], align 42705// CHECK: %[[dep_arr_addr_0_kind:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[dep_arr_addr_0]], i32 0, i32 22706// CHECK: store i8 1, ptr %[[dep_arr_addr_0_kind]], align 12707 2708// CHECK: call i32 @__kmpc_omp_task_with_deps(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]], {{.*}})2709// -----2710// dependence_type: Out2711// CHECK: %[[DEP_ARR_ADDR_1:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR1]], i64 0, i64 02712// [...]2713// CHECK: %[[DEP_TYPE_1:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_1]], i32 0, i32 22714// CHECK: store i8 3, ptr %[[DEP_TYPE_1]], align 12715// -----2716// dependence_type: Inout2717// CHECK: %[[DEP_ARR_ADDR_2:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR2]], i64 0, i64 02718// [...]2719// CHECK: %[[DEP_TYPE_2:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_2]], i32 0, i32 22720// CHECK: store i8 3, ptr %[[DEP_TYPE_2]], align 12721// -----2722// dependence_type: Mutexinoutset2723// CHECK: %[[DEP_ARR_ADDR_3:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR3]], i64 0, i64 02724// [...]2725// CHECK: %[[DEP_TYPE_3:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_3]], i32 0, i32 22726// CHECK: store i8 4, ptr %[[DEP_TYPE_3]], align 12727// -----2728// dependence_type: Inoutset2729// CHECK: %[[DEP_ARR_ADDR_4:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR4]], i64 0, i64 02730// [...]2731// CHECK: %[[DEP_TYPE_4:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_4]], i32 0, i32 22732// CHECK: store i8 8, ptr %[[DEP_TYPE_4]], align 12733llvm.func @omp_task_with_deps(%zaddr: !llvm.ptr) {2734 omp.task depend(taskdependin -> %zaddr : !llvm.ptr) {2735 %n = llvm.mlir.constant(1 : i64) : i642736 %valaddr = llvm.alloca %n x i32 : (i64) -> !llvm.ptr2737 %val = llvm.load %valaddr : !llvm.ptr -> i322738 %double = llvm.add %val, %val : i322739 llvm.store %double, %valaddr : i32, !llvm.ptr2740 omp.terminator2741 }2742 omp.task depend(taskdependout -> %zaddr : !llvm.ptr) {2743 omp.terminator2744 }2745 omp.task depend(taskdependinout -> %zaddr : !llvm.ptr) {2746 omp.terminator2747 }2748 omp.task depend(taskdependmutexinoutset -> %zaddr : !llvm.ptr) {2749 omp.terminator2750 }2751 omp.task depend(taskdependinoutset -> %zaddr : !llvm.ptr) {2752 omp.terminator2753 }2754 llvm.return2755}2756 2757// CHECK: define internal void @[[outlined_fn]](i32 %[[global_tid:[^ ,]+]])2758// CHECK: task.alloca{{.*}}:2759// CHECK: br label %[[task_body:[^, ]+]]2760// CHECK: [[task_body]]:2761// CHECK: br label %[[task_region:[^, ]+]]2762// CHECK: [[task_region]]:2763// CHECK: %[[alloca:.+]] = alloca i32, i64 12764// CHECK: %[[val:.+]] = load i32, ptr %[[alloca]]2765// CHECK: %[[newval:.+]] = add i32 %[[val]], %[[val]]2766// CHECK: store i32 %[[newval]], ptr %{{[^, ]+}}2767// CHECK: br label %[[exit_stub:[^, ]+]]2768// CHECK: [[exit_stub]]:2769// CHECK: ret void2770 2771// -----2772 2773// CHECK-LABEL: define void @omp_task2774// CHECK-SAME: (i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])2775module attributes {llvm.target_triple = "x86_64-unknown-linux-gnu"} {2776 llvm.func @omp_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {2777 // CHECK: %[[diff:.+]] = sub i32 %[[x]], %[[y]]2778 %diff = llvm.sub %x, %y : i322779 // CHECK: store i32 %[[diff]], ptr %22780 llvm.store %diff, %zaddr : i32, !llvm.ptr2781 // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})2782 // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc2783 // CHECK-SAME: (ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40, i64 16,2784 // CHECK-SAME: ptr @[[outlined_fn:.+]])2785 // CHECK: %[[shareds:.+]] = load ptr, ptr %[[task_data]]2786 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{.+}} %[[shareds]], ptr {{.+}}, i64 16, i1 false)2787 // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])2788 omp.task {2789 %z = llvm.add %x, %y : i322790 llvm.store %z, %zaddr : i32, !llvm.ptr2791 omp.terminator2792 }2793 // CHECK: %[[prod:.+]] = mul i32 %[[x]], %[[y]]2794 %b = llvm.mul %x, %y : i322795 // CHECK: store i32 %[[prod]], ptr %[[zaddr]]2796 llvm.store %b, %zaddr : i32, !llvm.ptr2797 llvm.return2798 }2799}2800 2801// CHECK: define internal void @[[outlined_fn]](i32 %[[global_tid:[^ ,]+]], ptr %[[task_data:.+]])2802// CHECK: task.alloca{{.*}}:2803// CHECK: %[[shareds:.+]] = load ptr, ptr %[[task_data]]2804// CHECK: br label %[[task_body:[^, ]+]]2805// CHECK: [[task_body]]:2806// CHECK: br label %[[task_region:[^, ]+]]2807// CHECK: [[task_region]]:2808// CHECK: %[[sum:.+]] = add i32 %{{.+}}, %{{.+}}2809// CHECK: store i32 %[[sum]], ptr %{{.+}}2810// CHECK: br label %[[exit_stub:[^, ]+]]2811// CHECK: [[exit_stub]]:2812// CHECK: ret void2813 2814// -----2815 2816llvm.func @par_task_(%arg0: !llvm.ptr {fir.bindc_name = "a"}) {2817 %0 = llvm.mlir.constant(1 : i32) : i322818 omp.task {2819 omp.parallel {2820 llvm.store %0, %arg0 : i32, !llvm.ptr2821 omp.terminator2822 }2823 omp.terminator2824 }2825 llvm.return2826}2827 2828// CHECK-LABEL: @par_task_2829// CHECK: %[[ARG_ALLOC:.*]] = alloca { ptr }, align 82830// CHECK: %[[TASK_ALLOC:.*]] = call ptr @__kmpc_omp_task_alloc({{.*}}ptr @[[task_outlined_fn:.+]])2831// CHECK: call i32 @__kmpc_omp_task({{.*}}, ptr %[[TASK_ALLOC]])2832// CHECK: define internal void @[[task_outlined_fn]](i32 %[[GLOBAL_TID_VAL:.*]], ptr %[[STRUCT_ARG:.*]])2833// CHECK: %[[LOADED_STRUCT_PTR:.*]] = load ptr, ptr %[[STRUCT_ARG]], align 82834// CHECK: %[[GEP_STRUCTARG:.*]] = getelementptr { ptr }, ptr %[[LOADED_STRUCT_PTR]], i32 0, i32 02835// CHECK: %[[LOADGEP_STRUCTARG:.*]] = load ptr, ptr %[[GEP_STRUCTARG]], align 82836// CHEKC: %[[NEW_STRUCTARG:.*]] = alloca { ptr }, align 82837// CHECK: call void ({{.*}}) @__kmpc_fork_call({{.*}}, ptr @[[parallel_outlined_fn:.+]],2838// CHECK: define internal void @[[parallel_outlined_fn]]2839// -----2840 2841llvm.func @foo(!llvm.ptr) -> ()2842llvm.func @destroy(!llvm.ptr) -> ()2843 2844omp.private {type = firstprivate} @privatizer : i32 copy {2845^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):2846 %0 = llvm.load %arg0 : !llvm.ptr -> i322847 llvm.store %0, %arg1 : i32, !llvm.ptr2848 omp.yield(%arg1 : !llvm.ptr)2849} dealloc {2850^bb0(%arg0 : !llvm.ptr):2851 llvm.call @destroy(%arg0) : (!llvm.ptr) -> ()2852 omp.yield2853}2854 2855llvm.func @task(%arg0 : !llvm.ptr) {2856 omp.task private(@privatizer %arg0 -> %arg1 : !llvm.ptr) {2857 llvm.call @foo(%arg1) : (!llvm.ptr) -> ()2858 omp.terminator2859 }2860 llvm.return2861}2862// CHECK-LABEL: @task2863// CHECK-SAME: (ptr %[[ARG:.*]])2864// CHECK: %[[STRUCT_ARG:.*]] = alloca { ptr }, align 82865// ...2866// CHECK: br label %omp.private.init2867// CHECK: omp.private.init:2868// CHECK: %[[TASK_STRUCT:.*]] = tail call ptr @malloc(i64 ptrtoint (ptr getelementptr ({ i32 }, ptr null, i32 1) to i64))2869// CHECK: %[[GEP:.*]] = getelementptr { i32 }, ptr %[[TASK_STRUCT:.*]], i32 0, i32 02870// CHECK: br label %omp.private.copy12871// CHECK: omp.private.copy1:2872// CHECK: %[[LOADED:.*]] = load i32, ptr %[[ARG]], align 42873// CHECK: store i32 %[[LOADED]], ptr %[[GEP]], align 42874// ...2875// CHECK: br label %omp.task.start2876// CHECK: omp.task.start:2877// CHECK: br label %[[CODEREPL:.*]]2878// CHECK: [[CODEREPL]]:2879 2880// CHECK-LABEL: @task..omp_par2881// CHECK: task.alloca:2882// CHECK: %[[VAL_12:.*]] = load ptr, ptr %[[STRUCT_ARG:.*]], align 82883// CHECK: %[[VAL_13:.*]] = getelementptr { ptr }, ptr %[[VAL_12]], i32 0, i32 02884// CHECK: %[[VAL_14:.*]] = load ptr, ptr %[[VAL_13]], align 82885// CHECK: br label %task.body2886// CHECK: task.body: ; preds = %task.alloca2887// CHECK: %[[VAL_15:.*]] = getelementptr { i32 }, ptr %[[VAL_14]], i32 0, i32 02888// CHECK: br label %omp.task.region2889// CHECK: omp.task.region: ; preds = %task.body2890// CHECK: call void @foo(ptr %[[VAL_15]])2891// CHECK: br label %omp.region.cont2892// CHECK: omp.region.cont: ; preds = %omp.task.region2893// CHECK: call void @destroy(ptr %[[VAL_15]])2894// CHECK: br label %task.exit.exitStub2895// CHECK: task.exit.exitStub: ; preds = %omp.region.cont2896// CHECK: ret void2897// -----2898 2899llvm.func @foo() -> ()2900 2901llvm.func @omp_taskgroup(%x: i32, %y: i32, %zaddr: !llvm.ptr) {2902 omp.taskgroup {2903 llvm.call @foo() : () -> ()2904 omp.terminator2905 }2906 llvm.return2907}2908 2909// CHECK-LABEL: define void @omp_taskgroup(2910// CHECK-SAME: i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])2911// CHECK: br label %[[entry:[^,]+]]2912// CHECK: [[entry]]:2913// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})2914// CHECK: call void @__kmpc_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])2915// CHECK: br label %[[omp_taskgroup_region:[^,]+]]2916// CHECK: [[omp_taskgroup_region]]:2917// CHECK: call void @foo()2918// CHECK: br label %[[omp_region_cont:[^,]+]]2919// CHECK: [[omp_region_cont]]:2920// CHECK: br label %[[taskgroup_exit:[^,]+]]2921// CHECK: [[taskgroup_exit]]:2922// CHECK: call void @__kmpc_end_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])2923// CHECK: ret void2924 2925// -----2926 2927llvm.func @foo() -> ()2928llvm.func @bar(i32, i32, !llvm.ptr) -> ()2929 2930llvm.func @omp_taskgroup_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {2931 omp.taskgroup {2932 %c1 = llvm.mlir.constant(1) : i322933 %ptr1 = llvm.alloca %c1 x i8 : (i32) -> !llvm.ptr2934 omp.task {2935 llvm.call @foo() : () -> ()2936 omp.terminator2937 }2938 omp.task {2939 llvm.call @bar(%x, %y, %zaddr) : (i32, i32, !llvm.ptr) -> ()2940 omp.terminator2941 }2942 llvm.br ^bb12943 ^bb1:2944 llvm.call @foo() : () -> ()2945 omp.terminator2946 }2947 llvm.return2948}2949 2950// CHECK-LABEL: define void @omp_taskgroup_task(2951// CHECK-SAME: i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])2952// CHECK: %[[structArg:.+]] = alloca { i32, i32, ptr }, align 82953// CHECK: br label %[[entry:[^,]+]]2954// CHECK: [[entry]]: ; preds = %32955// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})2956// CHECK: call void @__kmpc_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])2957// CHECK: br label %[[omp_taskgroup_region:[^,]+]]2958// CHECK: [[omp_taskgroup_region1:.+]]:2959// CHECK: call void @foo()2960// CHECK: br label %[[omp_region_cont:[^,]+]]2961// CHECK: [[omp_taskgroup_region]]:2962// CHECK: %{{.+}} = alloca i8, align 12963// CHECK: br label %[[omp_private_init:[^,]+]]2964// CHECK: [[omp_private_init]]:2965// CHECK: br label %[[omp_private_copy:[^,]+]]2966// CHECK: [[omp_private_copy]]:2967// CHECK: br label %[[omp_task_start:[^,]+]]2968 2969// CHECK: [[omp_region_cont:[^,]+]]:2970// CHECK: br label %[[taskgroup_exit:[^,]+]]2971// CHECK: [[taskgroup_exit]]:2972// CHECK: call void @__kmpc_end_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])2973// CHECK: ret void2974 2975// CHECK: [[omp_task_start]]:2976// CHECK: br label %[[codeRepl:[^,]+]]2977// CHECK: [[codeRepl]]:2978// CHECK: %[[omp_global_thread_num_t1:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})2979// CHECK: %[[t1_alloc:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num_t1]], i32 1, i64 40, i64 0, ptr @[[outlined_task_fn:.+]])2980// CHECK: %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num_t1]], ptr %[[t1_alloc]])2981// CHECK: br label %[[task_exit:[^,]+]]2982// CHECK: [[task_exit]]:2983// CHECK: br label %[[codeRepl9:[^,]+]]2984// CHECK: [[codeRepl9]]:2985// CHECK: %[[gep1:.+]] = getelementptr { i32, i32, ptr }, ptr %[[structArg]], i32 0, i32 02986// CHECK: store i32 %[[x]], ptr %[[gep1]], align 42987// CHECK: %[[gep2:.+]] = getelementptr { i32, i32, ptr }, ptr %[[structArg]], i32 0, i32 12988// CHECK: store i32 %[[y]], ptr %[[gep2]], align 42989// CHECK: %[[gep3:.+]] = getelementptr { i32, i32, ptr }, ptr %[[structArg]], i32 0, i32 22990// CHECK: store ptr %[[zaddr]], ptr %[[gep3]], align 82991// CHECK: %[[omp_global_thread_num_t2:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})2992// CHECK: %[[t2_alloc:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num_t2]], i32 1, i64 40, i64 16, ptr @[[outlined_task_fn:.+]])2993// CHECK: %[[shareds:.+]] = load ptr, ptr %[[t2_alloc]]2994// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[shareds]], ptr align 1 %[[structArg]], i64 16, i1 false)2995// CHECK: %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num_t2]], ptr %[[t2_alloc]])2996// CHECK: br label %[[task_exit3:[^,]+]]2997// CHECK: [[task_exit3]]:2998// CHECK: br label %[[omp_taskgroup_region1]]2999// CHECK: }3000 3001// -----3002 3003llvm.func @test_01() attributes {sym_visibility = "private"}3004llvm.func @test_02() attributes {sym_visibility = "private"}3005// CHECK-LABEL: define void @_QPomp_task_priority() {3006llvm.func @_QPomp_task_priority() {3007 %0 = llvm.mlir.constant(1 : i64) : i643008 %1 = llvm.alloca %0 x i32 {bindc_name = "x"} : (i64) -> !llvm.ptr3009 %2 = llvm.mlir.constant(4 : i32) : i323010 %3 = llvm.mlir.constant(true) : i13011 %4 = llvm.load %1 : !llvm.ptr -> i323012// CHECK: %[[GID_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})3013// CHECK: %[[I_01:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[GID_01]], i32 33, i64 40, i64 0, ptr @{{.*}})3014// CHECK: %[[I_02:.*]] = getelementptr inbounds { ptr }, ptr %[[I_01]], i32 0, i32 03015// CHECK: %[[I_03:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_02]], i32 0, i32 43016// CHECK: %[[I_04:.*]] = getelementptr inbounds { ptr, ptr }, ptr %[[I_03]], i32 0, i32 03017// CHECK: store i32 {{.*}}, ptr %[[I_04]], align 43018// CHECK: %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[GID_01]], ptr %[[I_01]])3019 omp.task priority(%4 : i32) {3020 llvm.call @test_01() : () -> ()3021 omp.terminator3022 }3023// CHECK: %[[GID_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})3024// CHECK: %[[I_05:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[GID_02]], i32 35, i64 40, i64 0, ptr @{{.*}})3025// CHECK: %[[I_06:.*]] = getelementptr inbounds { ptr }, ptr %[[I_05]], i32 0, i32 03026// CHECK: %[[I_07:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_06]], i32 0, i32 43027// CHECK: %[[I_08:.*]] = getelementptr inbounds { ptr, ptr }, ptr %[[I_07]], i32 0, i32 03028// CHECK: store i32 4, ptr %[[I_08]], align 43029// CHECK: %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[GID_02]], ptr %[[I_05]])3030 omp.task final(%3) priority(%2 : i32) {3031 llvm.call @test_02() : () -> ()3032 omp.terminator3033 }3034 llvm.return3035// CHECK: ret void3036// CHECK: }3037}3038 3039// -----3040 3041// CHECK-LABEL: @omp_opaque_pointers3042// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]], i32 %[[EXPR:.*]])3043llvm.func @omp_opaque_pointers(%arg0 : !llvm.ptr, %arg1: !llvm.ptr, %expr: i32) -> () {3044 // CHECK: %[[X1:.*]] = load atomic i32, ptr %[[ARG0]] monotonic, align 43045 // CHECK: store i32 %[[X1]], ptr %[[ARG1]], align 43046 omp.atomic.read %arg1 = %arg0 : !llvm.ptr, !llvm.ptr, i323047 3048 // CHECK: %[[RES:.*]] = atomicrmw add ptr %[[ARG1]], i32 %[[EXPR]] acq_rel3049 // CHECK: store i32 %[[RES]], ptr %[[ARG0]]3050 omp.atomic.capture memory_order(acq_rel) {3051 omp.atomic.read %arg0 = %arg1 : !llvm.ptr, !llvm.ptr, i323052 omp.atomic.update %arg1 : !llvm.ptr {3053 ^bb0(%xval: i32):3054 %newval = llvm.add %xval, %expr : i323055 omp.yield(%newval : i32)3056 }3057 }3058 llvm.return3059}3060 3061// -----3062 3063// CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 13064// CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 13065// CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 13066// CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 13067// CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 13068module attributes {omp.flags = #omp.flags<debug_kind = 1, assume_teams_oversubscription = true, 3069 assume_threads_oversubscription = true, assume_no_thread_state = true, 3070 assume_no_nested_parallelism = true>} {}3071// -----3072 3073// CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 03074// CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 03075// CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 03076// CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 03077// CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 03078// CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 50}3079module attributes {omp.flags = #omp.flags<>} {}3080 3081// -----3082 3083// CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 03084// CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 03085// CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 03086// CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 03087// CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 03088// CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 51}3089module attributes {omp.flags = #omp.flags<openmp_device_version = 51>} {}3090 3091// -----3092 3093// CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 03094// CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 03095// CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 03096// CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 03097// CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 03098// CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 50}3099// CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp", i32 50}3100module attributes {omp.version = #omp.version<version = 50>, omp.flags = #omp.flags<>} {}3101 3102// -----3103 3104// CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp", i32 51}3105// CHECK-NOT: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 50}3106module attributes {omp.version = #omp.version<version = 51>} {}3107 3108// -----3109// CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 03110// CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 03111// CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 03112// CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 03113// CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 03114module attributes {omp.flags = #omp.flags<debug_kind = 0, assume_teams_oversubscription = false, 3115 assume_threads_oversubscription = false, assume_no_thread_state = false, 3116 assume_no_nested_parallelism = false>} {}3117 3118// -----3119 3120// CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 03121// CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 13122// CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 03123// CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 13124// CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 03125module attributes {omp.flags = #omp.flags<assume_teams_oversubscription = true, assume_no_thread_state = true>} {}3126 3127// -----3128 3129// CHECK-NOT: @__omp_rtl_debug_kind = weak_odr hidden constant i32 03130// CHECK-NOT: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 13131// CHECK-NOT: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 03132// CHECK-NOT: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 13133// CHECK-NOT: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 03134module attributes {omp.flags = #omp.flags<assume_teams_oversubscription = true, assume_no_thread_state = true,3135 no_gpu_lib=true>} {}3136 3137// -----3138 3139module attributes {omp.is_target_device = false} {3140 // CHECK: define void @filter_nohost3141 llvm.func @filter_nohost() -> ()3142 attributes {3143 omp.declare_target =3144 #omp.declaretarget<device_type = (nohost), capture_clause = (to)>3145 } {3146 llvm.return3147 }3148 3149 // CHECK: define void @filter_host3150 llvm.func @filter_host() -> ()3151 attributes {3152 omp.declare_target =3153 #omp.declaretarget<device_type = (host), capture_clause = (to)>3154 } {3155 llvm.return3156 }3157}3158 3159// -----3160 3161module attributes {omp.is_target_device = false} {3162 // CHECK: define void @filter_nohost3163 llvm.func @filter_nohost() -> ()3164 attributes {3165 omp.declare_target =3166 #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>3167 } {3168 llvm.return3169 }3170 3171 // CHECK: define void @filter_host3172 llvm.func @filter_host() -> ()3173 attributes {3174 omp.declare_target =3175 #omp.declaretarget<device_type = (host), capture_clause = (enter)>3176 } {3177 llvm.return3178 }3179}3180 3181// -----3182 3183module attributes {omp.is_target_device = true} {3184 // CHECK: define void @filter_nohost3185 llvm.func @filter_nohost() -> ()3186 attributes {3187 omp.declare_target =3188 #omp.declaretarget<device_type = (nohost), capture_clause = (to)>3189 } {3190 llvm.return3191 }3192 3193 // CHECK-NOT: define void @filter_host3194 llvm.func @filter_host() -> ()3195 attributes {3196 omp.declare_target =3197 #omp.declaretarget<device_type = (host), capture_clause = (to)>3198 } {3199 llvm.return3200 }3201}3202 3203// -----3204 3205module attributes {omp.is_target_device = true} {3206 // CHECK: define void @filter_nohost3207 llvm.func @filter_nohost() -> ()3208 attributes {3209 omp.declare_target =3210 #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>3211 } {3212 llvm.return3213 }3214 3215 // CHECK-NOT: define void @filter_host3216 llvm.func @filter_host() -> ()3217 attributes {3218 omp.declare_target =3219 #omp.declaretarget<device_type = (host), capture_clause = (enter)>3220 } {3221 llvm.return3222 }3223}3224 3225// -----3226 3227llvm.func @omp_task_untied() {3228 // The third argument is 0: which signifies the untied task3229 // CHECK: {{.*}} = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %{{.*}}, i32 0,3230 // CHECK-SAME: i64 40, i64 0, ptr @{{.*}})3231 omp.task untied {3232 omp.terminator3233 }3234 llvm.return3235}3236 3237// -----3238 3239// Third argument is 5: essentially (4 || 1)3240// signifying this task is TIED and MERGEABLE3241 3242// CHECK: {{.*}} = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %omp_global_thread_num, i32 5, i64 40, i64 0, ptr @omp_task_mergeable..omp_par)3243llvm.func @omp_task_mergeable() {3244 omp.task mergeable {3245 omp.terminator3246 }3247 llvm.return3248}3249 3250// -----3251 3252llvm.func external @foo_before() -> ()3253llvm.func external @foo() -> ()3254llvm.func external @foo_after() -> ()3255 3256llvm.func @omp_task_final(%boolexpr: i1) {3257 llvm.call @foo_before() : () -> ()3258 omp.task final(%boolexpr) {3259 llvm.call @foo() : () -> ()3260 omp.terminator3261 }3262 llvm.call @foo_after() : () -> ()3263 llvm.return3264}3265 3266// CHECK-LABEL: define void @omp_task_final(3267// CHECK-SAME: i1 %[[boolexpr:.+]]) {3268// CHECK: call void @foo_before()3269// CHECK: br label %[[entry:[^,]+]]3270// CHECK: [[entry]]:3271// CHECK: br label %[[codeRepl:[^,]+]]3272// CHECK: [[codeRepl]]: ; preds = %entry3273// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})3274// CHECK: %[[final_flag:.+]] = select i1 %[[boolexpr]], i32 2, i32 03275// CHECK: %[[task_flags:.+]] = or i32 %[[final_flag]], 13276// CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 %[[task_flags]], i64 40, i64 0, ptr @[[task_outlined_fn:.+]])3277// CHECK: %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])3278// CHECK: br label %[[task_exit:[^,]+]]3279// CHECK: [[task_exit]]:3280// CHECK: call void @foo_after()3281// CHECK: ret void3282 3283// -----3284 3285llvm.func external @foo_before() -> ()3286llvm.func external @foo() -> ()3287llvm.func external @foo_after() -> ()3288 3289llvm.func @omp_task_if(%boolexpr: i1) {3290 llvm.call @foo_before() : () -> ()3291 omp.task if(%boolexpr) {3292 llvm.call @foo() : () -> ()3293 omp.terminator3294 }3295 llvm.call @foo_after() : () -> ()3296 llvm.return3297}3298 3299// CHECK-LABEL: define void @omp_task_if(3300// CHECK-SAME: i1 %[[boolexpr:.+]]) {3301// CHECK: call void @foo_before()3302// CHECK: br label %[[entry:[^,]+]]3303// CHECK: [[entry]]:3304// CHECK: br label %[[codeRepl:[^,]+]]3305// CHECK: [[codeRepl]]:3306// CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})3307// CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40, i64 0, ptr @[[task_outlined_fn:.+]])3308// CHECK: br i1 %[[boolexpr]], label %[[true_label:[^,]+]], label %[[false_label:[^,]+]]3309// CHECK: [[true_label]]:3310// CHECK: %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])3311// CHECK: br label %[[if_else_exit:[^,]+]]3312// CHECK: [[false_label:[^,]+]]: ; preds = %codeRepl3313// CHECK: call void @__kmpc_omp_task_begin_if0(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])3314// CHECK: call void @[[task_outlined_fn]](i32 %[[omp_global_thread_num]])3315// CHECK: call void @__kmpc_omp_task_complete_if0(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])3316// CHECK: br label %[[if_else_exit]]3317// CHECK: [[if_else_exit]]:3318// CHECK: br label %[[task_exit:[^,]+]]3319// CHECK: [[task_exit]]:3320// CHECK: call void @foo_after()3321// CHECK: ret void3322 3323// -----3324 3325module attributes {omp.requires = #omp<clause_requires reverse_offload|unified_shared_memory>} {}3326 3327// -----3328 3329llvm.func @distribute() {3330 %0 = llvm.mlir.constant(42 : index) : i643331 %1 = llvm.mlir.constant(10 : index) : i643332 %2 = llvm.mlir.constant(1 : index) : i643333 omp.distribute {3334 omp.loop_nest (%arg1) : i64 = (%1) to (%0) step (%2) {3335 omp.yield3336 }3337 }3338 llvm.return3339}3340 3341// CHECK-LABEL: define void @distribute3342// CHECK: %[[LASTITER:.*]] = alloca i323343// CHECK: %[[LB:.*]] = alloca i643344// CHECK: %[[UB:.*]] = alloca i643345// CHECK: %[[STRIDE:.*]] = alloca i643346// CHECK: br label %[[BODY:.*]]3347// CHECK: [[BODY]]:3348// CHECK-NEXT: br label %[[REGION:.*]]3349// CHECK: [[REGION]]:3350// CHECK-NEXT: br label %[[PREHEADER:.*]]3351// CHECK: [[PREHEADER]]:3352// CHECK: store i64 0, ptr %[[LB]]3353// CHECK: store i64 31, ptr %[[UB]]3354// CHECK: store i64 1, ptr %[[STRIDE]]3355// CHECK: %[[TID:.*]] = call i32 @__kmpc_global_thread_num({{.*}})3356// CHECK: call void @__kmpc_for_static_init_{{.*}}(ptr @{{.*}}, i32 %[[TID]], i32 92, ptr %[[LASTITER]], ptr %[[LB]], ptr %[[UB]], ptr %[[STRIDE]], i64 1, i64 0)3357 3358// -----3359 3360llvm.func @distribute_wsloop(%lb : i32, %ub : i32, %step : i32) {3361 omp.parallel {3362 omp.distribute {3363 omp.wsloop {3364 omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {3365 omp.yield3366 }3367 } {omp.composite}3368 } {omp.composite}3369 omp.terminator3370 } {omp.composite}3371 llvm.return3372}3373 3374// CHECK-LABEL: define void @distribute_wsloop3375// CHECK: call void{{.*}}@__kmpc_fork_call({{.*}}, ptr @[[OUTLINED_PARALLEL:.*]],3376 3377// CHECK: define internal void @[[OUTLINED_PARALLEL]]3378// CHECK: distribute.alloca:3379// CHECK: %[[LASTITER:.*]] = alloca i323380// CHECK: %[[LB:.*]] = alloca i323381// CHECK: %[[UB:.*]] = alloca i323382// CHECK: %[[STRIDE:.*]] = alloca i323383// CHECK: br label %[[AFTER_ALLOCA:.*]]3384 3385// CHECK: [[AFTER_ALLOCA]]:3386// CHECK: br label %[[DISTRIBUTE_BODY:.*]]3387 3388// CHECK: [[DISTRIBUTE_BODY]]:3389// CHECK-NEXT: br label %[[DISTRIBUTE_REGION:.*]]3390 3391// CHECK: [[DISTRIBUTE_REGION]]:3392// CHECK-NEXT: br label %[[WSLOOP_REGION:.*]]3393 3394// CHECK: [[WSLOOP_REGION]]:3395// CHECK: %omp_loop.tripcount = select {{.*}}3396// CHECK-NEXT: br label %[[PREHEADER:.*]]3397 3398// CHECK: [[PREHEADER]]:3399// CHECK: store i32 0, ptr %[[LB]]3400// CHECK: %[[TRIPCOUNT:.*]] = sub i32 %omp_loop.tripcount, 13401// CHECK: store i32 %[[TRIPCOUNT]], ptr %[[UB]]3402// CHECK: store i32 1, ptr %[[STRIDE]]3403// CHECK: %[[TID:.*]] = call i32 @__kmpc_global_thread_num({{.*}})3404// CHECK: %[[DIST_UB:.*]] = alloca i323405// CHECK: call void @__kmpc_dist_for_static_init_{{.*}}(ptr @{{.*}}, i32 %[[TID]], i32 34, ptr %[[LASTITER]], ptr %[[LB]], ptr %[[UB]], ptr %[[DIST_UB]], ptr %[[STRIDE]], i32 1, i32 0)3406 3407// -----3408 3409omp.private {type = private} @_QFEx_private_i32 : i323410llvm.func @nested_task_with_deps() {3411 %0 = llvm.mlir.constant(1 : i64) : i643412 %1 = llvm.alloca %0 x i32 {bindc_name = "x"} : (i64) -> !llvm.ptr3413 %2 = llvm.mlir.constant(1 : i64) : i643414 omp.parallel private(@_QFEx_private_i32 %1 -> %arg0 : !llvm.ptr) {3415 omp.task depend(taskdependout -> %arg0 : !llvm.ptr) {3416 omp.terminator3417 }3418 omp.terminator3419 }3420 llvm.return3421}3422 3423// CHECK-LABEL: define void @nested_task_with_deps() {3424// CHECK: %[[PAR_FORK_ARG:.*]] = alloca { ptr }, align 83425// CHECK: %[[DEP_ARR:.*]] = alloca [1 x %struct.kmp_dep_info], align 83426 3427// CHECK: omp_parallel:3428// CHECK-NEXT: %[[DEP_ARR_GEP:.*]] = getelementptr { ptr }, ptr %[[PAR_FORK_ARG]], i32 0, i32 03429// CHECK-NEXT: store ptr %[[DEP_ARR]], ptr %[[DEP_ARR_GEP]], align 83430// CHECK-NEXT: call void {{.*}} @__kmpc_fork_call(ptr @{{.*}}, i32 1, ptr @[[PAR_OUTLINED:.*]], ptr %[[PAR_FORK_ARG]])3431// CHECK-NEXT: br label %[[PAR_EXIT:.*]]3432 3433// CHECK: [[PAR_EXIT]]:3434// CHECK-NEXT: ret void3435// CHECK: }3436 3437// CHECK: define internal void @[[PAR_OUTLINED]]{{.*}} {3438// CHECK: omp.par.entry:3439// CHECK: %[[DEP_ARR_GEP_2:.*]] = getelementptr { ptr }, ptr %{{.*}}, i32 0, i32 03440// CHECK: %[[DEP_ARR_2:.*]] = load ptr, ptr %[[DEP_ARR_GEP_2]], align 83441// CHECK: %[[PRIV_ALLOC:omp.private.alloc]] = alloca i32, align 43442 3443// CHECK: %[[TASK:.*]] = call ptr @__kmpc_omp_task_alloc3444// CHECK: %[[DEP_STRUCT_GEP:.*]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_2]], i64 0, i64 03445// CHECK: %[[DEP_GEP:.*]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_STRUCT_GEP]], i32 0, i32 03446// CHECK: %[[PRIV_ALLOC_TO_INT:.*]] = ptrtoint ptr %[[PRIV_ALLOC]] to i643447// CHECK: store i64 %[[PRIV_ALLOC_TO_INT]], ptr %[[DEP_GEP]], align 43448// CHECK: call i32 @__kmpc_omp_task_with_deps(ptr @{{.*}}, i32 %{{.*}}, ptr %{{.*}}, i32 1, ptr %[[DEP_ARR_2]], i32 0, ptr null)3449 3450// CHECK: ret void3451// CHECK: }3452