brintos

brintos / llvm-project-archived public Read only

0
0
Text · 130.8 KiB · 8bd33a3 Raw
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