1// RUN: mlir-opt -split-input-file %s | mlir-opt | FileCheck %s 2 3func.func @omp_barrier() -> () { 4 // CHECK: omp.barrier 5 omp.barrier 6 return 7} 8 9func.func @omp_master() -> () { 10 // CHECK: omp.master 11 omp.master { 12 // CHECK: omp.terminator 13 omp.terminator 14 } 15 16 return 17} 18 19func.func @omp_taskwait() -> () { 20 // CHECK: omp.taskwait 21 omp.taskwait 22 return 23} 24 25func.func @omp_taskyield() -> () { 26 // CHECK: omp.taskyield 27 omp.taskyield 28 return 29} 30 31// CHECK-LABEL: func @omp_flush 32// CHECK-SAME: ([[ARG0:%.*]]: i32) { 33func.func @omp_flush(%arg0 : i32) -> () { 34 // Test without data var 35 // CHECK: omp.flush 36 omp.flush 37 38 // Test with one data var 39 // CHECK: omp.flush([[ARG0]] : i32) 40 omp.flush(%arg0 : i32) 41 42 // Test with two data var 43 // CHECK: omp.flush([[ARG0]], [[ARG0]] : i32, i32) 44 omp.flush(%arg0, %arg0: i32, i32) 45 46 return 47} 48 49func.func @omp_terminator() -> () { 50 // CHECK: omp.terminator 51 omp.terminator 52} 53 54func.func @omp_parallel(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32) -> () { 55 // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 56 "omp.parallel" (%if_cond, %num_threads, %data_var, %data_var) ({ 57 58 // test without if condition 59 // CHECK: omp.parallel num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 60 "omp.parallel"(%num_threads, %data_var, %data_var) ({ 61 omp.terminator 62 }) {operand_segment_sizes = dense<[0,1,1,1,0]> : vector<5xi32>} : (i32, memref<i32>, memref<i32>) -> () 63 64 // CHECK: omp.barrier 65 omp.barrier 66 67 // test without num_threads 68 // CHECK: omp.parallel if(%{{.*}}) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 69 "omp.parallel"(%if_cond, %data_var, %data_var) ({ 70 omp.terminator 71 }) {operand_segment_sizes = dense<[1,0,1,1,0]> : vector<5xi32>} : (i1, memref<i32>, memref<i32>) -> () 72 73 // test without allocate 74 // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) 75 "omp.parallel"(%if_cond, %num_threads) ({ 76 omp.terminator 77 }) {operand_segment_sizes = dense<[1,1,0,0,0]> : vector<5xi32>} : (i1, i32) -> () 78 79 omp.terminator 80 }) {operand_segment_sizes = dense<[1,1,1,1,0]> : vector<5xi32>, proc_bind_val = #omp<"procbindkind spread">} : (i1, i32, memref<i32>, memref<i32>) -> () 81 82 // test with multiple parameters for single variadic argument 83 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 84 "omp.parallel" (%data_var, %data_var) ({ 85 omp.terminator 86 }) {operand_segment_sizes = dense<[0,0,1,1,0]> : vector<5xi32>} : (memref<i32>, memref<i32>) -> () 87 88 return 89} 90 91func.func @omp_parallel_pretty(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %allocator : si32) -> () { 92 // CHECK: omp.parallel 93 omp.parallel { 94 omp.terminator 95 } 96 97 // CHECK: omp.parallel num_threads(%{{.*}} : i32) 98 omp.parallel num_threads(%num_threads : i32) { 99 omp.terminator 100 } 101 102 %n_index = arith.constant 2 : index 103 // CHECK: omp.parallel num_threads(%{{.*}} : index) 104 omp.parallel num_threads(%n_index : index) { 105 omp.terminator 106 } 107 108 %n_i64 = arith.constant 4 : i64 109 // CHECK: omp.parallel num_threads(%{{.*}} : i64) 110 omp.parallel num_threads(%n_i64 : i64) { 111 omp.terminator 112 } 113 114 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 115 omp.parallel allocate(%data_var : memref<i32> -> %data_var : memref<i32>) { 116 omp.terminator 117 } 118 119 // CHECK: omp.parallel 120 // CHECK-NEXT: omp.parallel if(%{{.*}} : i1) 121 omp.parallel { 122 omp.parallel if(%if_cond: i1) { 123 omp.terminator 124 } 125 omp.terminator 126 } 127 128 // CHECK omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) private(%{{.*}} : memref<i32>) proc_bind(close) 129 omp.parallel num_threads(%num_threads : i32) if(%if_cond: i1) proc_bind(close) { 130 omp.terminator 131 } 132 133 return 134} 135 136// CHECK-LABEL: omp_wsloop 137func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32) -> () { 138 139 // CHECK: omp.wsloop collapse(2) ordered(1) 140 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 141 "omp.wsloop" (%lb, %ub, %step) ({ 142 ^bb0(%iv: index): 143 omp.yield 144 }) {operand_segment_sizes = dense<[1,1,1,0,0,0,0]> : vector<7xi32>, collapse_val = 2, ordered_val = 1} : 145 (index, index, index) -> () 146 147 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static) 148 // CHECK-SAMe: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 149 "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var) ({ 150 ^bb0(%iv: index): 151 omp.yield 152 }) {operand_segment_sizes = dense<[1,1,1,1,1,0,0]> : vector<7xi32>, schedule_val = #omp<"schedulekind static">} : 153 (index, index, index, memref<i32>, i32) -> () 154 155 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>, %{{.*}} = %{{.*}} : memref<i32>) schedule(static) 156 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 157 "omp.wsloop" (%lb, %ub, %step, %data_var, %data_var, %linear_var, %linear_var) ({ 158 ^bb0(%iv: index): 159 omp.yield 160 }) {operand_segment_sizes = dense<[1,1,1,2,2,0,0]> : vector<7xi32>, schedule_val = #omp<"schedulekind static">} : 161 (index, index, index, memref<i32>, memref<i32>, i32, i32) -> () 162 163 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}}) collapse(3) ordered(2) 164 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 165 "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var, %chunk_var) ({ 166 ^bb0(%iv: index): 167 omp.yield 168 }) {operand_segment_sizes = dense<[1,1,1,1,1,0,1]> : vector<7xi32>, schedule_val = #omp<"schedulekind dynamic">, collapse_val = 3, ordered_val = 2} : 169 (index, index, index, memref<i32>, i32, i32) -> () 170 171 // CHECK: omp.wsloop schedule(auto) nowait 172 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 173 "omp.wsloop" (%lb, %ub, %step) ({ 174 ^bb0(%iv: index): 175 omp.yield 176 }) {operand_segment_sizes = dense<[1,1,1,0,0,0,0]> : vector<7xi32>, nowait, schedule_val = #omp<"schedulekind auto">} : 177 (index, index, index) -> () 178 179 return 180} 181 182// CHECK-LABEL: omp_wsloop_pretty 183func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32, %chunk_var2 : i16) -> () { 184 185 // CHECK: omp.wsloop collapse(2) ordered(2) 186 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 187 omp.wsloop collapse(2) ordered(2) 188 for (%iv) : index = (%lb) to (%ub) step (%step) { 189 omp.yield 190 } 191 192 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static) 193 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 194 omp.wsloop schedule(static) linear(%data_var = %linear_var : memref<i32>) 195 for (%iv) : index = (%lb) to (%ub) step (%step) { 196 omp.yield 197 } 198 199 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static = %{{.*}} : i32) collapse(3) ordered(2) 200 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 201 omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(static = %chunk_var : i32) collapse(3) 202 for (%iv) : index = (%lb) to (%ub) step (%step) { 203 omp.yield 204 } 205 206 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}} : i32, nonmonotonic) collapse(3) ordered(2) 207 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 208 omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var : i32, nonmonotonic) collapse(3) 209 for (%iv) : index = (%lb) to (%ub) step (%step) { 210 omp.yield 211 } 212 213 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}} : i16, monotonic) collapse(3) ordered(2) 214 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 215 omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var2 : i16, monotonic) collapse(3) 216 for (%iv) : index = (%lb) to (%ub) step (%step) { 217 omp.yield 218 } 219 220 // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 221 omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { 222 omp.yield 223 } 224 225 // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}}) 226 omp.wsloop for (%iv) : index = (%lb) to (%ub) inclusive step (%step) { 227 omp.yield 228 } 229 230 // CHECK: omp.wsloop nowait 231 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 232 omp.wsloop nowait 233 for (%iv) : index = (%lb) to (%ub) step (%step) { 234 omp.yield 235 } 236 237 // CHECK: omp.wsloop nowait order(concurrent) 238 // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 239 omp.wsloop order(concurrent) nowait 240 for (%iv) : index = (%lb) to (%ub) step (%step) { 241 omp.yield 242 } 243 244 return 245} 246 247// CHECK-LABEL: omp_wsloop_pretty_multi_block 248func.func @omp_wsloop_pretty_multi_block(%lb : index, %ub : index, %step : index, %data1 : memref<?xi32>, %data2 : memref<?xi32>) -> () { 249 250 // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 251 omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { 252 %1 = "test.payload"(%iv) : (index) -> (i32) 253 cf.br ^bb1(%1: i32) 254 ^bb1(%arg: i32): 255 memref.store %arg, %data1[%iv] : memref<?xi32> 256 omp.yield 257 } 258 259 // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 260 omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { 261 %c = "test.condition"(%iv) : (index) -> (i1) 262 %v1 = "test.payload"(%iv) : (index) -> (i32) 263 cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32) 264 ^bb1(%arg0: i32): 265 memref.store %arg0, %data1[%iv] : memref<?xi32> 266 cf.br ^bb3 267 ^bb2(%arg1: i32): 268 memref.store %arg1, %data2[%iv] : memref<?xi32> 269 cf.br ^bb3 270 ^bb3: 271 omp.yield 272 } 273 274 // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 275 omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { 276 %c = "test.condition"(%iv) : (index) -> (i1) 277 %v1 = "test.payload"(%iv) : (index) -> (i32) 278 cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32) 279 ^bb1(%arg0: i32): 280 memref.store %arg0, %data1[%iv] : memref<?xi32> 281 omp.yield 282 ^bb2(%arg1: i32): 283 memref.store %arg1, %data2[%iv] : memref<?xi32> 284 omp.yield 285 } 286 287 return 288} 289 290// CHECK-LABEL: omp_wsloop_pretty_non_index 291func.func @omp_wsloop_pretty_non_index(%lb1 : i32, %ub1 : i32, %step1 : i32, %lb2 : i64, %ub2 : i64, %step2 : i64, 292 %data1 : memref<?xi32>, %data2 : memref<?xi64>) -> () { 293 294 // CHECK: omp.wsloop for (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 295 omp.wsloop for (%iv1) : i32 = (%lb1) to (%ub1) step (%step1) { 296 %1 = "test.payload"(%iv1) : (i32) -> (index) 297 cf.br ^bb1(%1: index) 298 ^bb1(%arg1: index): 299 memref.store %iv1, %data1[%arg1] : memref<?xi32> 300 omp.yield 301 } 302 303 // CHECK: omp.wsloop for (%{{.*}}) : i64 = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 304 omp.wsloop for (%iv2) : i64 = (%lb2) to (%ub2) step (%step2) { 305 %2 = "test.payload"(%iv2) : (i64) -> (index) 306 cf.br ^bb1(%2: index) 307 ^bb1(%arg2: index): 308 memref.store %iv2, %data2[%arg2] : memref<?xi64> 309 omp.yield 310 } 311 312 return 313} 314 315// CHECK-LABEL: omp_wsloop_pretty_multiple 316func.func @omp_wsloop_pretty_multiple(%lb1 : i32, %ub1 : i32, %step1 : i32, %lb2 : i32, %ub2 : i32, %step2 : i32, %data1 : memref<?xi32>) -> () { 317 318 // CHECK: omp.wsloop for (%{{.*}}, %{{.*}}) : i32 = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}}) 319 omp.wsloop for (%iv1, %iv2) : i32 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) { 320 %1 = "test.payload"(%iv1) : (i32) -> (index) 321 %2 = "test.payload"(%iv2) : (i32) -> (index) 322 memref.store %iv1, %data1[%1] : memref<?xi32> 323 memref.store %iv2, %data1[%2] : memref<?xi32> 324 omp.yield 325 } 326 327 return 328} 329 330// CHECK-LABEL: omp_simdloop 331func.func @omp_simdloop(%lb : index, %ub : index, %step : index) -> () { 332 // CHECK: omp.simdloop (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 333 "omp.simdloop" (%lb, %ub, %step) ({ 334 ^bb0(%iv: index): 335 omp.yield 336 }) {operand_segment_sizes = dense<[1,1,1]> : vector<3xi32>} : 337 (index, index, index) -> () 338 339 return 340} 341 342 343// CHECK-LABEL: omp_simdloop_pretty 344func.func @omp_simdloop_pretty(%lb : index, %ub : index, %step : index) -> () { 345 // CHECK: omp.simdloop (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) 346 omp.simdloop (%iv) : index = (%lb) to (%ub) step (%step) { 347 omp.yield 348 } 349 return 350} 351 352// CHECK-LABEL: omp_simdloop_pretty_multiple 353func.func @omp_simdloop_pretty_multiple(%lb1 : index, %ub1 : index, %step1 : index, %lb2 : index, %ub2 : index, %step2 : index) -> () { 354 // CHECK: omp.simdloop (%{{.*}}, %{{.*}}) : index = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}}) 355 omp.simdloop (%iv1, %iv2) : index = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) { 356 omp.yield 357 } 358 return 359} 360 361// CHECK-LABEL: omp_target 362func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32) -> () { 363 364 // Test with optional operands; if_expr, device, thread_limit, private, firstprivate and nowait. 365 // CHECK: omp.target if({{.*}}) device({{.*}}) thread_limit({{.*}}) nowait 366 "omp.target"(%if_cond, %device, %num_threads) ({ 367 // CHECK: omp.terminator 368 omp.terminator 369 }) {nowait, operand_segment_sizes = dense<[1,1,1]>: vector<3xi32>} : ( i1, si32, i32 ) -> () 370 371 // CHECK: omp.barrier 372 omp.barrier 373 374 return 375} 376 377// CHECK-LABEL: omp_target_pretty 378func.func @omp_target_pretty(%if_cond : i1, %device : si32, %num_threads : i32) -> () { 379 // CHECK: omp.target if({{.*}}) device({{.*}}) 380 omp.target if(%if_cond) device(%device : si32) { 381 omp.terminator 382 } 383 384 // CHECK: omp.target if({{.*}}) device({{.*}}) nowait 385 omp.target if(%if_cond) device(%device : si32) thread_limit(%num_threads : i32) nowait { 386 omp.terminator 387 } 388 389 return 390} 391 392// CHECK: omp.reduction.declare 393// CHECK-LABEL: @add_f32 394// CHECK: : f32 395// CHECK: init 396// CHECK: ^{{.+}}(%{{.+}}: f32): 397// CHECK: omp.yield 398// CHECK: combiner 399// CHECK: ^{{.+}}(%{{.+}}: f32, %{{.+}}: f32): 400// CHECK: omp.yield 401// CHECK: atomic 402// CHECK: ^{{.+}}(%{{.+}}: !llvm.ptr<f32>, %{{.+}}: !llvm.ptr<f32>): 403// CHECK: omp.yield 404omp.reduction.declare @add_f32 : f32 405init { 406^bb0(%arg: f32): 407 %0 = arith.constant 0.0 : f32 408 omp.yield (%0 : f32) 409} 410combiner { 411^bb1(%arg0: f32, %arg1: f32): 412 %1 = arith.addf %arg0, %arg1 : f32 413 omp.yield (%1 : f32) 414} 415atomic { 416^bb2(%arg2: !llvm.ptr<f32>, %arg3: !llvm.ptr<f32>): 417 %2 = llvm.load %arg3 : !llvm.ptr<f32> 418 llvm.atomicrmw fadd %arg2, %2 monotonic : f32 419 omp.yield 420} 421 422// CHECK-LABEL: func @wsloop_reduction 423func.func @wsloop_reduction(%lb : index, %ub : index, %step : index) { 424 %c1 = arith.constant 1 : i32 425 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32> 426 // CHECK: reduction(@add_f32 -> %{{.+}} : !llvm.ptr<f32>) 427 omp.wsloop reduction(@add_f32 -> %0 : !llvm.ptr<f32>) 428 for (%iv) : index = (%lb) to (%ub) step (%step) { 429 %1 = arith.constant 2.0 : f32 430 // CHECK: omp.reduction %{{.+}}, %{{.+}} 431 omp.reduction %1, %0 : !llvm.ptr<f32> 432 omp.yield 433 } 434 return 435} 436 437// CHECK-LABEL: func @parallel_reduction 438func.func @parallel_reduction() { 439 %c1 = arith.constant 1 : i32 440 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32> 441 // CHECK: omp.parallel reduction(@add_f32 -> {{.+}} : !llvm.ptr<f32>) 442 omp.parallel reduction(@add_f32 -> %0 : !llvm.ptr<f32>) { 443 %1 = arith.constant 2.0 : f32 444 // CHECK: omp.reduction %{{.+}}, %{{.+}} 445 omp.reduction %1, %0 : !llvm.ptr<f32> 446 omp.terminator 447 } 448 return 449} 450 451// CHECK: func @parallel_wsloop_reduction 452func.func @parallel_wsloop_reduction(%lb : index, %ub : index, %step : index) { 453 %c1 = arith.constant 1 : i32 454 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32> 455 // CHECK: omp.parallel reduction(@add_f32 -> %{{.+}} : !llvm.ptr<f32>) { 456 omp.parallel reduction(@add_f32 -> %0 : !llvm.ptr<f32>) { 457 // CHECK: omp.wsloop for (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}}) 458 omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { 459 %1 = arith.constant 2.0 : f32 460 // CHECK: omp.reduction %{{.+}}, %{{.+}} : !llvm.ptr<f32> 461 omp.reduction %1, %0 : !llvm.ptr<f32> 462 // CHECK: omp.yield 463 omp.yield 464 } 465 // CHECK: omp.terminator 466 omp.terminator 467 } 468 return 469} 470 471// CHECK-LABEL: func @sections_reduction 472func.func @sections_reduction() { 473 %c1 = arith.constant 1 : i32 474 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32> 475 // CHECK: omp.sections reduction(@add_f32 -> {{.+}} : !llvm.ptr<f32>) 476 omp.sections reduction(@add_f32 -> %0 : !llvm.ptr<f32>) { 477 // CHECK: omp.section 478 omp.section { 479 %1 = arith.constant 2.0 : f32 480 // CHECK: omp.reduction %{{.+}}, %{{.+}} 481 omp.reduction %1, %0 : !llvm.ptr<f32> 482 omp.terminator 483 } 484 // CHECK: omp.section 485 omp.section { 486 %1 = arith.constant 3.0 : f32 487 // CHECK: omp.reduction %{{.+}}, %{{.+}} 488 omp.reduction %1, %0 : !llvm.ptr<f32> 489 omp.terminator 490 } 491 omp.terminator 492 } 493 return 494} 495 496// CHECK: omp.reduction.declare 497// CHECK-LABEL: @add2_f32 498omp.reduction.declare @add2_f32 : f32 499// CHECK: init 500init { 501^bb0(%arg: f32): 502 %0 = arith.constant 0.0 : f32 503 omp.yield (%0 : f32) 504} 505// CHECK: combiner 506combiner { 507^bb1(%arg0: f32, %arg1: f32): 508 %1 = arith.addf %arg0, %arg1 : f32 509 omp.yield (%1 : f32) 510} 511// CHECK-NOT: atomic 512 513// CHECK-LABEL: func @wsloop_reduction2 514func.func @wsloop_reduction2(%lb : index, %ub : index, %step : index) { 515 %0 = memref.alloca() : memref<1xf32> 516 // CHECK: omp.wsloop reduction(@add2_f32 -> %{{.+}} : memref<1xf32>) 517 omp.wsloop reduction(@add2_f32 -> %0 : memref<1xf32>) 518 for (%iv) : index = (%lb) to (%ub) step (%step) { 519 %1 = arith.constant 2.0 : f32 520 // CHECK: omp.reduction 521 omp.reduction %1, %0 : memref<1xf32> 522 omp.yield 523 } 524 return 525} 526 527// CHECK-LABEL: func @parallel_reduction2 528func.func @parallel_reduction2() { 529 %0 = memref.alloca() : memref<1xf32> 530 // CHECK: omp.parallel reduction(@add2_f32 -> %{{.+}} : memref<1xf32>) 531 omp.parallel reduction(@add2_f32 -> %0 : memref<1xf32>) { 532 %1 = arith.constant 2.0 : f32 533 // CHECK: omp.reduction 534 omp.reduction %1, %0 : memref<1xf32> 535 omp.terminator 536 } 537 return 538} 539 540// CHECK: func @parallel_wsloop_reduction2 541func.func @parallel_wsloop_reduction2(%lb : index, %ub : index, %step : index) { 542 %c1 = arith.constant 1 : i32 543 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32> 544 // CHECK: omp.parallel reduction(@add2_f32 -> %{{.+}} : !llvm.ptr<f32>) { 545 omp.parallel reduction(@add2_f32 -> %0 : !llvm.ptr<f32>) { 546 // CHECK: omp.wsloop for (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}}) 547 omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { 548 %1 = arith.constant 2.0 : f32 549 // CHECK: omp.reduction %{{.+}}, %{{.+}} : !llvm.ptr<f32> 550 omp.reduction %1, %0 : !llvm.ptr<f32> 551 // CHECK: omp.yield 552 omp.yield 553 } 554 // CHECK: omp.terminator 555 omp.terminator 556 } 557 return 558} 559 560// CHECK-LABEL: func @sections_reduction2 561func.func @sections_reduction2() { 562 %0 = memref.alloca() : memref<1xf32> 563 // CHECK: omp.sections reduction(@add2_f32 -> %{{.+}} : memref<1xf32>) 564 omp.sections reduction(@add2_f32 -> %0 : memref<1xf32>) { 565 omp.section { 566 %1 = arith.constant 2.0 : f32 567 // CHECK: omp.reduction 568 omp.reduction %1, %0 : memref<1xf32> 569 omp.terminator 570 } 571 omp.section { 572 %1 = arith.constant 2.0 : f32 573 // CHECK: omp.reduction 574 omp.reduction %1, %0 : memref<1xf32> 575 omp.terminator 576 } 577 omp.terminator 578 } 579 return 580} 581 582// CHECK: omp.critical.declare @mutex1 hint(uncontended) 583omp.critical.declare @mutex1 hint(uncontended) 584// CHECK: omp.critical.declare @mutex2 hint(contended) 585omp.critical.declare @mutex2 hint(contended) 586// CHECK: omp.critical.declare @mutex3 hint(nonspeculative) 587omp.critical.declare @mutex3 hint(nonspeculative) 588// CHECK: omp.critical.declare @mutex4 hint(speculative) 589omp.critical.declare @mutex4 hint(speculative) 590// CHECK: omp.critical.declare @mutex5 hint(uncontended, nonspeculative) 591omp.critical.declare @mutex5 hint(uncontended, nonspeculative) 592// CHECK: omp.critical.declare @mutex6 hint(contended, nonspeculative) 593omp.critical.declare @mutex6 hint(contended, nonspeculative) 594// CHECK: omp.critical.declare @mutex7 hint(uncontended, speculative) 595omp.critical.declare @mutex7 hint(uncontended, speculative) 596// CHECK: omp.critical.declare @mutex8 hint(contended, speculative) 597omp.critical.declare @mutex8 hint(contended, speculative) 598// CHECK: omp.critical.declare @mutex9 hint(none) 599omp.critical.declare @mutex9 hint(none) 600// CHECK: omp.critical.declare @mutex10 601omp.critical.declare @mutex10 602 603 604// CHECK-LABEL: omp_critical 605func.func @omp_critical() -> () { 606 // CHECK: omp.critical 607 omp.critical { 608 omp.terminator 609 } 610 611 // CHECK: omp.critical(@{{.*}}) 612 omp.critical(@mutex1) { 613 omp.terminator 614 } 615 return 616} 617 618func.func @omp_ordered(%arg1 : i32, %arg2 : i32, %arg3 : i32, 619 %vec0 : i64, %vec1 : i64, %vec2 : i64, %vec3 : i64) -> () { 620 // CHECK: omp.ordered_region 621 omp.ordered_region { 622 // CHECK: omp.terminator 623 omp.terminator 624 } 625 626 omp.wsloop ordered(0) 627 for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) { 628 omp.ordered_region { 629 omp.terminator 630 } 631 omp.yield 632 } 633 634 omp.wsloop ordered(1) 635 for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) { 636 // Only one DEPEND(SINK: vec) clause 637 // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}} : i64) {num_loops_val = 1 : i64} 638 omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {num_loops_val = 1 : i64} 639 640 // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}} : i64) {num_loops_val = 1 : i64} 641 omp.ordered depend_type(dependsource) depend_vec(%vec0 : i64) {num_loops_val = 1 : i64} 642 643 omp.yield 644 } 645 646 omp.wsloop ordered(2) 647 for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) { 648 // Multiple DEPEND(SINK: vec) clauses 649 // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : i64, i64, i64, i64) {num_loops_val = 2 : i64} 650 omp.ordered depend_type(dependsink) depend_vec(%vec0, %vec1, %vec2, %vec3 : i64, i64, i64, i64) {num_loops_val = 2 : i64} 651 652 // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}}, %{{.*}} : i64, i64) {num_loops_val = 2 : i64} 653 omp.ordered depend_type(dependsource) depend_vec(%vec0, %vec1 : i64, i64) {num_loops_val = 2 : i64} 654 655 omp.yield 656 } 657 658 return 659} 660 661// CHECK-LABEL: omp_atomic_read 662// CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>) 663func.func @omp_atomic_read(%v: memref<i32>, %x: memref<i32>) { 664 // CHECK: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 665 omp.atomic.read %v = %x : memref<i32> 666 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32> 667 omp.atomic.read %v = %x memory_order(seq_cst) : memref<i32> 668 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(acquire) : memref<i32> 669 omp.atomic.read %v = %x memory_order(acquire) : memref<i32> 670 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(relaxed) : memref<i32> 671 omp.atomic.read %v = %x memory_order(relaxed) : memref<i32> 672 // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, nonspeculative) : memref<i32> 673 omp.atomic.read %v = %x hint(nonspeculative, contended) : memref<i32> 674 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(contended, speculative) : memref<i32> 675 omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref<i32> 676 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(none) : memref<i32> 677 omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref<i32> 678 return 679} 680 681// CHECK-LABEL: omp_atomic_write 682// CHECK-SAME: (%[[ADDR:.*]]: memref<i32>, %[[VAL:.*]]: i32) 683func.func @omp_atomic_write(%addr : memref<i32>, %val : i32) { 684 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] : memref<i32>, i32 685 omp.atomic.write %addr = %val : memref<i32>, i32 686 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(seq_cst) : memref<i32>, i32 687 omp.atomic.write %addr = %val memory_order(seq_cst) : memref<i32>, i32 688 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(release) : memref<i32>, i32 689 omp.atomic.write %addr = %val memory_order(release) : memref<i32>, i32 690 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(relaxed) : memref<i32>, i32 691 omp.atomic.write %addr = %val memory_order(relaxed) : memref<i32>, i32 692 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : memref<i32>, i32 693 omp.atomic.write %addr = %val hint(speculative, uncontended) : memref<i32>, i32 694 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(none) : memref<i32>, i32 695 omp.atomic.write %addr = %val hint(none) : memref<i32>, i32 696 return 697} 698 699// CHECK-LABEL: omp_atomic_update 700// CHECK-SAME: (%[[X:.*]]: memref<i32>, %[[EXPR:.*]]: i32, %[[XBOOL:.*]]: memref<i1>, %[[EXPRBOOL:.*]]: i1) 701func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exprBool : i1) { 702 // CHECK: omp.atomic.update %[[X]] : memref<i32> 703 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 704 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 705 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 706 omp.atomic.update %x : memref<i32> { 707 ^bb0(%xval: i32): 708 %newval = llvm.add %xval, %expr : i32 709 omp.yield(%newval : i32) 710 } 711 // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1> 712 // CHECK-NEXT: (%[[XVAL:.*]]: i1): 713 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.and %[[XVAL]], %[[EXPRBOOL]] : i1 714 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1) 715 omp.atomic.update %xBool : memref<i1> { 716 ^bb0(%xval: i1): 717 %newval = llvm.and %xval, %exprBool : i1 718 omp.yield(%newval : i1) 719 } 720 // CHECK: omp.atomic.update %[[X]] : memref<i32> 721 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 722 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.shl %[[XVAL]], %[[EXPR]] : i32 723 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 724 // CHECK-NEXT: } 725 omp.atomic.update %x : memref<i32> { 726 ^bb0(%xval: i32): 727 %newval = llvm.shl %xval, %expr : i32 728 omp.yield(%newval : i32) 729 } 730 // CHECK: omp.atomic.update %[[X]] : memref<i32> 731 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 732 // CHECK-NEXT: %[[NEWVAL:.*]] = "llvm.intr.smax"(%[[XVAL]], %[[EXPR]]) : (i32, i32) -> i32 733 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 734 // CHECK-NEXT: } 735 omp.atomic.update %x : memref<i32> { 736 ^bb0(%xval: i32): 737 %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32 738 omp.yield(%newval : i32) 739 } 740 741 // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1> 742 // CHECK-NEXT: (%[[XVAL:.*]]: i1): 743 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : i1 744 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1) 745 // } 746 omp.atomic.update %xBool : memref<i1> { 747 ^bb0(%xval: i1): 748 %newval = llvm.icmp "eq" %xval, %exprBool : i1 749 omp.yield(%newval : i1) 750 } 751 752 // CHECK: omp.atomic.update hint(none) %[[X]] : memref<i32> 753 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 754 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 755 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 756 omp.atomic.update hint(none) %x : memref<i32> { 757 ^bb0(%xval: i32): 758 %newval = llvm.add %xval, %expr : i32 759 omp.yield(%newval : i32) 760 } 761 762 // CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref<i32> 763 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 764 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 765 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 766 omp.atomic.update hint(uncontended) %x : memref<i32> { 767 ^bb0(%xval: i32): 768 %newval = llvm.add %xval, %expr : i32 769 omp.yield(%newval : i32) 770 } 771 772 // CHECK: omp.atomic.update hint(contended) %[[X]] : memref<i32> 773 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 774 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 775 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 776 omp.atomic.update hint(contended) %x : memref<i32> { 777 ^bb0(%xval: i32): 778 %newval = llvm.add %xval, %expr : i32 779 omp.yield(%newval : i32) 780 } 781 782 // CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref<i32> 783 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 784 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 785 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 786 omp.atomic.update hint(nonspeculative) %x : memref<i32> { 787 ^bb0(%xval: i32): 788 %newval = llvm.add %xval, %expr : i32 789 omp.yield(%newval : i32) 790 } 791 792 // CHECK: omp.atomic.update hint(speculative) %[[X]] : memref<i32> 793 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 794 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 795 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 796 omp.atomic.update hint(speculative) %x : memref<i32> { 797 ^bb0(%xval: i32): 798 %newval = llvm.add %xval, %expr : i32 799 omp.yield(%newval : i32) 800 } 801 802 // CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : memref<i32> 803 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 804 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 805 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 806 omp.atomic.update hint(uncontended, nonspeculative) %x : memref<i32> { 807 ^bb0(%xval: i32): 808 %newval = llvm.add %xval, %expr : i32 809 omp.yield(%newval : i32) 810 } 811 812 // CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : memref<i32> 813 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 814 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 815 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 816 omp.atomic.update hint(contended, nonspeculative) %x : memref<i32> { 817 ^bb0(%xval: i32): 818 %newval = llvm.add %xval, %expr : i32 819 omp.yield(%newval : i32) 820 } 821 822 // CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : memref<i32> 823 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 824 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 825 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 826 omp.atomic.update hint(uncontended, speculative) %x : memref<i32> { 827 ^bb0(%xval: i32): 828 %newval = llvm.add %xval, %expr : i32 829 omp.yield(%newval : i32) 830 } 831 832 // CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref<i32> 833 // CHECK-NEXT: (%[[XVAL:.*]]: i32): 834 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32 835 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32) 836 omp.atomic.update hint(contended, speculative) %x : memref<i32> { 837 ^bb0(%xval: i32): 838 %newval = llvm.add %xval, %expr : i32 839 omp.yield(%newval : i32) 840 } 841 842 return 843} 844 845// CHECK-LABEL: omp_atomic_capture 846// CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>, %[[expr:.*]]: i32) 847func.func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) { 848 // CHECK: omp.atomic.capture { 849 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 850 // CHECK-NEXT: (%[[xval:.*]]: i32): 851 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 852 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 853 // CHECK-NEXT: } 854 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 855 // CHECK-NEXT: } 856 omp.atomic.capture{ 857 omp.atomic.update %x : memref<i32> { 858 ^bb0(%xval: i32): 859 %newval = llvm.add %xval, %expr : i32 860 omp.yield(%newval : i32) 861 } 862 omp.atomic.read %v = %x : memref<i32> 863 } 864 // CHECK: omp.atomic.capture { 865 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 866 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 867 // CHECK-NEXT: (%[[xval:.*]]: i32): 868 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 869 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 870 // CHECK-NEXT: } 871 // CHECK-NEXT: } 872 omp.atomic.capture{ 873 omp.atomic.read %v = %x : memref<i32> 874 omp.atomic.update %x : memref<i32> { 875 ^bb0(%xval: i32): 876 %newval = llvm.add %xval, %expr : i32 877 omp.yield(%newval : i32) 878 } 879 } 880 // CHECK: omp.atomic.capture { 881 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 882 // CHECK-NEXT: omp.atomic.write %[[x]] = %[[expr]] : memref<i32>, i32 883 // CHECK-NEXT: } 884 omp.atomic.capture{ 885 omp.atomic.read %v = %x : memref<i32> 886 omp.atomic.write %x = %expr : memref<i32>, i32 887 } 888 889 // CHECK: omp.atomic.capture hint(none) { 890 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 891 // CHECK-NEXT: (%[[xval:.*]]: i32): 892 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 893 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 894 // CHECK-NEXT: } 895 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 896 // CHECK-NEXT: } 897 omp.atomic.capture hint(none) { 898 omp.atomic.update %x : memref<i32> { 899 ^bb0(%xval: i32): 900 %newval = llvm.add %xval, %expr : i32 901 omp.yield(%newval : i32) 902 } 903 omp.atomic.read %v = %x : memref<i32> 904 } 905 906 // CHECK: omp.atomic.capture hint(uncontended) { 907 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 908 // CHECK-NEXT: (%[[xval:.*]]: i32): 909 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 910 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 911 // CHECK-NEXT: } 912 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 913 // CHECK-NEXT: } 914 omp.atomic.capture hint(uncontended) { 915 omp.atomic.update %x : memref<i32> { 916 ^bb0(%xval: i32): 917 %newval = llvm.add %xval, %expr : i32 918 omp.yield(%newval : i32) 919 } 920 omp.atomic.read %v = %x : memref<i32> 921 } 922 923 // CHECK: omp.atomic.capture hint(contended) { 924 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 925 // CHECK-NEXT: (%[[xval:.*]]: i32): 926 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 927 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 928 // CHECK-NEXT: } 929 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 930 // CHECK-NEXT: } 931 omp.atomic.capture hint(contended) { 932 omp.atomic.update %x : memref<i32> { 933 ^bb0(%xval: i32): 934 %newval = llvm.add %xval, %expr : i32 935 omp.yield(%newval : i32) 936 } 937 omp.atomic.read %v = %x : memref<i32> 938 } 939 940 // CHECK: omp.atomic.capture hint(nonspeculative) { 941 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 942 // CHECK-NEXT: (%[[xval:.*]]: i32): 943 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 944 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 945 // CHECK-NEXT: } 946 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 947 // CHECK-NEXT: } 948 omp.atomic.capture hint(nonspeculative) { 949 omp.atomic.update %x : memref<i32> { 950 ^bb0(%xval: i32): 951 %newval = llvm.add %xval, %expr : i32 952 omp.yield(%newval : i32) 953 } 954 omp.atomic.read %v = %x : memref<i32> 955 } 956 957 // CHECK: omp.atomic.capture hint(speculative) { 958 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 959 // CHECK-NEXT: (%[[xval:.*]]: i32): 960 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 961 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 962 // CHECK-NEXT: } 963 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 964 // CHECK-NEXT: } 965 omp.atomic.capture hint(speculative) { 966 omp.atomic.update %x : memref<i32> { 967 ^bb0(%xval: i32): 968 %newval = llvm.add %xval, %expr : i32 969 omp.yield(%newval : i32) 970 } 971 omp.atomic.read %v = %x : memref<i32> 972 } 973 974 // CHECK: omp.atomic.capture hint(uncontended, nonspeculative) { 975 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 976 // CHECK-NEXT: (%[[xval:.*]]: i32): 977 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 978 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 979 // CHECK-NEXT: } 980 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 981 // CHECK-NEXT: } 982 omp.atomic.capture hint(uncontended, nonspeculative) { 983 omp.atomic.update %x : memref<i32> { 984 ^bb0(%xval: i32): 985 %newval = llvm.add %xval, %expr : i32 986 omp.yield(%newval : i32) 987 } 988 omp.atomic.read %v = %x : memref<i32> 989 } 990 991 // CHECK: omp.atomic.capture hint(contended, nonspeculative) { 992 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 993 // CHECK-NEXT: (%[[xval:.*]]: i32): 994 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 995 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 996 // CHECK-NEXT: } 997 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 998 // CHECK-NEXT: } 999 omp.atomic.capture hint(contended, nonspeculative) { 1000 omp.atomic.update %x : memref<i32> { 1001 ^bb0(%xval: i32): 1002 %newval = llvm.add %xval, %expr : i32 1003 omp.yield(%newval : i32) 1004 } 1005 omp.atomic.read %v = %x : memref<i32> 1006 } 1007 1008 // CHECK: omp.atomic.capture hint(uncontended, speculative) { 1009 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 1010 // CHECK-NEXT: (%[[xval:.*]]: i32): 1011 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 1012 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 1013 // CHECK-NEXT: } 1014 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 1015 // CHECK-NEXT: } 1016 omp.atomic.capture hint(uncontended, speculative) { 1017 omp.atomic.update %x : memref<i32> { 1018 ^bb0(%xval: i32): 1019 %newval = llvm.add %xval, %expr : i32 1020 omp.yield(%newval : i32) 1021 } 1022 omp.atomic.read %v = %x : memref<i32> 1023 } 1024 1025 // CHECK: omp.atomic.capture hint(contended, speculative) { 1026 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32> 1027 // CHECK-NEXT: (%[[xval:.*]]: i32): 1028 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32 1029 // CHECK-NEXT: omp.yield(%[[newval]] : i32) 1030 // CHECK-NEXT: } 1031 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32> 1032 // CHECK-NEXT: } 1033 omp.atomic.capture hint(contended, speculative) { 1034 omp.atomic.update %x : memref<i32> { 1035 ^bb0(%xval: i32): 1036 %newval = llvm.add %xval, %expr : i32 1037 omp.yield(%newval : i32) 1038 } 1039 omp.atomic.read %v = %x : memref<i32> 1040 } 1041 return 1042} 1043 1044// CHECK-LABEL: omp_sectionsop 1045func.func @omp_sectionsop(%data_var1 : memref<i32>, %data_var2 : memref<i32>, 1046 %data_var3 : memref<i32>, %redn_var : !llvm.ptr<f32>) { 1047 // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 1048 "omp.sections" (%data_var1, %data_var1) ({ 1049 // CHECK: omp.terminator 1050 omp.terminator 1051 }) {operand_segment_sizes = dense<[0,1,1]> : vector<3xi32>} : (memref<i32>, memref<i32>) -> () 1052 1053 // CHECK: omp.sections reduction(@add_f32 -> %{{.*}} : !llvm.ptr<f32>) 1054 "omp.sections" (%redn_var) ({ 1055 // CHECK: omp.terminator 1056 omp.terminator 1057 }) {operand_segment_sizes = dense<[1,0,0]> : vector<3xi32>, reductions=[@add_f32]} : (!llvm.ptr<f32>) -> () 1058 1059 // CHECK: omp.sections nowait { 1060 omp.sections nowait { 1061 // CHECK: omp.terminator 1062 omp.terminator 1063 } 1064 1065 // CHECK: omp.sections reduction(@add_f32 -> %{{.*}} : !llvm.ptr<f32>) { 1066 omp.sections reduction(@add_f32 -> %redn_var : !llvm.ptr<f32>) { 1067 // CHECK: omp.terminator 1068 omp.terminator 1069 } 1070 1071 // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) 1072 omp.sections allocate(%data_var1 : memref<i32> -> %data_var1 : memref<i32>) { 1073 // CHECK: omp.terminator 1074 omp.terminator 1075 } 1076 1077 // CHECK: omp.sections nowait 1078 omp.sections nowait { 1079 // CHECK: omp.section 1080 omp.section { 1081 // CHECK: %{{.*}} = "test.payload"() : () -> i32 1082 %1 = "test.payload"() : () -> i32 1083 // CHECK: %{{.*}} = "test.payload"() : () -> i32 1084 %2 = "test.payload"() : () -> i32 1085 // CHECK: %{{.*}} = "test.payload"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32 1086 %3 = "test.payload"(%1, %2) : (i32, i32) -> i32 1087 } 1088 // CHECK: omp.section 1089 omp.section { 1090 // CHECK: %{{.*}} = "test.payload"(%{{.*}}) : (!llvm.ptr<f32>) -> i32 1091 %1 = "test.payload"(%redn_var) : (!llvm.ptr<f32>) -> i32 1092 } 1093 // CHECK: omp.section 1094 omp.section { 1095 // CHECK: "test.payload"(%{{.*}}) : (!llvm.ptr<f32>) -> () 1096 "test.payload"(%redn_var) : (!llvm.ptr<f32>) -> () 1097 } 1098 // CHECK: omp.terminator 1099 omp.terminator 1100 } 1101 return 1102} 1103 1104// CHECK-LABEL: func @omp_single 1105func.func @omp_single() { 1106 omp.parallel { 1107 // CHECK: omp.single { 1108 omp.single { 1109 "test.payload"() : () -> () 1110 // CHECK: omp.terminator 1111 omp.terminator 1112 } 1113 // CHECK: omp.terminator 1114 omp.terminator 1115 } 1116 return 1117} 1118 1119// CHECK-LABEL: func @omp_single_nowait 1120func.func @omp_single_nowait() { 1121 omp.parallel { 1122 // CHECK: omp.single nowait { 1123 omp.single nowait { 1124 "test.payload"() : () -> () 1125 // CHECK: omp.terminator 1126 omp.terminator 1127 } 1128 // CHECK: omp.terminator 1129 omp.terminator 1130 } 1131 return 1132} 1133 1134// CHECK-LABEL: func @omp_single_allocate 1135func.func @omp_single_allocate(%data_var: memref<i32>) { 1136 omp.parallel { 1137 // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) { 1138 omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) { 1139 "test.payload"() : () -> () 1140 // CHECK: omp.terminator 1141 omp.terminator 1142 } 1143 // CHECK: omp.terminator 1144 omp.terminator 1145 } 1146 return 1147} 1148 1149// CHECK-LABEL: func @omp_single_allocate_nowait 1150func.func @omp_single_allocate_nowait(%data_var: memref<i32>) { 1151 omp.parallel { 1152 // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) nowait { 1153 omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) nowait { 1154 "test.payload"() : () -> () 1155 // CHECK: omp.terminator 1156 omp.terminator 1157 } 1158 // CHECK: omp.terminator 1159 omp.terminator 1160 } 1161 return 1162} 1163 1164// CHECK-LABEL: @omp_task 1165// CHECK-SAME: (%[[bool_var:.*]]: i1, %[[i64_var:.*]]: i64, %[[i32_var:.*]]: i32, %[[data_var:.*]]: memref<i32>) 1166func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memref<i32>) { 1167 1168 // Checking simple task 1169 // CHECK: omp.task { 1170 omp.task { 1171 // CHECK: "test.foo"() : () -> () 1172 "test.foo"() : () -> () 1173 // CHECK: omp.terminator 1174 omp.terminator 1175 } 1176 1177 // Checking `if` clause 1178 // CHECK: omp.task if(%[[bool_var]]) { 1179 omp.task if(%bool_var) { 1180 // CHECK: "test.foo"() : () -> () 1181 "test.foo"() : () -> () 1182 // CHECK: omp.terminator 1183 omp.terminator 1184 } 1185 1186 // Checking `final` clause 1187 // CHECK: omp.task final(%[[bool_var]]) { 1188 omp.task final(%bool_var) { 1189 // CHECK: "test.foo"() : () -> () 1190 "test.foo"() : () -> () 1191 // CHECK: omp.terminator 1192 omp.terminator 1193 } 1194 1195 // Checking `untied` clause 1196 // CHECK: omp.task untied { 1197 omp.task untied { 1198 // CHECK: "test.foo"() : () -> () 1199 "test.foo"() : () -> () 1200 // CHECK: omp.terminator 1201 omp.terminator 1202 } 1203 1204 // Checking `in_reduction` clause 1205 %c1 = arith.constant 1 : i32 1206 // CHECK: %[[redn_var1:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr<f32> 1207 %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr<f32> 1208 // CHECK: %[[redn_var2:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr<f32> 1209 %1 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr<f32> 1210 // CHECK: omp.task in_reduction(@add_f32 -> %[[redn_var1]] : !llvm.ptr<f32>, @add_f32 -> %[[redn_var2]] : !llvm.ptr<f32>) { 1211 omp.task in_reduction(@add_f32 -> %0 : !llvm.ptr<f32>, @add_f32 -> %1 : !llvm.ptr<f32>) { 1212 // CHECK: "test.foo"() : () -> () 1213 "test.foo"() : () -> () 1214 // CHECK: omp.terminator 1215 omp.terminator 1216 } 1217 1218 // Checking priority clause 1219 // CHECK: omp.task priority(%[[i32_var]]) { 1220 omp.task priority(%i32_var) { 1221 // CHECK: "test.foo"() : () -> () 1222 "test.foo"() : () -> () 1223 // CHECK: omp.terminator 1224 omp.terminator 1225 } 1226 1227 // Checking allocate clause 1228 // CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>) { 1229 omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>) { 1230 // CHECK: "test.foo"() : () -> () 1231 "test.foo"() : () -> () 1232 // CHECK: omp.terminator 1233 omp.terminator 1234 } 1235 1236 // Checking multiple clauses 1237 // CHECK: omp.task if(%[[bool_var]]) final(%[[bool_var]]) untied 1238 omp.task if(%bool_var) final(%bool_var) untied 1239 // CHECK-SAME: in_reduction(@add_f32 -> %[[redn_var1]] : !llvm.ptr<f32>, @add_f32 -> %[[redn_var2]] : !llvm.ptr<f32>) 1240 in_reduction(@add_f32 -> %0 : !llvm.ptr<f32>, @add_f32 -> %1 : !llvm.ptr<f32>) 1241 // CHECK-SAME: priority(%[[i32_var]]) 1242 priority(%i32_var) 1243 // CHECK-SAME: allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>) 1244 allocate(%data_var : memref<i32> -> %data_var : memref<i32>) { 1245 // CHECK: "test.foo"() : () -> () 1246 "test.foo"() : () -> () 1247 // CHECK: omp.terminator 1248 omp.terminator 1249 } 1250 1251 return 1252} 1253 1254// ----- 1255 1256func.func @omp_threadprivate() { 1257 %0 = arith.constant 1 : i32 1258 %1 = arith.constant 2 : i32 1259 %2 = arith.constant 3 : i32 1260 1261 // CHECK: [[ARG0:%.*]] = llvm.mlir.addressof @_QFsubEx : !llvm.ptr<i32> 1262 // CHECK: {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr<i32> -> !llvm.ptr<i32> 1263 %3 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr<i32> 1264 %4 = omp.threadprivate %3 : !llvm.ptr<i32> -> !llvm.ptr<i32> 1265 llvm.store %0, %4 : !llvm.ptr<i32> 1266 1267 // CHECK: omp.parallel 1268 // CHECK: {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr<i32> -> !llvm.ptr<i32> 1269 omp.parallel { 1270 %5 = omp.threadprivate %3 : !llvm.ptr<i32> -> !llvm.ptr<i32> 1271 llvm.store %1, %5 : !llvm.ptr<i32> 1272 omp.terminator 1273 } 1274 llvm.store %2, %4 : !llvm.ptr<i32> 1275 return 1276} 1277 1278llvm.mlir.global internal @_QFsubEx() : i32 1279 1280func.func @omp_cancel_parallel(%if_cond : i1) -> () { 1281 // Test with optional operand; if_expr. 1282 omp.parallel { 1283 // CHECK: omp.cancel cancellation_construct_type(parallel) if(%{{.*}}) 1284 omp.cancel cancellation_construct_type(parallel) if(%if_cond) 1285 // CHECK: omp.terminator 1286 omp.terminator 1287 } 1288 return 1289} 1290 1291func.func @omp_cancel_wsloop(%lb : index, %ub : index, %step : index) { 1292 omp.wsloop 1293 for (%iv) : index = (%lb) to (%ub) step (%step) { 1294 // CHECK: omp.cancel cancellation_construct_type(loop) 1295 omp.cancel cancellation_construct_type(loop) 1296 // CHECK: omp.terminator 1297 omp.terminator 1298 } 1299 return 1300} 1301 1302func.func @omp_cancel_sections() -> () { 1303 omp.sections { 1304 omp.section { 1305 // CHECK: omp.cancel cancellation_construct_type(sections) 1306 omp.cancel cancellation_construct_type(sections) 1307 omp.terminator 1308 } 1309 // CHECK: omp.terminator 1310 omp.terminator 1311 } 1312 return 1313} 1314 1315func.func @omp_cancellationpoint_parallel() -> () { 1316 omp.parallel { 1317 // CHECK: omp.cancellationpoint cancellation_construct_type(parallel) 1318 omp.cancellationpoint cancellation_construct_type(parallel) 1319 // CHECK: omp.cancel cancellation_construct_type(parallel) 1320 omp.cancel cancellation_construct_type(parallel) 1321 omp.terminator 1322 } 1323 return 1324} 1325 1326func.func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) { 1327 omp.wsloop 1328 for (%iv) : index = (%lb) to (%ub) step (%step) { 1329 // CHECK: omp.cancellationpoint cancellation_construct_type(loop) 1330 omp.cancellationpoint cancellation_construct_type(loop) 1331 // CHECK: omp.cancel cancellation_construct_type(loop) 1332 omp.cancel cancellation_construct_type(loop) 1333 // CHECK: omp.terminator 1334 omp.terminator 1335 } 1336 return 1337} 1338 1339func.func @omp_cancellationpoint_sections() -> () { 1340 omp.sections { 1341 omp.section { 1342 // CHECK: omp.cancellationpoint cancellation_construct_type(sections) 1343 omp.cancellationpoint cancellation_construct_type(sections) 1344 // CHECK: omp.cancel cancellation_construct_type(sections) 1345 omp.cancel cancellation_construct_type(sections) 1346 omp.terminator 1347 } 1348 // CHECK: omp.terminator 1349 omp.terminator 1350 } 1351 return 1352} 1353