1// RUN: mlir-opt %s -pass-pipeline='func.func(scf-for-loop-range-folding)' -split-input-file | FileCheck %s
2
3func.func @fold_one_loop(%arg0: memref<?xi32>, %arg1: index, %arg2: index) {
4  %c0 = arith.constant 0 : index
5  %c1 = arith.constant 1 : index
6  %c4 = arith.constant 4 : index
7  scf.for %i = %c0 to %arg1 step %c1 {
8    %0 = arith.addi %arg2, %i : index
9    %1 = arith.muli %0, %c4 : index
10    %2 = memref.load %arg0[%1] : memref<?xi32>
11    %3 = arith.muli %2, %2 : i32
12    memref.store %3, %arg0[%1] : memref<?xi32>
13  }
14  return
15}
16
17// CHECK-LABEL: func @fold_one_loop
18// CHECK-SAME:   (%[[ARG0:.*]]: {{.*}}, %[[ARG1:.*]]: {{.*}}, %[[ARG2:.*]]: {{.*}}
19// CHECK:       %[[C0:.*]] = arith.constant 0 : index
20// CHECK:       %[[C1:.*]] = arith.constant 1 : index
21// CHECK:       %[[C4:.*]] = arith.constant 4 : index
22// CHECK:       %[[I0:.*]] = arith.addi %[[ARG2]], %[[C0]] : index
23// CHECK:       %[[I1:.*]] = arith.addi %[[ARG2]], %[[ARG1]] : index
24// CHECK:       %[[I2:.*]] = arith.muli %[[I1]], %[[C4]] : index
25// CHECK:       %[[I3:.*]] = arith.muli %[[C1]], %[[C4]] : index
26// CHECK:       scf.for %[[I:.*]] = %[[I0]] to %[[I2]] step %[[I3]] {
27// CHECK:         %[[I4:.*]] = memref.load %[[ARG0]]{{\[}}%[[I]]
28// CHECK:         %[[I5:.*]] = arith.muli %[[I4]], %[[I4]] : i32
29// CHECK:         memref.store %[[I5]], %[[ARG0]]{{\[}}%[[I]]
30
31func.func @fold_one_loop2(%arg0: memref<?xi32>, %arg1: index, %arg2: index) {
32  %c0 = arith.constant 0 : index
33  %c1 = arith.constant 1 : index
34  %c4 = arith.constant 4 : index
35  %c10 = arith.constant 10 : index
36  scf.for %j = %c0 to %c10 step %c1 {
37    scf.for %i = %c0 to %arg1 step %c1 {
38      %0 = arith.addi %arg2, %i : index
39      %1 = arith.muli %0, %c4 : index
40      %2 = memref.load %arg0[%1] : memref<?xi32>
41      %3 = arith.muli %2, %2 : i32
42      memref.store %3, %arg0[%1] : memref<?xi32>
43    }
44  }
45  return
46}
47
48// CHECK-LABEL: func @fold_one_loop2
49// CHECK-SAME:   (%[[ARG0:.*]]: {{.*}}, %[[ARG1:.*]]: {{.*}}, %[[ARG2:.*]]: {{.*}}
50// CHECK:       %[[C0:.*]] = arith.constant 0 : index
51// CHECK:       %[[C1:.*]] = arith.constant 1 : index
52// CHECK:       %[[C4:.*]] = arith.constant 4 : index
53// CHECK:       %[[C10:.*]] = arith.constant 10 : index
54// CHECK:       scf.for %[[J:.*]] = %[[C0]] to %[[C10]] step %[[C1]] {
55// CHECK:         %[[I0:.*]] = arith.addi %[[ARG2]], %[[C0]] : index
56// CHECK:         %[[I1:.*]] = arith.addi %[[ARG2]], %[[ARG1]] : index
57// CHECK:         %[[I2:.*]] = arith.muli %[[I1]], %[[C4]] : index
58// CHECK:         %[[I3:.*]] = arith.muli %[[C1]], %[[C4]] : index
59// CHECK:         scf.for %[[I:.*]] = %[[I0]] to %[[I2]] step %[[I3]] {
60// CHECK:           %[[I4:.*]] = memref.load %[[ARG0]]{{\[}}%[[I]]
61// CHECK:           %[[I5:.*]] = arith.muli %[[I4]], %[[I4]] : i32
62// CHECK:           memref.store %[[I5]], %[[ARG0]]{{\[}}%[[I]]
63
64func.func @fold_two_loops(%arg0: memref<?xi32>, %arg1: index, %arg2: index) {
65  %c0 = arith.constant 0 : index
66  %c1 = arith.constant 1 : index
67  %c4 = arith.constant 4 : index
68  %c10 = arith.constant 10 : index
69  scf.for %j = %c0 to %c10 step %c1 {
70    scf.for %i = %j to %arg1 step %c1 {
71      %0 = arith.addi %arg2, %i : index
72      %1 = arith.muli %0, %c4 : index
73      %2 = memref.load %arg0[%1] : memref<?xi32>
74      %3 = arith.muli %2, %2 : i32
75      memref.store %3, %arg0[%1] : memref<?xi32>
76    }
77  }
78  return
79}
80
81// CHECK-LABEL: func @fold_two_loops
82// CHECK-SAME:   (%[[ARG0:.*]]: {{.*}}, %[[ARG1:.*]]: {{.*}}, %[[ARG2:.*]]: {{.*}}
83// CHECK:       %[[C0:.*]] = arith.constant 0 : index
84// CHECK:       %[[C1:.*]] = arith.constant 1 : index
85// CHECK:       %[[C4:.*]] = arith.constant 4 : index
86// CHECK:       %[[C10:.*]] = arith.constant 10 : index
87// CHECK:       %[[I0:.*]] = arith.addi %[[ARG2]], %[[C0]] : index
88// CHECK:       %[[I1:.*]] = arith.addi %[[ARG2]], %[[C10]] : index
89// CHECK:       scf.for %[[J:.*]] = %[[I0]] to %[[I1]] step %[[C1]] {
90// CHECK:         %[[I1:.*]] = arith.addi %[[ARG2]], %[[ARG1]] : index
91// CHECK:         %[[I2:.*]] = arith.muli %[[I1]], %[[C4]] : index
92// CHECK:         %[[I3:.*]] = arith.muli %[[C1]], %[[C4]] : index
93// CHECK:         scf.for %[[I:.*]] = %[[J]] to %[[I2]] step %[[I3]] {
94// CHECK:           %[[I4:.*]] = memref.load %[[ARG0]]{{\[}}%[[I]]
95// CHECK:           %[[I5:.*]] = arith.muli %[[I4]], %[[I4]] : i32
96// CHECK:           memref.store %[[I5]], %[[ARG0]]{{\[}}%[[I]]
97
98// If an instruction's operands are not defined outside the loop, we cannot
99// perform the optimization, as is the case with the arith.muli below. (If
100// paired with loop invariant code motion we can continue.)
101func.func @fold_only_first_add(%arg0: memref<?xi32>, %arg1: index, %arg2: index) {
102  %c0 = arith.constant 0 : index
103  %c1 = arith.constant 1 : index
104  %c4 = arith.constant 4 : index
105  scf.for %i = %c0 to %arg1 step %c1 {
106    %0 = arith.addi %arg2, %i : index
107    %1 = arith.addi %arg2, %c4 : index
108    %2 = arith.muli %0, %1 : index
109    %3 = memref.load %arg0[%2] : memref<?xi32>
110    %4 = arith.muli %3, %3 : i32
111    memref.store %4, %arg0[%2] : memref<?xi32>
112  }
113  return
114}
115
116// CHECK-LABEL: func @fold_only_first_add
117// CHECK-SAME:   (%[[ARG0:.*]]: {{.*}}, %[[ARG1:.*]]: {{.*}}, %[[ARG2:.*]]: {{.*}}
118// CHECK:       %[[C0:.*]] = arith.constant 0 : index
119// CHECK:       %[[C1:.*]] = arith.constant 1 : index
120// CHECK:       %[[C4:.*]] = arith.constant 4 : index
121// CHECK:       %[[I0:.*]] = arith.addi %[[ARG2]], %[[C0]] : index
122// CHECK:       %[[I1:.*]] = arith.addi %[[ARG2]], %[[ARG1]] : index
123// CHECK:       scf.for %[[I:.*]] = %[[I0]] to %[[I1]] step %[[C1]] {
124// CHECK:         %[[I2:.*]] = arith.addi %[[ARG2]], %[[C4]] : index
125// CHECK:         %[[I3:.*]] = arith.muli %[[I]], %[[I2]] : index
126// CHECK:         %[[I4:.*]] = memref.load %[[ARG0]]{{\[}}%[[I3]]
127// CHECK:         %[[I5:.*]] = arith.muli %[[I4]], %[[I4]] : i32
128// CHECK:         memref.store %[[I5]], %[[ARG0]]{{\[}}%[[I3]]
129