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