@@ -114,6 +114,102 @@ func.func @reuse_tiles_after_initial_use() {
114114
115115// -----
116116
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+
117213// CHECK-LIVE-RANGE-LABEL: @non_overlapping_branches
118214// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges:
119215// CHECK-LIVE-RANGE: ^bb1:
@@ -161,31 +257,6 @@ func.func @overlapping_branches(%cond: i1, %vecA: vector<[4]x[4]xf32>, %vecB: ve
161257
162258// -----
163259
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-
189260// CHECK-LIVE-RANGE-LABEL: @run_out_of_tiles_but_avoid_spill
190261// CHECK-LIVE-RANGE: ========== Coalesced Live Ranges:
191262// CHECK-LIVE-RANGE: ^bb2:
0 commit comments