@@ -114,6 +114,102 @@ func.func @reuse_tiles_after_initial_use() {
114
114
115
115
// -----
116
116
117
+ // CHECK-LIVE-RANGE-LABEL: @tile_live_ins
118
+ // CHECK-LIVE-RANGE: ========== Coalesced Live Ranges:
119
+ // CHECK-LIVE-RANGE: ^bb0:
120
+ // CHECK-LIVE-RANGE-NEXT: S arm_sme.get_tile
121
+ // CHECK-LIVE-RANGE-NEXT: |S arm_sme.zero
122
+ // CHECK-LIVE-RANGE-NEXT: EE cf.br
123
+ // CHECK-LIVE-RANGE-NEXT: ^bb1:
124
+ // CHECK-LIVE-RANGE-NEXT: || test.dummy
125
+ // CHECK-LIVE-RANGE-NEXT: || test.dummy
126
+ // CHECK-LIVE-RANGE-NEXT: EE cf.br
127
+ // CHECK-LIVE-RANGE-NEXT: ^bb2:
128
+ // CHECK-LIVE-RANGE-NEXT: || test.dummy
129
+ // CHECK-LIVE-RANGE-NEXT: || test.dummy
130
+ // CHECK-LIVE-RANGE-NEXT: EE cf.br
131
+ // CHECK-LIVE-RANGE-NEXT: ^bb3:
132
+ // CHECK-LIVE-RANGE-NEXT: E| test.some_use
133
+ // CHECK-LIVE-RANGE-NEXT: E test.some_use
134
+
135
+ // CHECK-LABEL: @tile_live_ins
136
+ func.func @tile_live_ins ()
137
+ {
138
+ // CHECK: arm_sme.get_tile {tile_id = 0 : i32} : vector<[4]x[4]xf32>
139
+ // CHECK: arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32>
140
+ %tile_1 = arm_sme.get_tile : vector <[4 ]x[4 ]xf32 >
141
+ %tile_2 = arm_sme.zero : vector <[4 ]x[4 ]xf32 >
142
+ cf.br ^bb1
143
+ ^bb1 :
144
+ " test.dummy" (): () -> ()
145
+ " test.dummy" (): () -> ()
146
+ cf.br ^bb2
147
+ ^bb2 :
148
+ " test.dummy" (): () -> ()
149
+ " test.dummy" (): () -> ()
150
+ cf.br ^bb3
151
+ ^bb3 :
152
+ " test.some_use" (%tile_1 ) : (vector <[4 ]x[4 ]xf32 >) -> ()
153
+ " test.some_use" (%tile_2 ) : (vector <[4 ]x[4 ]xf32 >) -> ()
154
+ return
155
+ }
156
+
157
+ // -----
158
+
159
+ // This is basically the same test as tile_live_ins but shows that the order of
160
+ // the blocks within the source does not relate to the liveness, which is based
161
+ // on successors and predecessors (not textual order).
162
+ //
163
+ // So %tile_1 is live on the path bb0 -> bb2 -> bb1 (and dies in bb1). The
164
+ // 'hole' when looking at the live range dump comes from the textual order
165
+ // (and would disappear if bb1 was moved before bb2 in the source).
166
+ //
167
+ // When looking at the live range dump (outside of straight-line code) it
168
+ // normally makes more sense to consider blocks in isolation (and how they
169
+ // relate to the CFG).
170
+
171
+ // CHECK-LIVE-RANGE-LABEL: @non_sequential_live_ins
172
+ // CHECK-LIVE-RANGE: ========== Coalesced Live Ranges:
173
+ // CHECK-LIVE-RANGE: ^bb0:
174
+ // CHECK-LIVE-RANGE-NEXT: S arm_sme.get_tile
175
+ // CHECK-LIVE-RANGE-NEXT: | test.dummy
176
+ // CHECK-LIVE-RANGE-NEXT: E cf.br
177
+ // CHECK-LIVE-RANGE-NEXT: ^bb1:
178
+ // CHECK-LIVE-RANGE-NEXT: E| test.some_use
179
+ // CHECK-LIVE-RANGE-NEXT: | test.dummy
180
+ // CHECK-LIVE-RANGE-NEXT: E cf.br
181
+ // CHECK-LIVE-RANGE-NEXT: ^bb2:
182
+ // CHECK-LIVE-RANGE-NEXT: |S arm_sme.zero
183
+ // CHECK-LIVE-RANGE-NEXT: || test.dummy
184
+ // CHECK-LIVE-RANGE-NEXT: EE cf.cond_br
185
+ // CHECK-LIVE-RANGE-NEXT: ^bb3:
186
+ // CHECK-LIVE-RANGE-NEXT: | test.dummy
187
+ // CHECK-LIVE-RANGE-NEXT: E test.some_use
188
+ // CHECK-LIVE-RANGE-NEXT: func.return
189
+
190
+ // CHECK-LABEL: @non_sequential_live_ins
191
+ func.func @non_sequential_live_ins (%cond: i1 ) {
192
+ // CHECK: arm_sme.get_tile {tile_id = 0 : i32} : vector<[4]x[4]xf32>
193
+ // CHECK: arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32>
194
+ %tile_1 = arm_sme.get_tile : vector <[4 ]x[4 ]xf32 >
195
+ " test.dummy" (): () -> ()
196
+ cf.br ^bb2
197
+ ^bb1 :
198
+ " test.some_use" (%tile_1 ) : (vector <[4 ]x[4 ]xf32 >) -> ()
199
+ " test.dummy" (): () -> ()
200
+ cf.br ^bb3
201
+ ^bb2 :
202
+ %tile_2 = arm_sme.zero : vector <[4 ]x[4 ]xf32 >
203
+ " test.dummy" (): () -> ()
204
+ cf.cond_br %cond , ^bb1 , ^bb3
205
+ ^bb3 :
206
+ " test.dummy" (): () -> ()
207
+ " test.some_use" (%tile_2 ) : (vector <[4 ]x[4 ]xf32 >) -> ()
208
+ return
209
+ }
210
+
211
+ // -----
212
+
117
213
// CHECK-LIVE-RANGE-LABEL: @non_overlapping_branches
118
214
// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges:
119
215
// CHECK-LIVE-RANGE: ^bb1:
@@ -161,31 +257,6 @@ func.func @overlapping_branches(%cond: i1, %vecA: vector<[4]x[4]xf32>, %vecB: ve
161
257
162
258
// -----
163
259
164
- // CHECK-LABEL: @constant_loop_init_with_multiple_users
165
- func.func @constant_loop_init_with_multiple_users (%a: vector <[4 ]xf32 >, %b: vector <[4 ]xf32 >) {
166
- // CHECK: arm_sme.zero {tile_id = 0 : i32} : vector<[4]x[4]xf32>
167
- // CHECK: arm_sme.zero {tile_id = 1 : i32} : vector<[4]x[4]xf32>
168
- // CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 1 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32>
169
- // CHECK: arm_sme.move_vector_to_tile_slice {{.*}} {tile_id = 0 : i32} : vector<[4]xf32> into vector<[4]x[4]xf32>
170
- %c0 = arith.constant 0 : index
171
- %c1 = arith.constant 1 : index
172
- %c10 = arith.constant 10 : index
173
- %init = arm_sme.zero : vector <[4 ]x[4 ]xf32 >
174
- %tile_a = scf.for %i = %c0 to %c10 step %c1 iter_args (%iter = %init ) -> vector <[4 ]x[4 ]xf32 > {
175
- %new_tile = arm_sme.move_vector_to_tile_slice %a , %iter , %i : vector <[4 ]xf32 > into vector <[4 ]x[4 ]xf32 >
176
- scf.yield %new_tile : vector <[4 ]x[4 ]xf32 >
177
- }
178
- %tile_b = scf.for %i = %c0 to %c10 step %c1 iter_args (%iter = %init ) -> vector <[4 ]x[4 ]xf32 > {
179
- %new_tile = arm_sme.move_vector_to_tile_slice %a , %iter , %i : vector <[4 ]xf32 > into vector <[4 ]x[4 ]xf32 >
180
- scf.yield %new_tile : vector <[4 ]x[4 ]xf32 >
181
- }
182
- " test.some_use" (%tile_a ) : (vector <[4 ]x[4 ]xf32 >) -> ()
183
- " test.some_use" (%tile_b ) : (vector <[4 ]x[4 ]xf32 >) -> ()
184
- return
185
- }
186
-
187
- // -----
188
-
189
260
// CHECK-LIVE-RANGE-LABEL: @run_out_of_tiles_but_avoid_spill
190
261
// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges:
191
262
// CHECK-LIVE-RANGE: ^bb2:
0 commit comments