3
3
///----------------------------------------------------------------------------------------
4
4
/// Tests for vector.transfer_read + vector.transfer_write pairs
5
5
///
6
- /// * Indices are static
7
- /// * Single loop
6
+ /// * Nested inside a single loop
7
+ // * Indices are constant
8
8
///----------------------------------------------------------------------------------------
9
9
10
10
// The most basic example - hoisting is safe.
@@ -23,13 +23,13 @@ func.func @hoist_basic_vector_xfer_pair(
23
23
// CHECK: %[[PAD:.*]] = arith.constant 0.000000e+00 : f32
24
24
// CHECK: %[[READ:.*]] = vector.transfer_read %[[MEM]][%[[C0]], %[[C0]]], %[[PAD]] : memref<?x?xf32>, vector<1xf32>
25
25
// CHECK: %[[SCF:.*]] = scf.for %[[I:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] iter_args(%[[INIT:.*]] = %[[READ]]) -> (vector<1xf32>) {
26
- // CHECK: %[[VAL_6:.*]] = "some_use "(%[[INIT]]) : (vector<1xf32>) -> vector<1xf32>
26
+ // CHECK: %[[VAL_6:.*]] = "val_use "(%[[INIT]]) : (vector<1xf32>) -> vector<1xf32>
27
27
// CHECK: scf.yield %[[VAL_6]] : vector<1xf32>
28
28
// CHECK: }
29
29
// CHECK: vector.transfer_write %[[SCF]], %[[MEM]][%[[C0]], %[[C0]]] : vector<1xf32>, memref<?x?xf32>
30
30
scf.for %i = %lb to %ub step %step {
31
31
%r0 = vector.transfer_read %mem [%c0 , %c0 ], %pad: memref <?x?xf32 >, vector <1 xf32 >
32
- %u0 = " some_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
32
+ %u0 = " val_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
33
33
vector.transfer_write %u0 , %mem [%c0 , %c0 ] : vector <1 xf32 >, memref <?x?xf32 >
34
34
}
35
35
return
@@ -66,15 +66,15 @@ func.func @negative_hoist_basic_vector_xfer_pair_extra_write(
66
66
// CHECK: scf.for %[[I:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] {
67
67
// CHECK: vector.transfer_write %[[IN]], %[[MEM]][%[[C0]], %[[C0]]] : vector<1xf32>, memref<?x?xf32>
68
68
// CHECK: %[[READ:.*]] = vector.transfer_read %[[MEM]][%[[C0]], %[[C0]]], %[[PAD]] : memref<?x?xf32>, vector<1xf32>
69
- // CHECK: %[[USE:.*]] = "some_use "(%[[READ]]) : (vector<1xf32>) -> vector<1xf32>
69
+ // CHECK: %[[USE:.*]] = "val_use "(%[[READ]]) : (vector<1xf32>) -> vector<1xf32>
70
70
// CHECK: vector.transfer_write %[[USE]], %[[MEM]][%[[C0]], %[[C0]]] : vector<1xf32>, memref<?x?xf32>
71
71
// CHECK: }
72
72
73
73
scf.for %i = %lb to %ub step %step {
74
74
vector.transfer_write %in , %mem [%c0 , %c0 ] : vector <1 xf32 >, memref <?x?xf32 >
75
75
76
76
%r0 = vector.transfer_read %mem [%c0 , %c0 ], %pad: memref <?x?xf32 >, vector <1 xf32 >
77
- %u0 = " some_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
77
+ %u0 = " val_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
78
78
vector.transfer_write %u0 , %mem [%c0 , %c0 ] : vector <1 xf32 >, memref <?x?xf32 >
79
79
}
80
80
return
@@ -113,7 +113,7 @@ func.func @negative_hoist_basic_vector_xfer_pair_extra_write_into_alias(
113
113
// CHECK: scf.for %[[I:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] {
114
114
// CHECK: vector.transfer_write %[[IN]], %[[SV]][%[[C0]], %[[C0]]] {{.*}} : vector<1xf32>, memref<1x1xf32, strided<[?, 1]>>
115
115
// CHECK: %[[READ:.*]] = vector.transfer_read %[[MEM]][%[[C0]], %[[C0]]], %[[PAD]] : memref<?x?xf32>, vector<1xf32>
116
- // CHECK: %[[USE:.*]] = "some_use "(%[[READ]]) : (vector<1xf32>) -> vector<1xf32>
116
+ // CHECK: %[[USE:.*]] = "val_use "(%[[READ]]) : (vector<1xf32>) -> vector<1xf32>
117
117
// CHECK: vector.transfer_write %[[USE]], %[[MEM]][%[[C0]], %[[C0]]] : vector<1xf32>, memref<?x?xf32>
118
118
// CHECK: }
119
119
@@ -122,7 +122,7 @@ func.func @negative_hoist_basic_vector_xfer_pair_extra_write_into_alias(
122
122
vector.transfer_write %in , %sv [%c0 , %c0 ] : vector <1 xf32 >, memref <1 x1 xf32 , strided <[?, 1 ]>>
123
123
124
124
%r0 = vector.transfer_read %mem [%c0 , %c0 ], %pad: memref <?x?xf32 >, vector <1 xf32 >
125
- %u0 = " some_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
125
+ %u0 = " val_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
126
126
vector.transfer_write %u0 , %mem [%c0 , %c0 ] : vector <1 xf32 >, memref <?x?xf32 >
127
127
}
128
128
return
@@ -160,14 +160,14 @@ func.func @hoist_basic_vector_xfer_pair_with_assume_align(
160
160
// CHECK: %[[AA:.*]] = memref.assume_alignment %[[MEM]], 4 : memref<?x?xf32>
161
161
// CHECK: %[[READ:.*]] = vector.transfer_read %[[AA]][%[[C0]], %[[C0]]], %[[PAD]] : memref<?x?xf32>, vector<1xf32>
162
162
// CHECK: %[[SCF:.*]] = scf.for %[[I:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] iter_args(%[[INIT:.*]] = %[[READ]]) -> (vector<1xf32>) {
163
- // CHECK: %[[USE:.*]] = "some_use "(%[[INIT]]) : (vector<1xf32>) -> vector<1xf32>
163
+ // CHECK: %[[USE:.*]] = "val_use "(%[[INIT]]) : (vector<1xf32>) -> vector<1xf32>
164
164
// CHECK: }
165
165
// CHECK: vector.transfer_write %[[SCF]], %[[AA]][%[[C0]], %[[C0]]] : vector<1xf32>, memref<?x?xf32>
166
166
167
167
%aa = memref.assume_alignment %mem , 4 : memref <?x?xf32 >
168
168
scf.for %i = %lb to %ub step %step {
169
169
%r0 = vector.transfer_read %aa [%c0 , %c0 ], %pad: memref <?x?xf32 >, vector <1 xf32 >
170
- %u0 = " some_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
170
+ %u0 = " val_use " (%r0 ) : (vector <1 xf32 >) -> vector <1 xf32 >
171
171
vector.transfer_write %u0 , %aa [%c0 , %c0 ] : vector <1 xf32 >, memref <?x?xf32 >
172
172
}
173
173
return
@@ -185,6 +185,50 @@ module attributes {transform.with_named_sequence} {
185
185
186
186
// -----
187
187
188
+ // Similar as the example above, but hoisting is not safe due to extra memory
189
+ // access inside the loop via the original memref.
190
+
191
+ // CHECK-LABEL: func.func @negative_hoist_basic_vector_xfer_pair_with_assume_align(
192
+ // CHECK-SAME: %[[MEM:[a-zA-Z0-9]+]]: memref<?x?xf32>,
193
+ // CHECK-SAME: %[[LB:[a-zA-Z0-9]+]]: index,
194
+ // CHECK-SAME: %[[UB:[a-zA-Z0-9]+]]: index,
195
+ // CHECK-SAME: %[[STEP:[a-zA-Z0-9]+]]: index,
196
+ // CHECK-SAME: %[[IN:[a-zA-Z0-9]+]]: vector<1xf32>) {
197
+ func.func @negative_hoist_basic_vector_xfer_pair_with_assume_align (
198
+ %mem: memref <?x?xf32 >, %lb : index , %ub : index , %step: index , %in: vector <1 xf32 >) {
199
+ %c0 = arith.constant 0 : index
200
+ %pad = arith.constant 0.0 : f32
201
+
202
+ // CHECK: %[[C0:.*]] = arith.constant 0 : index
203
+ // CHECK: %[[PAD:.*]] = arith.constant 0.000000e+00 : f32
204
+ // CHECK: %[[AA:.*]] = memref.assume_alignment %[[MEM]], 4 : memref<?x?xf32>
205
+ // CHECK: scf.for %[[I:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] {
206
+ // CHECK: %[[READ:.*]] = vector.transfer_read %[[AA]][%[[C0]], %[[C0]]], %[[PAD]] : memref<?x?xf32>, vector<1xf32>
207
+ // CHECK: "mem_use"(%[[MEM]])
208
+ // CHECK: vector.transfer_write %[[READ]], %[[AA]][%[[C0]], %[[C0]]] : vector<1xf32>, memref<?x?xf32>
209
+ // CHECK: }
210
+
211
+ %aa = memref.assume_alignment %mem , 4 : memref <?x?xf32 >
212
+ scf.for %i = %lb to %ub step %step {
213
+ %r0 = vector.transfer_read %aa [%c0 , %c0 ], %pad: memref <?x?xf32 >, vector <1 xf32 >
214
+ " mem_use" (%mem ) : (memref <?x?xf32 >) -> ()
215
+ vector.transfer_write %r0 , %aa [%c0 , %c0 ] : vector <1 xf32 >, memref <?x?xf32 >
216
+ }
217
+ return
218
+ }
219
+
220
+ module attributes {transform.with_named_sequence } {
221
+ transform.named_sequence @__transform_main (%arg1: !transform.any_op {transform.readonly }) {
222
+ %0 = transform.structured.match ops {[" func.func" ]} in %arg1
223
+ : (!transform.any_op ) -> !transform.any_op
224
+ transform.structured.hoist_redundant_vector_transfers %0
225
+ : (!transform.any_op ) -> !transform.any_op
226
+ transform.yield
227
+ }
228
+ }
229
+
230
+ // -----
231
+
188
232
///----------------------------------------------------------------------------------------
189
233
/// Tests for vector.transfer_read + vector.transfer_write pairs
190
234
///
0 commit comments