1// RUN: mlir-opt %s | FileCheck %s 2// Verify the printed output can be parsed. 3// RUN: mlir-opt %s | mlir-opt | FileCheck %s 4// Verify the generic form can be parsed. 5// RUN: mlir-opt -mlir-print-op-generic %s | mlir-opt | FileCheck %s 6 7func @std_for(%arg0 : index, %arg1 : index, %arg2 : index) { 8 scf.for %i0 = %arg0 to %arg1 step %arg2 { 9 scf.for %i1 = %arg0 to %arg1 step %arg2 { 10 %min_cmp = cmpi "slt", %i0, %i1 : index 11 %min = select %min_cmp, %i0, %i1 : index 12 %max_cmp = cmpi "sge", %i0, %i1 : index 13 %max = select %max_cmp, %i0, %i1 : index 14 scf.for %i2 = %min to %max step %i1 { 15 } 16 } 17 } 18 return 19} 20// CHECK-LABEL: func @std_for( 21// CHECK-NEXT: scf.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} { 22// CHECK-NEXT: scf.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} { 23// CHECK-NEXT: %{{.*}} = cmpi "slt", %{{.*}}, %{{.*}} : index 24// CHECK-NEXT: %{{.*}} = select %{{.*}}, %{{.*}}, %{{.*}} : index 25// CHECK-NEXT: %{{.*}} = cmpi "sge", %{{.*}}, %{{.*}} : index 26// CHECK-NEXT: %{{.*}} = select %{{.*}}, %{{.*}}, %{{.*}} : index 27// CHECK-NEXT: scf.for %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} { 28 29func @std_if(%arg0: i1, %arg1: f32) { 30 scf.if %arg0 { 31 %0 = addf %arg1, %arg1 : f32 32 } 33 return 34} 35// CHECK-LABEL: func @std_if( 36// CHECK-NEXT: scf.if %{{.*}} { 37// CHECK-NEXT: %{{.*}} = addf %{{.*}}, %{{.*}} : f32 38 39func @std_if_else(%arg0: i1, %arg1: f32) { 40 scf.if %arg0 { 41 %0 = addf %arg1, %arg1 : f32 42 } else { 43 %1 = addf %arg1, %arg1 : f32 44 } 45 return 46} 47// CHECK-LABEL: func @std_if_else( 48// CHECK-NEXT: scf.if %{{.*}} { 49// CHECK-NEXT: %{{.*}} = addf %{{.*}}, %{{.*}} : f32 50// CHECK-NEXT: } else { 51// CHECK-NEXT: %{{.*}} = addf %{{.*}}, %{{.*}} : f32 52 53func @std_parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index, 54 %arg3 : index, %arg4 : index) { 55 %step = constant 1 : index 56 scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) 57 step (%arg4, %step) { 58 %min_cmp = cmpi "slt", %i0, %i1 : index 59 %min = select %min_cmp, %i0, %i1 : index 60 %max_cmp = cmpi "sge", %i0, %i1 : index 61 %max = select %max_cmp, %i0, %i1 : index 62 %zero = constant 0.0 : f32 63 %int_zero = constant 0 : i32 64 %red:2 = scf.parallel (%i2) = (%min) to (%max) step (%i1) 65 init (%zero, %int_zero) -> (f32, i32) { 66 %one = constant 1.0 : f32 67 scf.reduce(%one) : f32 { 68 ^bb0(%lhs : f32, %rhs: f32): 69 %res = addf %lhs, %rhs : f32 70 scf.reduce.return %res : f32 71 } 72 %int_one = constant 1 : i32 73 scf.reduce(%int_one) : i32 { 74 ^bb0(%lhs : i32, %rhs: i32): 75 %res = muli %lhs, %rhs : i32 76 scf.reduce.return %res : i32 77 } 78 } 79 } 80 return 81} 82// CHECK-LABEL: func @std_parallel_loop( 83// CHECK-SAME: %[[ARG0:[A-Za-z0-9]+]]: 84// CHECK-SAME: %[[ARG1:[A-Za-z0-9]+]]: 85// CHECK-SAME: %[[ARG2:[A-Za-z0-9]+]]: 86// CHECK-SAME: %[[ARG3:[A-Za-z0-9]+]]: 87// CHECK-SAME: %[[ARG4:[A-Za-z0-9]+]]: 88// CHECK: %[[STEP:.*]] = constant 1 : index 89// CHECK-NEXT: scf.parallel (%[[I0:.*]], %[[I1:.*]]) = (%[[ARG0]], %[[ARG1]]) to 90// CHECK: (%[[ARG2]], %[[ARG3]]) step (%[[ARG4]], %[[STEP]]) { 91// CHECK-NEXT: %[[MIN_CMP:.*]] = cmpi "slt", %[[I0]], %[[I1]] : index 92// CHECK-NEXT: %[[MIN:.*]] = select %[[MIN_CMP]], %[[I0]], %[[I1]] : index 93// CHECK-NEXT: %[[MAX_CMP:.*]] = cmpi "sge", %[[I0]], %[[I1]] : index 94// CHECK-NEXT: %[[MAX:.*]] = select %[[MAX_CMP]], %[[I0]], %[[I1]] : index 95// CHECK-NEXT: %[[ZERO:.*]] = constant 0.000000e+00 : f32 96// CHECK-NEXT: %[[INT_ZERO:.*]] = constant 0 : i32 97// CHECK-NEXT: scf.parallel (%{{.*}}) = (%[[MIN]]) to (%[[MAX]]) 98// CHECK-SAME: step (%[[I1]]) 99// CHECK-SAME: init (%[[ZERO]], %[[INT_ZERO]]) -> (f32, i32) { 100// CHECK-NEXT: %[[ONE:.*]] = constant 1.000000e+00 : f32 101// CHECK-NEXT: scf.reduce(%[[ONE]]) : f32 { 102// CHECK-NEXT: ^bb0(%[[LHS:.*]]: f32, %[[RHS:.*]]: f32): 103// CHECK-NEXT: %[[RES:.*]] = addf %[[LHS]], %[[RHS]] : f32 104// CHECK-NEXT: scf.reduce.return %[[RES]] : f32 105// CHECK-NEXT: } 106// CHECK-NEXT: %[[INT_ONE:.*]] = constant 1 : i32 107// CHECK-NEXT: scf.reduce(%[[INT_ONE]]) : i32 { 108// CHECK-NEXT: ^bb0(%[[LHS:.*]]: i32, %[[RHS:.*]]: i32): 109// CHECK-NEXT: %[[RES:.*]] = muli %[[LHS]], %[[RHS]] : i32 110// CHECK-NEXT: scf.reduce.return %[[RES]] : i32 111// CHECK-NEXT: } 112// CHECK-NEXT: scf.yield 113// CHECK-NEXT: } 114// CHECK-NEXT: scf.yield 115 116func @parallel_explicit_yield( 117 %arg0: index, %arg1: index, %arg2: index) { 118 scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) { 119 scf.yield 120 } 121 return 122} 123 124// CHECK-LABEL: func @parallel_explicit_yield( 125// CHECK-SAME: %[[ARG0:[A-Za-z0-9]+]]: 126// CHECK-SAME: %[[ARG1:[A-Za-z0-9]+]]: 127// CHECK-SAME: %[[ARG2:[A-Za-z0-9]+]]: 128// CHECK-NEXT: scf.parallel (%{{.*}}) = (%[[ARG0]]) to (%[[ARG1]]) step (%[[ARG2]]) 129// CHECK-NEXT: scf.yield 130// CHECK-NEXT: } 131// CHECK-NEXT: return 132// CHECK-NEXT: } 133 134func @std_if_yield(%arg0: i1, %arg1: f32) 135{ 136 %x, %y = scf.if %arg0 -> (f32, f32) { 137 %0 = addf %arg1, %arg1 : f32 138 %1 = subf %arg1, %arg1 : f32 139 scf.yield %0, %1 : f32, f32 140 } else { 141 %0 = subf %arg1, %arg1 : f32 142 %1 = addf %arg1, %arg1 : f32 143 scf.yield %0, %1 : f32, f32 144 } 145 return 146} 147// CHECK-LABEL: func @std_if_yield( 148// CHECK-SAME: %[[ARG0:[A-Za-z0-9]+]]: 149// CHECK-SAME: %[[ARG1:[A-Za-z0-9]+]]: 150// CHECK-NEXT: %{{.*}}:2 = scf.if %[[ARG0]] -> (f32, f32) { 151// CHECK-NEXT: %[[T1:.*]] = addf %[[ARG1]], %[[ARG1]] 152// CHECK-NEXT: %[[T2:.*]] = subf %[[ARG1]], %[[ARG1]] 153// CHECK-NEXT: scf.yield %[[T1]], %[[T2]] : f32, f32 154// CHECK-NEXT: } else { 155// CHECK-NEXT: %[[T3:.*]] = subf %[[ARG1]], %[[ARG1]] 156// CHECK-NEXT: %[[T4:.*]] = addf %[[ARG1]], %[[ARG1]] 157// CHECK-NEXT: scf.yield %[[T3]], %[[T4]] : f32, f32 158// CHECK-NEXT: } 159 160func @std_for_yield(%arg0 : index, %arg1 : index, %arg2 : index) { 161 %s0 = constant 0.0 : f32 162 %result = scf.for %i0 = %arg0 to %arg1 step %arg2 iter_args(%si = %s0) -> (f32) { 163 %sn = addf %si, %si : f32 164 scf.yield %sn : f32 165 } 166 return 167} 168// CHECK-LABEL: func @std_for_yield( 169// CHECK-SAME: %[[ARG0:[A-Za-z0-9]+]]: 170// CHECK-SAME: %[[ARG1:[A-Za-z0-9]+]]: 171// CHECK-SAME: %[[ARG2:[A-Za-z0-9]+]]: 172// CHECK-NEXT: %[[INIT:.*]] = constant 173// CHECK-NEXT: %{{.*}} = scf.for %{{.*}} = %[[ARG0]] to %[[ARG1]] step %[[ARG2]] 174// CHECK-SAME: iter_args(%[[ITER:.*]] = %[[INIT]]) -> (f32) { 175// CHECK-NEXT: %[[NEXT:.*]] = addf %[[ITER]], %[[ITER]] : f32 176// CHECK-NEXT: scf.yield %[[NEXT]] : f32 177// CHECK-NEXT: } 178 179 180func @std_for_yield_multi(%arg0 : index, %arg1 : index, %arg2 : index) { 181 %s0 = constant 0.0 : f32 182 %t0 = constant 1 : i32 183 %u0 = constant 1.0 : f32 184 %result1:3 = scf.for %i0 = %arg0 to %arg1 step %arg2 iter_args(%si = %s0, %ti = %t0, %ui = %u0) -> (f32, i32, f32) { 185 %sn = addf %si, %si : f32 186 %tn = addi %ti, %ti : i32 187 %un = subf %ui, %ui : f32 188 scf.yield %sn, %tn, %un : f32, i32, f32 189 } 190 return 191} 192// CHECK-LABEL: func @std_for_yield_multi( 193// CHECK-SAME: %[[ARG0:[A-Za-z0-9]+]]: 194// CHECK-SAME: %[[ARG1:[A-Za-z0-9]+]]: 195// CHECK-SAME: %[[ARG2:[A-Za-z0-9]+]]: 196// CHECK-NEXT: %[[INIT1:.*]] = constant 197// CHECK-NEXT: %[[INIT2:.*]] = constant 198// CHECK-NEXT: %[[INIT3:.*]] = constant 199// CHECK-NEXT: %{{.*}}:3 = scf.for %{{.*}} = %[[ARG0]] to %[[ARG1]] step %[[ARG2]] 200// CHECK-SAME: iter_args(%[[ITER1:.*]] = %[[INIT1]], %[[ITER2:.*]] = %[[INIT2]], %[[ITER3:.*]] = %[[INIT3]]) -> (f32, i32, f32) { 201// CHECK-NEXT: %[[NEXT1:.*]] = addf %[[ITER1]], %[[ITER1]] : f32 202// CHECK-NEXT: %[[NEXT2:.*]] = addi %[[ITER2]], %[[ITER2]] : i32 203// CHECK-NEXT: %[[NEXT3:.*]] = subf %[[ITER3]], %[[ITER3]] : f32 204// CHECK-NEXT: scf.yield %[[NEXT1]], %[[NEXT2]], %[[NEXT3]] : f32, i32, f32 205 206 207func @conditional_reduce(%buffer: memref<1024xf32>, %lb: index, %ub: index, %step: index) -> (f32) { 208 %sum_0 = constant 0.0 : f32 209 %c0 = constant 0.0 : f32 210 %sum = scf.for %iv = %lb to %ub step %step iter_args(%sum_iter = %sum_0) -> (f32) { 211 %t = load %buffer[%iv] : memref<1024xf32> 212 %cond = cmpf "ugt", %t, %c0 : f32 213 %sum_next = scf.if %cond -> (f32) { 214 %new_sum = addf %sum_iter, %t : f32 215 scf.yield %new_sum : f32 216 } else { 217 scf.yield %sum_iter : f32 218 } 219 scf.yield %sum_next : f32 220 } 221 return %sum : f32 222} 223// CHECK-LABEL: func @conditional_reduce( 224// CHECK-SAME: %[[ARG0:[A-Za-z0-9]+]] 225// CHECK-SAME: %[[ARG1:[A-Za-z0-9]+]] 226// CHECK-SAME: %[[ARG2:[A-Za-z0-9]+]] 227// CHECK-SAME: %[[ARG3:[A-Za-z0-9]+]] 228// CHECK-NEXT: %[[INIT:.*]] = constant 229// CHECK-NEXT: %[[ZERO:.*]] = constant 230// CHECK-NEXT: %[[RESULT:.*]] = scf.for %[[IV:.*]] = %[[ARG1]] to %[[ARG2]] step %[[ARG3]] 231// CHECK-SAME: iter_args(%[[ITER:.*]] = %[[INIT]]) -> (f32) { 232// CHECK-NEXT: %[[T:.*]] = load %[[ARG0]][%[[IV]]] 233// CHECK-NEXT: %[[COND:.*]] = cmpf "ugt", %[[T]], %[[ZERO]] 234// CHECK-NEXT: %[[IFRES:.*]] = scf.if %[[COND]] -> (f32) { 235// CHECK-NEXT: %[[THENRES:.*]] = addf %[[ITER]], %[[T]] 236// CHECK-NEXT: scf.yield %[[THENRES]] : f32 237// CHECK-NEXT: } else { 238// CHECK-NEXT: scf.yield %[[ITER]] : f32 239// CHECK-NEXT: } 240// CHECK-NEXT: scf.yield %[[IFRES]] : f32 241// CHECK-NEXT: } 242// CHECK-NEXT: return %[[RESULT]] 243 244// CHECK-LABEL: @while 245func @while() { 246 %0 = "test.get_some_value"() : () -> i32 247 %1 = "test.get_some_value"() : () -> f32 248 249 // CHECK: = scf.while (%{{.*}} = %{{.*}}, %{{.*}} = %{{.*}}) : (i32, f32) -> (i64, f64) { 250 %2:2 = scf.while (%arg0 = %0, %arg1 = %1) : (i32, f32) -> (i64, f64) { 251 %3:2 = "test.some_operation"(%arg0, %arg1) : (i32, f32) -> (i64, f64) 252 %4 = "test.some_condition"(%arg0, %arg1) : (i32, f32) -> i1 253 // CHECK: scf.condition(%{{.*}}) %{{.*}}, %{{.*}} : i64, f64 254 scf.condition(%4) %3#0, %3#1 : i64, f64 255 // CHECK: } do { 256 } do { 257 // CHECK: ^{{.*}}(%{{.*}}: i64, %{{.*}}: f64): 258 ^bb0(%arg2: i64, %arg3: f64): 259 %5:2 = "test.some_operation"(%arg2, %arg3): (i64, f64) -> (i32, f32) 260 // CHECK: scf.yield %{{.*}}, %{{.*}} : i32, f32 261 scf.yield %5#0, %5#1 : i32, f32 262 // CHECK: attributes {foo = "bar"} 263 } attributes {foo="bar"} 264 return 265} 266 267// CHECK-LABEL: @infinite_while 268func @infinite_while() { 269 %true = constant true 270 271 // CHECK: scf.while : () -> () { 272 scf.while : () -> () { 273 // CHECK: scf.condition(%{{.*}}) 274 scf.condition(%true) 275 // CHECK: } do { 276 } do { 277 // CHECK: scf.yield 278 scf.yield 279 } 280 return 281} 282