1 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2 # RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -start-before=si-lower-sgpr-spills -stop-after=virtregrewriter,1 -verify-machineinstrs %s -o - | FileCheck -check-prefix=GCN %s
4 # Tests to check the conservative lieness extension for the wwm registers during SGPR spill lowering.
6 # Even though the VGPR can be shared for the wwm-operand (writelane/readlane get inserted for the SGPR spills)
7 # and the regular operand (%0), they get different registers as we conservatively extend the liveness of the
10 name: test_single_block
11 tracksRegLiveness: true
15 - { id: 0, type: spill-slot, size: 4, alignment: 4, stack-id: sgpr-spill }
17 isEntryFunction: false
18 scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
19 stackPtrOffsetReg: '$sgpr32'
20 frameOffsetReg: '$sgpr33'
24 liveins: $sgpr4, $vgpr2_vgpr3
25 ; GCN-LABEL: name: test_single_block
26 ; GCN: liveins: $sgpr4, $vgpr2_vgpr3
28 ; GCN-NEXT: renamable $vgpr0 = IMPLICIT_DEF
29 ; GCN-NEXT: renamable $vgpr0 = SI_SPILL_S32_TO_VGPR $sgpr4, 0, killed $vgpr0
31 ; GCN-NEXT: $sgpr4 = SI_RESTORE_S32_FROM_VGPR $vgpr0, 0
32 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 20, implicit $exec
33 ; GCN-NEXT: GLOBAL_STORE_DWORD $vgpr2_vgpr3, killed renamable $vgpr1, 0, 0, implicit $exec
34 ; GCN-NEXT: KILL killed renamable $vgpr0
36 SI_SPILL_S32_SAVE killed $sgpr4, %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
38 renamable $sgpr4 = SI_SPILL_S32_RESTORE %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
39 %0:vgpr_32 = V_MOV_B32_e32 20, implicit $exec
40 GLOBAL_STORE_DWORD $vgpr2_vgpr3, %0:vgpr_32, 0, 0, implicit $exec
44 # Due to the presence of wwm-operand in the divergent flow, the regular variable (%0) shouldn't get the same register
45 # allocated for the wwm-operand in writelane/readlane when the SGPR spill is lowered.
49 tracksRegLiveness: true
53 - { id: 0, type: spill-slot, size: 4, alignment: 4, stack-id: sgpr-spill }
55 isEntryFunction: false
56 scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
57 stackPtrOffsetReg: '$sgpr32'
58 frameOffsetReg: '$sgpr33'
61 ; GCN-LABEL: name: test_if_else
63 ; GCN-NEXT: successors: %bb.1(0x80000000)
64 ; GCN-NEXT: liveins: $sgpr6, $sgpr10_sgpr11
66 ; GCN-NEXT: renamable $vgpr0 = IMPLICIT_DEF
67 ; GCN-NEXT: S_BRANCH %bb.1
70 ; GCN-NEXT: successors: %bb.3(0x40000000), %bb.2(0x40000000)
71 ; GCN-NEXT: liveins: $sgpr6, $vgpr0, $sgpr10_sgpr11
73 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 10, implicit $exec
74 ; GCN-NEXT: S_CBRANCH_EXECZ %bb.3, implicit $exec
77 ; GCN-NEXT: successors: %bb.3(0x80000000)
78 ; GCN-NEXT: liveins: $sgpr6, $vgpr0, $sgpr10_sgpr11
80 ; GCN-NEXT: renamable $vgpr0 = SI_SPILL_S32_TO_VGPR $sgpr6, 0, killed $vgpr0
82 ; GCN-NEXT: $sgpr6 = SI_RESTORE_S32_FROM_VGPR $vgpr0, 0
83 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 20, implicit $exec
84 ; GCN-NEXT: S_BRANCH %bb.3
87 ; GCN-NEXT: liveins: $vgpr0, $vgpr1, $sgpr10_sgpr11
89 ; GCN-NEXT: $sgpr5 = V_READFIRSTLANE_B32 killed $vgpr1, implicit $exec
90 ; GCN-NEXT: S_STORE_DWORD_IMM $sgpr5, $sgpr10_sgpr11, 0, 0
91 ; GCN-NEXT: KILL killed renamable $vgpr0
94 liveins: $sgpr6, $sgpr10_sgpr11
97 liveins: $sgpr6, $sgpr10_sgpr11
98 %0:vgpr_32 = V_MOV_B32_e32 10, implicit $exec
99 S_CBRANCH_EXECZ %bb.3, implicit $exec
101 liveins: $sgpr6, $sgpr10_sgpr11
102 SI_SPILL_S32_SAVE killed $sgpr6, %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
104 renamable $sgpr6 = SI_SPILL_S32_RESTORE %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
105 %0:vgpr_32 = V_MOV_B32_e32 20, implicit $exec
108 liveins: $sgpr10_sgpr11
109 $sgpr5 = V_READFIRSTLANE_B32 %0:vgpr_32, implicit $exec
110 S_STORE_DWORD_IMM $sgpr5, $sgpr10_sgpr11, 0, 0
114 # The wwm-register usage outside the loop should have the interference marked with
115 # all the regular virtual registers used in the test. The divergent loop index value (%1)
116 # can actually share the same VGPR as the wwm-operand. But since we extend the liveness of
117 # the wwm operand, an interference will always exist between them.
121 tracksRegLiveness: true
125 - { id: 0, type: spill-slot, size: 4, alignment: 4, stack-id: sgpr-spill }
127 isEntryFunction: false
128 scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
129 stackPtrOffsetReg: '$sgpr32'
130 frameOffsetReg: '$sgpr33'
131 hasSpilledSGPRs: true
133 ; GCN-LABEL: name: test_loop
135 ; GCN-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
136 ; GCN-NEXT: liveins: $sgpr4, $sgpr10_sgpr11
138 ; GCN-NEXT: renamable $vgpr0 = IMPLICIT_DEF
139 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 10, implicit $exec
140 ; GCN-NEXT: S_CBRANCH_EXECZ %bb.2, implicit $exec
143 ; GCN-NEXT: successors: %bb.2(0x80000000)
144 ; GCN-NEXT: liveins: $sgpr4, $vgpr0, $sgpr10_sgpr11
146 ; GCN-NEXT: renamable $vgpr0 = SI_SPILL_S32_TO_VGPR $sgpr4, 0, killed $vgpr0
148 ; GCN-NEXT: $sgpr4 = SI_RESTORE_S32_FROM_VGPR $vgpr0, 0
149 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 20, implicit $exec
150 ; GCN-NEXT: S_BRANCH %bb.2
153 ; GCN-NEXT: successors: %bb.3(0x80000000)
154 ; GCN-NEXT: liveins: $sgpr4, $vgpr0, $vgpr1, $sgpr10_sgpr11
156 ; GCN-NEXT: S_STORE_DWORD_IMM $sgpr4, $sgpr10_sgpr11, 0, 0
157 ; GCN-NEXT: $sgpr5 = V_READFIRSTLANE_B32 killed $vgpr1, implicit $exec
158 ; GCN-NEXT: S_STORE_DWORD_IMM $sgpr5, $sgpr10_sgpr11, 0, 4
159 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 5, implicit $exec
160 ; GCN-NEXT: S_CBRANCH_EXECZ %bb.3, implicit $exec
161 ; GCN-NEXT: S_BRANCH %bb.3
164 ; GCN-NEXT: successors: %bb.5(0x40000000), %bb.4(0x40000000)
165 ; GCN-NEXT: liveins: $vgpr0, $vgpr1
167 ; GCN-NEXT: $vcc = V_CMP_EQ_U32_e64 0, $vgpr1, implicit $exec
168 ; GCN-NEXT: $sgpr6_sgpr7 = S_AND_SAVEEXEC_B64 $vcc, implicit-def $exec, implicit-def $scc, implicit $exec
169 ; GCN-NEXT: S_CBRANCH_SCC1 %bb.5, implicit $scc
172 ; GCN-NEXT: successors: %bb.3(0x80000000)
173 ; GCN-NEXT: liveins: $vgpr0, $vgpr1, $sgpr6_sgpr7
175 ; GCN-NEXT: renamable $vgpr1 = V_SUB_U32_e32 1, killed $vgpr1, implicit $exec
176 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 killed $vgpr1, implicit $exec
177 ; GCN-NEXT: S_BRANCH %bb.3
180 ; GCN-NEXT: liveins: $vgpr0, $sgpr6_sgpr7
182 ; GCN-NEXT: $exec = S_OR_B64 $exec, $sgpr6_sgpr7, implicit-def $scc
183 ; GCN-NEXT: KILL killed renamable $vgpr0
184 ; GCN-NEXT: SI_RETURN
186 liveins: $sgpr4, $sgpr10_sgpr11
187 %0:vgpr_32 = V_MOV_B32_e32 10, implicit $exec
188 S_CBRANCH_EXECZ %bb.2, implicit $exec
190 liveins: $sgpr4, $sgpr10_sgpr11
191 SI_SPILL_S32_SAVE killed $sgpr4, %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
193 renamable $sgpr4 = SI_SPILL_S32_RESTORE %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
194 %0:vgpr_32 = V_MOV_B32_e32 20, implicit $exec
197 liveins: $sgpr4, $sgpr10_sgpr11
198 S_STORE_DWORD_IMM $sgpr4, $sgpr10_sgpr11, 0, 0
199 $sgpr5 = V_READFIRSTLANE_B32 %0:vgpr_32, implicit $exec
200 S_STORE_DWORD_IMM $sgpr5, $sgpr10_sgpr11, 0, 4
201 %1:vgpr_32 = V_MOV_B32_e32 5, implicit $exec
202 S_CBRANCH_EXECZ %bb.3, implicit $exec
205 $vcc = V_CMP_EQ_U32_e64 0, %1:vgpr_32, implicit $exec
206 $sgpr6_sgpr7 = S_AND_SAVEEXEC_B64 $vcc, implicit-def $exec, implicit-def $scc, implicit $exec
207 S_CBRANCH_SCC1 %bb.5, implicit $scc
209 liveins: $sgpr6_sgpr7
210 %2:vgpr_32 = V_SUB_U32_e32 1, %1:vgpr_32, implicit $exec
211 %1:vgpr_32 = V_MOV_B32_e32 %2:vgpr_32, implicit $exec
214 liveins: $sgpr6_sgpr7
215 $exec = S_OR_B64 $exec, $sgpr6_sgpr7, implicit-def $scc
219 # There must be one KILL instruction for the wwm-operand in every return block.
220 # Due to that, the wwm-register allocated should be different from the ones
221 # allocated for the regular virtual registers.
224 name: test_multiple_return_blocks
225 tracksRegLiveness: true
229 - { id: 0, type: spill-slot, size: 4, alignment: 4, stack-id: sgpr-spill }
231 isEntryFunction: false
232 scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
233 stackPtrOffsetReg: '$sgpr32'
234 frameOffsetReg: '$sgpr33'
235 hasSpilledSGPRs: true
237 ; GCN-LABEL: name: test_multiple_return_blocks
239 ; GCN-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
240 ; GCN-NEXT: liveins: $sgpr4, $vgpr2_vgpr3
242 ; GCN-NEXT: renamable $vgpr0 = IMPLICIT_DEF
243 ; GCN-NEXT: S_CBRANCH_EXECZ %bb.2, implicit $exec
246 ; GCN-NEXT: liveins: $sgpr4, $vgpr0, $vgpr2_vgpr3
248 ; GCN-NEXT: renamable $vgpr0 = SI_SPILL_S32_TO_VGPR $sgpr4, 0, killed $vgpr0
250 ; GCN-NEXT: $sgpr4 = SI_RESTORE_S32_FROM_VGPR $vgpr0, 0
251 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 10, implicit $exec
252 ; GCN-NEXT: GLOBAL_STORE_DWORD $vgpr2_vgpr3, killed renamable $vgpr1, 0, 0, implicit $exec
253 ; GCN-NEXT: KILL killed renamable $vgpr0
254 ; GCN-NEXT: SI_RETURN
257 ; GCN-NEXT: liveins: $vgpr0, $vgpr2_vgpr3
259 ; GCN-NEXT: renamable $vgpr1 = V_MOV_B32_e32 20, implicit $exec
260 ; GCN-NEXT: GLOBAL_STORE_DWORD $vgpr2_vgpr3, killed renamable $vgpr1, 0, 0, implicit $exec
261 ; GCN-NEXT: KILL killed renamable $vgpr0
262 ; GCN-NEXT: SI_RETURN
264 liveins: $sgpr4, $vgpr2_vgpr3
265 S_CBRANCH_EXECZ %bb.2, implicit $exec
267 liveins: $sgpr4, $vgpr2_vgpr3
268 SI_SPILL_S32_SAVE killed $sgpr4, %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
270 renamable $sgpr4 = SI_SPILL_S32_RESTORE %stack.0, implicit $exec, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr32
271 %0:vgpr_32 = V_MOV_B32_e32 10, implicit $exec
272 GLOBAL_STORE_DWORD $vgpr2_vgpr3, %0:vgpr_32, 0, 0, implicit $exec
275 liveins: $vgpr2_vgpr3
276 %1:vgpr_32 = V_MOV_B32_e32 20, implicit $exec
277 GLOBAL_STORE_DWORD $vgpr2_vgpr3, %1:vgpr_32, 0, 0, implicit $exec