1# RUN: llc -march=amdgcn -verify-machineinstrs -run-pass si-optimize-exec-masking -o -  %s | FileCheck %s
2
3--- |
4  define amdgpu_kernel void @optimize_if_and_saveexec_xor(i32 %z, i32 %v) #0 {
5  main_body:
6    %id = call i32 @llvm.amdgcn.workitem.id.x()
7    %cc = icmp eq i32 %id, 0
8    %0 = call { i1, i64 } @llvm.amdgcn.if(i1 %cc)
9    %1 = extractvalue { i1, i64 } %0, 0
10    %2 = extractvalue { i1, i64 } %0, 1
11    br i1 %1, label %if, label %end
12
13  if:                                               ; preds = %main_body
14    %v.if = load volatile i32, i32 addrspace(1)* undef
15    br label %end
16
17  end:                                              ; preds = %if, %main_body
18    %r = phi i32 [ 4, %main_body ], [ %v.if, %if ]
19    call void @llvm.amdgcn.end.cf(i64 %2)
20    store i32 %r, i32 addrspace(1)* undef
21    ret void
22  }
23
24  define amdgpu_kernel void @optimize_if_and_saveexec(i32 %z, i32 %v)  #0 {
25  main_body:
26      br i1 undef, label %if, label %end
27
28  if:
29    br label %end
30
31  end:
32    ret void
33  }
34
35  define amdgpu_kernel void @optimize_if_or_saveexec(i32 %z, i32 %v)  #0 {
36  main_body:
37      br i1 undef, label %if, label %end
38
39  if:
40    br label %end
41
42  end:
43    ret void
44  }
45
46
47  define amdgpu_kernel void @optimize_if_and_saveexec_xor_valu_middle(i32 %z, i32 %v) #0 {
48  main_body:
49    %id = call i32 @llvm.amdgcn.workitem.id.x()
50    %cc = icmp eq i32 %id, 0
51    %0 = call { i1, i64 } @llvm.amdgcn.if(i1 %cc)
52    %1 = extractvalue { i1, i64 } %0, 0
53    %2 = extractvalue { i1, i64 } %0, 1
54    store i32 %id, i32 addrspace(1)* undef
55    br i1 %1, label %if, label %end
56
57  if:                                               ; preds = %main_body
58    %v.if = load volatile i32, i32 addrspace(1)* undef
59    br label %end
60
61  end:                                              ; preds = %if, %main_body
62    %r = phi i32 [ 4, %main_body ], [ %v.if, %if ]
63    call void @llvm.amdgcn.end.cf(i64 %2)
64    store i32 %r, i32 addrspace(1)* undef
65    ret void
66  }
67
68  define amdgpu_kernel void @optimize_if_and_saveexec_xor_wrong_reg(i32 %z, i32 %v)  #0 {
69  main_body:
70      br i1 undef, label %if, label %end
71
72  if:
73    br label %end
74
75  end:
76    ret void
77  }
78
79  define amdgpu_kernel void @optimize_if_and_saveexec_xor_modify_copy_to_exec(i32 %z, i32 %v)  #0 {
80  main_body:
81      br i1 undef, label %if, label %end
82
83  if:
84    br label %end
85
86  end:
87    ret void
88  }
89
90  define amdgpu_kernel void @optimize_if_and_saveexec_xor_live_out_setexec(i32 %z, i32 %v)  #0 {
91  main_body:
92      br i1 undef, label %if, label %end
93
94  if:
95    br label %end
96
97  end:
98    ret void
99  }
100
101  define amdgpu_kernel void @optimize_if_unknown_saveexec(i32 %z, i32 %v)  #0 {
102  main_body:
103      br i1 undef, label %if, label %end
104
105  if:
106    br label %end
107
108  end:
109    ret void
110  }
111
112  define amdgpu_kernel void @optimize_if_andn2_saveexec(i32 %z, i32 %v)  #0 {
113  main_body:
114      br i1 undef, label %if, label %end
115
116  if:
117    br label %end
118
119  end:
120    ret void
121  }
122
123  define amdgpu_kernel void @optimize_if_andn2_saveexec_no_commute(i32 %z, i32 %v)  #0 {
124  main_body:
125      br i1 undef, label %if, label %end
126
127  if:
128    br label %end
129
130  end:
131    ret void
132  }
133
134  ; Function Attrs: nounwind readnone
135  declare i32 @llvm.amdgcn.workitem.id.x() #1
136
137  declare { i1, i64 } @llvm.amdgcn.if(i1)
138
139  declare void @llvm.amdgcn.end.cf(i64)
140
141
142  attributes #0 = { nounwind }
143  attributes #1 = { nounwind readnone }
144
145...
146---
147# CHECK-LABEL: name: optimize_if_and_saveexec_xor{{$}}
148# CHECK: $sgpr0_sgpr1 = S_AND_SAVEEXEC_B64 $vcc, implicit-def $exec, implicit-def $scc, implicit $exec
149# CHECK-NEXT: $sgpr0_sgpr1 = S_XOR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
150# CHECK-NEXT: SI_MASK_BRANCH
151
152name:            optimize_if_and_saveexec_xor
153alignment:       0
154exposesReturnsTwice: false
155legalized:       false
156regBankSelected: false
157selected:        false
158tracksRegLiveness: true
159liveins:
160  - { reg: '$vgpr0' }
161frameInfo:
162  isFrameAddressTaken: false
163  isReturnAddressTaken: false
164  hasStackMap:     false
165  hasPatchPoint:   false
166  stackSize:       0
167  offsetAdjustment: 0
168  maxAlignment:    0
169  adjustsStack:    false
170  hasCalls:        false
171  maxCallFrameSize: 0
172  hasOpaqueSPAdjustment: false
173  hasVAStart:      false
174  hasMustTailInVarArgFunc: false
175body:             |
176  bb.0.main_body:
177    liveins: $vgpr0
178
179    $sgpr0_sgpr1 = COPY $exec
180    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
181    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
182    $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
183    $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
184    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
185    SI_MASK_BRANCH %bb.2, implicit $exec
186    S_BRANCH %bb.1
187
188  bb.1.if:
189    liveins: $sgpr0_sgpr1
190
191    $sgpr7 = S_MOV_B32 61440
192    $sgpr6 = S_MOV_B32 -1
193    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
194
195  bb.2.end:
196    liveins: $vgpr0, $sgpr0_sgpr1
197
198    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
199    $sgpr3 = S_MOV_B32 61440
200    $sgpr2 = S_MOV_B32 -1
201    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
202    S_ENDPGM
203
204...
205---
206# CHECK-LABEL: name: optimize_if_and_saveexec{{$}}
207# CHECK: $sgpr0_sgpr1 = S_AND_SAVEEXEC_B64 $vcc, implicit-def $exec, implicit-def $scc, implicit $exec
208# CHECK-NEXT: SI_MASK_BRANCH
209
210name:            optimize_if_and_saveexec
211alignment:       0
212exposesReturnsTwice: false
213legalized:       false
214regBankSelected: false
215selected:        false
216tracksRegLiveness: true
217liveins:
218  - { reg: '$vgpr0' }
219frameInfo:
220  isFrameAddressTaken: false
221  isReturnAddressTaken: false
222  hasStackMap:     false
223  hasPatchPoint:   false
224  stackSize:       0
225  offsetAdjustment: 0
226  maxAlignment:    0
227  adjustsStack:    false
228  hasCalls:        false
229  maxCallFrameSize: 0
230  hasOpaqueSPAdjustment: false
231  hasVAStart:      false
232  hasMustTailInVarArgFunc: false
233body:             |
234  bb.0.main_body:
235    liveins: $vgpr0
236
237    $sgpr0_sgpr1 = COPY $exec
238    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
239    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
240    $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
241    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
242    SI_MASK_BRANCH %bb.2, implicit $exec
243    S_BRANCH %bb.1
244
245  bb.1.if:
246    liveins: $sgpr0_sgpr1
247
248    $sgpr7 = S_MOV_B32 61440
249    $sgpr6 = S_MOV_B32 -1
250    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
251
252  bb.2.end:
253    liveins: $vgpr0, $sgpr0_sgpr1
254
255    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
256    $sgpr3 = S_MOV_B32 61440
257    $sgpr2 = S_MOV_B32 -1
258    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
259    S_ENDPGM
260
261...
262---
263# CHECK-LABEL: name: optimize_if_or_saveexec{{$}}
264# CHECK: $sgpr0_sgpr1 = S_OR_SAVEEXEC_B64 $vcc, implicit-def $exec, implicit-def $scc, implicit $exec
265# CHECK-NEXT: SI_MASK_BRANCH
266
267name:            optimize_if_or_saveexec
268alignment:       0
269exposesReturnsTwice: false
270legalized:       false
271regBankSelected: false
272selected:        false
273tracksRegLiveness: true
274liveins:
275  - { reg: '$vgpr0' }
276frameInfo:
277  isFrameAddressTaken: false
278  isReturnAddressTaken: false
279  hasStackMap:     false
280  hasPatchPoint:   false
281  stackSize:       0
282  offsetAdjustment: 0
283  maxAlignment:    0
284  adjustsStack:    false
285  hasCalls:        false
286  maxCallFrameSize: 0
287  hasOpaqueSPAdjustment: false
288  hasVAStart:      false
289  hasMustTailInVarArgFunc: false
290body:             |
291  bb.0.main_body:
292    liveins: $vgpr0
293
294    $sgpr0_sgpr1 = COPY $exec
295    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
296    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
297    $sgpr2_sgpr3 = S_OR_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
298    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
299    SI_MASK_BRANCH %bb.2, implicit $exec
300    S_BRANCH %bb.1
301
302  bb.1.if:
303    liveins: $sgpr0_sgpr1
304
305    $sgpr7 = S_MOV_B32 61440
306    $sgpr6 = S_MOV_B32 -1
307    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
308
309  bb.2.end:
310    liveins: $vgpr0, $sgpr0_sgpr1
311
312    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
313    $sgpr3 = S_MOV_B32 61440
314    $sgpr2 = S_MOV_B32 -1
315    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
316    S_ENDPGM
317
318...
319---
320# CHECK-LABEL: name: optimize_if_and_saveexec_xor_valu_middle
321# CHECK: $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
322# CHECK-NEXT: BUFFER_STORE_DWORD_OFFSET $vgpr0, undef $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`, addrspace 1)
323# CHECK-NEXT: $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
324# CHECK-NEXT: $exec = COPY killed $sgpr2_sgpr3
325# CHECK-NEXT: SI_MASK_BRANCH
326name:            optimize_if_and_saveexec_xor_valu_middle
327alignment:       0
328exposesReturnsTwice: false
329legalized:       false
330regBankSelected: false
331selected:        false
332tracksRegLiveness: true
333liveins:
334  - { reg: '$vgpr0' }
335frameInfo:
336  isFrameAddressTaken: false
337  isReturnAddressTaken: false
338  hasStackMap:     false
339  hasPatchPoint:   false
340  stackSize:       0
341  offsetAdjustment: 0
342  maxAlignment:    0
343  adjustsStack:    false
344  hasCalls:        false
345  maxCallFrameSize: 0
346  hasOpaqueSPAdjustment: false
347  hasVAStart:      false
348  hasMustTailInVarArgFunc: false
349body:             |
350  bb.0.main_body:
351    liveins: $vgpr0
352
353    $sgpr0_sgpr1 = COPY $exec
354    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
355    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
356    $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
357    BUFFER_STORE_DWORD_OFFSET $vgpr0, undef $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
358    $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
359    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
360    SI_MASK_BRANCH %bb.2, implicit $exec
361    S_BRANCH %bb.1
362
363  bb.1.if:
364    liveins: $sgpr0_sgpr1
365
366    $sgpr7 = S_MOV_B32 61440
367    $sgpr6 = S_MOV_B32 -1
368    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
369
370  bb.2.end:
371    liveins: $vgpr0, $sgpr0_sgpr1
372
373    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
374    $sgpr3 = S_MOV_B32 61440
375    $sgpr2 = S_MOV_B32 -1
376    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
377    S_ENDPGM
378
379...
380---
381# CHECK-LABEL: name: optimize_if_and_saveexec_xor_wrong_reg{{$}}
382# CHECK: $sgpr0_sgpr1 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
383# CHECK-NEXT: $sgpr0_sgpr1 = S_XOR_B64 undef $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
384# CHECK-NEXT: $exec = COPY $sgpr0_sgpr1
385# CHECK-NEXT: SI_MASK_BRANCH %bb.2, implicit $exec
386name:            optimize_if_and_saveexec_xor_wrong_reg
387alignment:       0
388exposesReturnsTwice: false
389legalized:       false
390regBankSelected: false
391selected:        false
392tracksRegLiveness: true
393liveins:
394  - { reg: '$vgpr0' }
395frameInfo:
396  isFrameAddressTaken: false
397  isReturnAddressTaken: false
398  hasStackMap:     false
399  hasPatchPoint:   false
400  stackSize:       0
401  offsetAdjustment: 0
402  maxAlignment:    0
403  adjustsStack:    false
404  hasCalls:        false
405  maxCallFrameSize: 0
406  hasOpaqueSPAdjustment: false
407  hasVAStart:      false
408  hasMustTailInVarArgFunc: false
409body:             |
410  bb.0.main_body:
411    liveins: $vgpr0
412
413    $sgpr6 = S_MOV_B32 -1
414    $sgpr7 = S_MOV_B32 61440
415    $sgpr0_sgpr1 = COPY $exec
416    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
417    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
418    $sgpr0_sgpr1 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
419    $sgpr0_sgpr1 = S_XOR_B64 undef $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
420    $exec = S_MOV_B64_term $sgpr0_sgpr1
421    SI_MASK_BRANCH %bb.2, implicit $exec
422    S_BRANCH %bb.1
423
424  bb.1.if:
425    liveins: $sgpr0_sgpr1 , $sgpr4_sgpr5_sgpr6_sgpr7
426    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
427
428  bb.2.end:
429    liveins: $vgpr0, $sgpr0_sgpr1, $sgpr4_sgpr5_sgpr6_sgpr7
430
431    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
432    $sgpr3 = S_MOV_B32 61440
433    $sgpr2 = S_MOV_B32 -1
434    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
435    S_ENDPGM
436
437...
438---
439# CHECK-LABEL: name: optimize_if_and_saveexec_xor_modify_copy_to_exec{{$}}
440# CHECK: $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
441# CHECK-NEXT: $sgpr2_sgpr3 = S_OR_B64 killed $sgpr2_sgpr3, 1, implicit-def $scc
442# CHECK-NEXT: $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
443# CHECK-NEXT: $exec = COPY killed $sgpr2_sgpr3
444# CHECK-NEXT: SI_MASK_BRANCH %bb.2, implicit $exec
445
446name:            optimize_if_and_saveexec_xor_modify_copy_to_exec
447alignment:       0
448exposesReturnsTwice: false
449legalized:       false
450regBankSelected: false
451selected:        false
452tracksRegLiveness: true
453liveins:
454  - { reg: '$vgpr0' }
455frameInfo:
456  isFrameAddressTaken: false
457  isReturnAddressTaken: false
458  hasStackMap:     false
459  hasPatchPoint:   false
460  stackSize:       0
461  offsetAdjustment: 0
462  maxAlignment:    0
463  adjustsStack:    false
464  hasCalls:        false
465  maxCallFrameSize: 0
466  hasOpaqueSPAdjustment: false
467  hasVAStart:      false
468  hasMustTailInVarArgFunc: false
469body:             |
470  bb.0.main_body:
471    liveins: $vgpr0
472
473    $sgpr0_sgpr1 = COPY $exec
474    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
475    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
476    $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
477    $sgpr2_sgpr3 = S_OR_B64 killed $sgpr2_sgpr3, 1, implicit-def $scc
478    $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
479    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
480    SI_MASK_BRANCH %bb.2, implicit $exec
481    S_BRANCH %bb.1
482
483  bb.1.if:
484    liveins: $sgpr0_sgpr1
485
486    $sgpr7 = S_MOV_B32 61440
487    $sgpr6 = S_MOV_B32 -1
488    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
489
490  bb.2.end:
491    liveins: $vgpr0, $sgpr0_sgpr1
492
493    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
494    $sgpr0 = S_MOV_B32 0
495    $sgpr1 = S_MOV_B32 1
496    $sgpr2 = S_MOV_B32 -1
497    $sgpr3 = S_MOV_B32 61440
498    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
499    S_ENDPGM
500
501...
502---
503# CHECK-LABEL: name: optimize_if_and_saveexec_xor_live_out_setexec{{$}}
504# CHECK: $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
505# CHECK-NEXT: $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
506# CHECK-NEXT: $exec = COPY $sgpr2_sgpr3
507# CHECK-NEXT: SI_MASK_BRANCH
508name:            optimize_if_and_saveexec_xor_live_out_setexec
509alignment:       0
510exposesReturnsTwice: false
511legalized:       false
512regBankSelected: false
513selected:        false
514tracksRegLiveness: true
515liveins:
516  - { reg: '$vgpr0' }
517frameInfo:
518  isFrameAddressTaken: false
519  isReturnAddressTaken: false
520  hasStackMap:     false
521  hasPatchPoint:   false
522  stackSize:       0
523  offsetAdjustment: 0
524  maxAlignment:    0
525  adjustsStack:    false
526  hasCalls:        false
527  maxCallFrameSize: 0
528  hasOpaqueSPAdjustment: false
529  hasVAStart:      false
530  hasMustTailInVarArgFunc: false
531body:             |
532  bb.0.main_body:
533    liveins: $vgpr0
534
535    $sgpr0_sgpr1 = COPY $exec
536    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
537    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
538    $sgpr2_sgpr3 = S_AND_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
539    $sgpr0_sgpr1 = S_XOR_B64 $sgpr2_sgpr3, killed $sgpr0_sgpr1, implicit-def $scc
540    $exec = S_MOV_B64_term $sgpr2_sgpr3
541    SI_MASK_BRANCH %bb.2, implicit $exec
542    S_BRANCH %bb.1
543
544  bb.1.if:
545    liveins: $sgpr0_sgpr1, $sgpr2_sgpr3
546    S_SLEEP 0, implicit $sgpr2_sgpr3
547    $sgpr7 = S_MOV_B32 61440
548    $sgpr6 = S_MOV_B32 -1
549    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
550
551  bb.2.end:
552    liveins: $vgpr0, $sgpr0_sgpr1
553
554    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
555    $sgpr3 = S_MOV_B32 61440
556    $sgpr2 = S_MOV_B32 -1
557    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
558    S_ENDPGM
559
560...
561
562# CHECK-LABEL: name: optimize_if_unknown_saveexec{{$}}
563# CHECK: $sgpr0_sgpr1 = COPY $exec
564# CHECK: $sgpr2_sgpr3 = S_LSHR_B64 $sgpr0_sgpr1, killed $vcc_lo, implicit-def $scc
565# CHECK-NEXT: $exec = COPY killed $sgpr2_sgpr3
566# CHECK-NEXT: SI_MASK_BRANCH %bb.2, implicit $exec
567
568name:            optimize_if_unknown_saveexec
569alignment:       0
570exposesReturnsTwice: false
571legalized:       false
572regBankSelected: false
573selected:        false
574tracksRegLiveness: true
575liveins:
576  - { reg: '$vgpr0' }
577frameInfo:
578  isFrameAddressTaken: false
579  isReturnAddressTaken: false
580  hasStackMap:     false
581  hasPatchPoint:   false
582  stackSize:       0
583  offsetAdjustment: 0
584  maxAlignment:    0
585  adjustsStack:    false
586  hasCalls:        false
587  maxCallFrameSize: 0
588  hasOpaqueSPAdjustment: false
589  hasVAStart:      false
590  hasMustTailInVarArgFunc: false
591body:             |
592  bb.0.main_body:
593    liveins: $vgpr0
594
595    $sgpr0_sgpr1 = COPY $exec
596    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
597    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
598    $sgpr2_sgpr3 = S_LSHR_B64 $sgpr0_sgpr1, killed $vcc_lo, implicit-def $scc
599    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
600    SI_MASK_BRANCH %bb.2, implicit $exec
601    S_BRANCH %bb.1
602
603  bb.1.if:
604    liveins: $sgpr0_sgpr1
605
606    $sgpr7 = S_MOV_B32 61440
607    $sgpr6 = S_MOV_B32 -1
608    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
609
610  bb.2.end:
611    liveins: $vgpr0, $sgpr0_sgpr1
612
613    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
614    $sgpr3 = S_MOV_B32 61440
615    $sgpr2 = S_MOV_B32 -1
616    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
617    S_ENDPGM
618
619...
620---
621# CHECK-LABEL: name: optimize_if_andn2_saveexec{{$}}
622# CHECK: $sgpr0_sgpr1 = S_ANDN2_SAVEEXEC_B64 $vcc, implicit-def $exec, implicit-def $scc, implicit $exec
623# CHECK-NEXT: SI_MASK_BRANCH
624
625name:            optimize_if_andn2_saveexec
626alignment:       0
627exposesReturnsTwice: false
628legalized:       false
629regBankSelected: false
630selected:        false
631tracksRegLiveness: true
632liveins:
633  - { reg: '$vgpr0' }
634frameInfo:
635  isFrameAddressTaken: false
636  isReturnAddressTaken: false
637  hasStackMap:     false
638  hasPatchPoint:   false
639  stackSize:       0
640  offsetAdjustment: 0
641  maxAlignment:    0
642  adjustsStack:    false
643  hasCalls:        false
644  maxCallFrameSize: 0
645  hasOpaqueSPAdjustment: false
646  hasVAStart:      false
647  hasMustTailInVarArgFunc: false
648body:             |
649  bb.0.main_body:
650    liveins: $vgpr0
651
652    $sgpr0_sgpr1 = COPY $exec
653    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
654    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
655    $sgpr2_sgpr3 = S_ANDN2_B64 $sgpr0_sgpr1, killed $vcc, implicit-def $scc
656    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
657    SI_MASK_BRANCH %bb.2, implicit $exec
658    S_BRANCH %bb.1
659
660  bb.1.if:
661    liveins: $sgpr0_sgpr1
662
663    $sgpr7 = S_MOV_B32 61440
664    $sgpr6 = S_MOV_B32 -1
665    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
666
667  bb.2.end:
668    liveins: $vgpr0, $sgpr0_sgpr1
669
670    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
671    $sgpr3 = S_MOV_B32 61440
672    $sgpr2 = S_MOV_B32 -1
673    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
674    S_ENDPGM
675
676...
677---
678# CHECK-LABEL: name: optimize_if_andn2_saveexec_no_commute{{$}}
679# CHECK: $sgpr2_sgpr3 = S_ANDN2_B64 killed $vcc, $sgpr0_sgpr1, implicit-def $scc
680# CHECK-NEXT: $exec = COPY killed $sgpr2_sgpr3
681# CHECK-NEXT: SI_MASK_BRANCH %bb.2, implicit $exec
682name:            optimize_if_andn2_saveexec_no_commute
683alignment:       0
684exposesReturnsTwice: false
685legalized:       false
686regBankSelected: false
687selected:        false
688tracksRegLiveness: true
689liveins:
690  - { reg: '$vgpr0' }
691frameInfo:
692  isFrameAddressTaken: false
693  isReturnAddressTaken: false
694  hasStackMap:     false
695  hasPatchPoint:   false
696  stackSize:       0
697  offsetAdjustment: 0
698  maxAlignment:    0
699  adjustsStack:    false
700  hasCalls:        false
701  maxCallFrameSize: 0
702  hasOpaqueSPAdjustment: false
703  hasVAStart:      false
704  hasMustTailInVarArgFunc: false
705body:             |
706  bb.0.main_body:
707    liveins: $vgpr0
708
709    $sgpr0_sgpr1 = COPY $exec
710    $vcc = V_CMP_EQ_I32_e64 0, killed $vgpr0, implicit $exec
711    $vgpr0 = V_MOV_B32_e32 4, implicit $exec
712    $sgpr2_sgpr3 = S_ANDN2_B64 killed $vcc, $sgpr0_sgpr1, implicit-def $scc
713    $exec = S_MOV_B64_term killed $sgpr2_sgpr3
714    SI_MASK_BRANCH %bb.2, implicit $exec
715    S_BRANCH %bb.1
716
717  bb.1.if:
718    liveins: $sgpr0_sgpr1
719
720    $sgpr7 = S_MOV_B32 61440
721    $sgpr6 = S_MOV_B32 -1
722    $vgpr0 = BUFFER_LOAD_DWORD_OFFSET $sgpr4_sgpr5_sgpr6_sgpr7, 0, 0, 0, 0, 0, implicit $exec :: (volatile load 4 from `i32 addrspace(1)* undef`)
723
724  bb.2.end:
725    liveins: $vgpr0, $sgpr0_sgpr1
726
727    $exec = S_OR_B64 $exec, killed $sgpr0_sgpr1, implicit-def $scc
728    $sgpr3 = S_MOV_B32 61440
729    $sgpr2 = S_MOV_B32 -1
730    BUFFER_STORE_DWORD_OFFSET killed $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, 0, implicit $exec :: (store 4 into `i32 addrspace(1)* undef`)
731    S_ENDPGM
732
733...
734