1// RUN: mlir-opt -convert-scf-to-openmp -split-input-file %s | FileCheck %s 2 3// CHECK: omp.reduction.declare @[[$REDF:.*]] : f32 4 5// CHECK: init 6// CHECK: %[[INIT:.*]] = llvm.mlir.constant(0.000000e+00 : f32) 7// CHECK: omp.yield(%[[INIT]] : f32) 8 9// CHECK: combiner 10// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32) 11// CHECK: %[[RES:.*]] = arith.addf %[[ARG0]], %[[ARG1]] 12// CHECK: omp.yield(%[[RES]] : f32) 13 14// CHECK: atomic 15// CHECK: ^{{.*}}(%[[ARG0:.*]]: !llvm.ptr<f32>, %[[ARG1:.*]]: !llvm.ptr<f32>): 16// CHECK: %[[RHS:.*]] = llvm.load %[[ARG1]] 17// CHECK: llvm.atomicrmw fadd %[[ARG0]], %[[RHS]] monotonic 18 19// CHECK-LABEL: @reduction1 20func.func @reduction1(%arg0 : index, %arg1 : index, %arg2 : index, 21 %arg3 : index, %arg4 : index) { 22 // CHECK: %[[CST:.*]] = arith.constant 0.0 23 // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 24 // CHECK: %[[BUF:.*]] = llvm.alloca %[[ONE]] x f32 25 // CHECK: llvm.store %[[CST]], %[[BUF]] 26 %step = arith.constant 1 : index 27 %zero = arith.constant 0.0 : f32 28 // CHECK: omp.parallel 29 // CHECK: omp.wsloop 30 // CHECK-SAME: reduction(@[[$REDF]] -> %[[BUF]] 31 // CHECK: memref.alloca_scope 32 scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) 33 step (%arg4, %step) init (%zero) -> (f32) { 34 // CHECK: %[[CST_INNER:.*]] = arith.constant 1.0 35 %one = arith.constant 1.0 : f32 36 // CHECK: omp.reduction %[[CST_INNER]], %[[BUF]] 37 scf.reduce(%one) : f32 { 38 ^bb0(%lhs : f32, %rhs: f32): 39 %res = arith.addf %lhs, %rhs : f32 40 scf.reduce.return %res : f32 41 } 42 // CHECK: omp.yield 43 } 44 // CHECK: omp.terminator 45 // CHECK: llvm.load %[[BUF]] 46 return 47} 48 49// ----- 50 51// Only check the declaration here, the rest is same as above. 52// CHECK: omp.reduction.declare @{{.*}} : f32 53 54// CHECK: init 55// CHECK: %[[INIT:.*]] = llvm.mlir.constant(1.000000e+00 : f32) 56// CHECK: omp.yield(%[[INIT]] : f32) 57 58// CHECK: combiner 59// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32) 60// CHECK: %[[RES:.*]] = arith.mulf %[[ARG0]], %[[ARG1]] 61// CHECK: omp.yield(%[[RES]] : f32) 62 63// CHECK-NOT: atomic 64 65// CHECK-LABEL: @reduction2 66func.func @reduction2(%arg0 : index, %arg1 : index, %arg2 : index, 67 %arg3 : index, %arg4 : index) { 68 %step = arith.constant 1 : index 69 %zero = arith.constant 0.0 : f32 70 scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) 71 step (%arg4, %step) init (%zero) -> (f32) { 72 %one = arith.constant 1.0 : f32 73 scf.reduce(%one) : f32 { 74 ^bb0(%lhs : f32, %rhs: f32): 75 %res = arith.mulf %lhs, %rhs : f32 76 scf.reduce.return %res : f32 77 } 78 } 79 return 80} 81 82// ----- 83 84// Only check the declaration here, the rest is same as above. 85// CHECK: omp.reduction.declare @{{.*}} : f32 86 87// CHECK: init 88// CHECK: %[[INIT:.*]] = llvm.mlir.constant(-3.4 89// CHECK: omp.yield(%[[INIT]] : f32) 90 91// CHECK: combiner 92// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32) 93// CHECK: %[[CMP:.*]] = arith.cmpf oge, %[[ARG0]], %[[ARG1]] 94// CHECK: %[[RES:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]] 95// CHECK: omp.yield(%[[RES]] : f32) 96 97// CHECK-NOT: atomic 98 99// CHECK-LABEL: @reduction3 100func.func @reduction3(%arg0 : index, %arg1 : index, %arg2 : index, 101 %arg3 : index, %arg4 : index) { 102 %step = arith.constant 1 : index 103 %zero = arith.constant 0.0 : f32 104 scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) 105 step (%arg4, %step) init (%zero) -> (f32) { 106 %one = arith.constant 1.0 : f32 107 scf.reduce(%one) : f32 { 108 ^bb0(%lhs : f32, %rhs: f32): 109 %cmp = arith.cmpf oge, %lhs, %rhs : f32 110 %res = arith.select %cmp, %lhs, %rhs : f32 111 scf.reduce.return %res : f32 112 } 113 } 114 return 115} 116 117// ----- 118 119// CHECK: omp.reduction.declare @[[$REDF1:.*]] : f32 120 121// CHECK: init 122// CHECK: %[[INIT:.*]] = llvm.mlir.constant(-3.4 123// CHECK: omp.yield(%[[INIT]] : f32) 124 125// CHECK: combiner 126// CHECK: ^{{.*}}(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32) 127// CHECK: %[[CMP:.*]] = arith.cmpf oge, %[[ARG0]], %[[ARG1]] 128// CHECK: %[[RES:.*]] = arith.select %[[CMP]], %[[ARG0]], %[[ARG1]] 129// CHECK: omp.yield(%[[RES]] : f32) 130 131// CHECK-NOT: atomic 132 133// CHECK: omp.reduction.declare @[[$REDF2:.*]] : i64 134 135// CHECK: init 136// CHECK: %[[INIT:.*]] = llvm.mlir.constant 137// CHECK: omp.yield(%[[INIT]] : i64) 138 139// CHECK: combiner 140// CHECK: ^{{.*}}(%[[ARG0:.*]]: i64, %[[ARG1:.*]]: i64) 141// CHECK: %[[CMP:.*]] = arith.cmpi slt, %[[ARG0]], %[[ARG1]] 142// CHECK: %[[RES:.*]] = arith.select %[[CMP]], %[[ARG1]], %[[ARG0]] 143// CHECK: omp.yield(%[[RES]] : i64) 144 145// CHECK: atomic 146// CHECK: ^{{.*}}(%[[ARG0:.*]]: !llvm.ptr<i64>, %[[ARG1:.*]]: !llvm.ptr<i64>): 147// CHECK: %[[RHS:.*]] = llvm.load %[[ARG1]] 148// CHECK: llvm.atomicrmw max %[[ARG0]], %[[RHS]] monotonic 149 150// CHECK-LABEL: @reduction4 151func.func @reduction4(%arg0 : index, %arg1 : index, %arg2 : index, 152 %arg3 : index, %arg4 : index) -> (f32, i64) { 153 %step = arith.constant 1 : index 154 // CHECK: %[[ZERO:.*]] = arith.constant 0.0 155 %zero = arith.constant 0.0 : f32 156 // CHECK: %[[IONE:.*]] = arith.constant 1 157 %ione = arith.constant 1 : i64 158 // CHECK: %[[BUF1:.*]] = llvm.alloca %{{.*}} x f32 159 // CHECK: llvm.store %[[ZERO]], %[[BUF1]] 160 // CHECK: %[[BUF2:.*]] = llvm.alloca %{{.*}} x i64 161 // CHECK: llvm.store %[[IONE]], %[[BUF2]] 162 163 // CHECK: omp.parallel 164 // CHECK: omp.wsloop 165 // CHECK-SAME: reduction(@[[$REDF1]] -> %[[BUF1]] 166 // CHECK-SAME: @[[$REDF2]] -> %[[BUF2]] 167 // CHECK: memref.alloca_scope 168 %res:2 = scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) 169 step (%arg4, %step) init (%zero, %ione) -> (f32, i64) { 170 %one = arith.constant 1.0 : f32 171 // CHECK: omp.reduction %{{.*}}, %[[BUF1]] 172 scf.reduce(%one) : f32 { 173 ^bb0(%lhs : f32, %rhs: f32): 174 %cmp = arith.cmpf oge, %lhs, %rhs : f32 175 %res = arith.select %cmp, %lhs, %rhs : f32 176 scf.reduce.return %res : f32 177 } 178 // CHECK: arith.fptosi 179 %1 = arith.fptosi %one : f32 to i64 180 // CHECK: omp.reduction %{{.*}}, %[[BUF2]] 181 scf.reduce(%1) : i64 { 182 ^bb1(%lhs: i64, %rhs: i64): 183 %cmp = arith.cmpi slt, %lhs, %rhs : i64 184 %res = arith.select %cmp, %rhs, %lhs : i64 185 scf.reduce.return %res : i64 186 } 187 // CHECK: omp.yield 188 } 189 // CHECK: omp.terminator 190 // CHECK: %[[RES1:.*]] = llvm.load %[[BUF1]] 191 // CHECK: %[[RES2:.*]] = llvm.load %[[BUF2]] 192 // CHECK: return %[[RES1]], %[[RES2]] 193 return %res#0, %res#1 : f32, i64 194} 195