1; RUN: llc -march=amdgcn -mcpu=tahiti -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,ALL %s
2; RUN: llc -march=amdgcn -mcpu=tahiti -verify-machineinstrs -amdgpu-opt-exec-mask-pre-ra=0 < %s | FileCheck -enable-var-scope -check-prefixes=DISABLED,ALL %s
3
4; ALL-LABEL: {{^}}simple_nested_if:
5; GCN:      s_and_saveexec_b64 [[SAVEEXEC:s\[[0-9:]+\]]]
6; GCN-NEXT: s_cbranch_execz [[ENDIF:BB[0-9_]+]]
7; GCN:      s_and_b64 exec, exec, vcc
8; GCN-NEXT: s_cbranch_execz [[ENDIF]]
9; GCN-NEXT: ; %bb.{{[0-9]+}}:
10; GCN:      store_dword
11; GCN-NEXT: {{^}}[[ENDIF]]:
12; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC]]
13; GCN: ds_write_b32
14; GCN: s_endpgm
15
16
17; DISABLED: s_or_b64 exec, exec
18; DISABLED: s_or_b64 exec, exec
19define amdgpu_kernel void @simple_nested_if(i32 addrspace(1)* nocapture %arg) {
20bb:
21  %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()
22  %tmp1 = icmp ugt i32 %tmp, 1
23  br i1 %tmp1, label %bb.outer.then, label %bb.outer.end
24
25bb.outer.then:                                    ; preds = %bb
26  %tmp4 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp
27  store i32 0, i32 addrspace(1)* %tmp4, align 4
28  %tmp5 = icmp eq i32 %tmp, 2
29  br i1 %tmp5, label %bb.outer.end, label %bb.inner.then
30
31bb.inner.then:                                    ; preds = %bb.outer.then
32  %tmp7 = add i32 %tmp, 1
33  %tmp9 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp7
34  store i32 1, i32 addrspace(1)* %tmp9, align 4
35  br label %bb.outer.end
36
37bb.outer.end:                                     ; preds = %bb.outer.then, %bb.inner.then, %bb
38  store i32 3, i32 addrspace(3)* null
39  ret void
40}
41
42; ALL-LABEL: {{^}}uncollapsable_nested_if:
43; GCN:      s_and_saveexec_b64 [[SAVEEXEC_OUTER:s\[[0-9:]+\]]]
44; GCN-NEXT: s_cbranch_execz [[ENDIF_OUTER:BB[0-9_]+]]
45; GCN:      s_and_saveexec_b64 [[SAVEEXEC_INNER:s\[[0-9:]+\]]]
46; GCN-NEXT: s_cbranch_execz [[ENDIF_INNER:BB[0-9_]+]]
47; GCN-NEXT: ; %bb.{{[0-9]+}}:
48; GCN:      store_dword
49; GCN-NEXT: {{^}}[[ENDIF_INNER]]:
50; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC_INNER]]
51; GCN:      store_dword
52; GCN-NEXT: {{^}}[[ENDIF_OUTER]]:
53; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC_OUTER]]
54; GCN: ds_write_b32
55; GCN: s_endpgm
56define amdgpu_kernel void @uncollapsable_nested_if(i32 addrspace(1)* nocapture %arg) {
57bb:
58  %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()
59  %tmp1 = icmp ugt i32 %tmp, 1
60  br i1 %tmp1, label %bb.outer.then, label %bb.outer.end
61
62bb.outer.then:                                    ; preds = %bb
63  %tmp4 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp
64  store i32 0, i32 addrspace(1)* %tmp4, align 4
65  %tmp5 = icmp eq i32 %tmp, 2
66  br i1 %tmp5, label %bb.inner.end, label %bb.inner.then
67
68bb.inner.then:                                    ; preds = %bb.outer.then
69  %tmp7 = add i32 %tmp, 1
70  %tmp8 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp7
71  store i32 1, i32 addrspace(1)* %tmp8, align 4
72  br label %bb.inner.end
73
74bb.inner.end:                                     ; preds = %bb.inner.then, %bb.outer.then
75  %tmp9 = add i32 %tmp, 2
76  %tmp10 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp9
77  store i32 2, i32 addrspace(1)* %tmp10, align 4
78  br label %bb.outer.end
79
80bb.outer.end:                                     ; preds = %bb.inner.then, %bb
81  store i32 3, i32 addrspace(3)* null
82  ret void
83}
84
85; ALL-LABEL: {{^}}nested_if_if_else:
86; GCN:      s_and_saveexec_b64 [[SAVEEXEC_OUTER:s\[[0-9:]+\]]]
87; GCN-NEXT: s_cbranch_execz [[ENDIF_OUTER:BB[0-9_]+]]
88; GCN:      s_and_saveexec_b64 [[SAVEEXEC_INNER:s\[[0-9:]+\]]]
89; GCN-NEXT: s_xor_b64 [[SAVEEXEC_INNER2:s\[[0-9:]+\]]], exec, [[SAVEEXEC_INNER]]
90; GCN-NEXT: s_cbranch_execz [[THEN_INNER:BB[0-9_]+]]
91; GCN-NEXT: ; %bb.{{[0-9]+}}:
92; GCN:      store_dword
93; GCN-NEXT: {{^}}[[THEN_INNER]]:
94; GCN-NEXT: s_or_saveexec_b64 [[SAVEEXEC_INNER3:s\[[0-9:]+\]]], [[SAVEEXEC_INNER2]]
95; GCN-NEXT: s_xor_b64 exec, exec, [[SAVEEXEC_INNER3]]
96; GCN-NEXT: s_cbranch_execz [[ENDIF_OUTER]]
97; GCN:      store_dword
98; GCN-NEXT: {{^}}[[ENDIF_OUTER]]:
99; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC_OUTER]]
100; GCN: ds_write_b32
101; GCN: s_endpgm
102define amdgpu_kernel void @nested_if_if_else(i32 addrspace(1)* nocapture %arg) {
103bb:
104  %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()
105  %tmp1 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp
106  store i32 0, i32 addrspace(1)* %tmp1, align 4
107  %tmp2 = icmp ugt i32 %tmp, 1
108  br i1 %tmp2, label %bb.outer.then, label %bb.outer.end
109
110bb.outer.then:                                       ; preds = %bb
111  %tmp5 = icmp eq i32 %tmp, 2
112  br i1 %tmp5, label %bb.then, label %bb.else
113
114bb.then:                                             ; preds = %bb.outer.then
115  %tmp3 = add i32 %tmp, 1
116  %tmp4 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp3
117  store i32 1, i32 addrspace(1)* %tmp4, align 4
118  br label %bb.outer.end
119
120bb.else:                                             ; preds = %bb.outer.then
121  %tmp7 = add i32 %tmp, 2
122  %tmp9 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp7
123  store i32 2, i32 addrspace(1)* %tmp9, align 4
124  br label %bb.outer.end
125
126bb.outer.end:                                        ; preds = %bb, %bb.then, %bb.else
127  store i32 3, i32 addrspace(3)* null
128  ret void
129}
130
131; ALL-LABEL: {{^}}nested_if_else_if:
132; GCN:      s_and_saveexec_b64 [[SAVEEXEC_OUTER:s\[[0-9:]+\]]]
133; GCN-NEXT: s_xor_b64 [[SAVEEXEC_OUTER2:s\[[0-9:]+\]]], exec, [[SAVEEXEC_OUTER]]
134; GCN-NEXT: s_cbranch_execz [[THEN_OUTER:BB[0-9_]+]]
135; GCN-NEXT: ; %bb.{{[0-9]+}}:
136; GCN:      store_dword
137; GCN-NEXT: s_and_saveexec_b64 [[SAVEEXEC_INNER_IF_OUTER_ELSE:s\[[0-9:]+\]]]
138; GCN-NEXT: s_cbranch_execz [[THEN_OUTER_FLOW:BB[0-9_]+]]
139; GCN-NEXT: ; %bb.{{[0-9]+}}:
140; GCN:      store_dword
141; GCN-NEXT: {{^}}[[THEN_OUTER_FLOW]]:
142; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC_INNER_IF_OUTER_ELSE]]
143; GCN-NEXT: {{^}}[[THEN_OUTER]]:
144; GCN-NEXT: s_or_saveexec_b64 [[SAVEEXEC_OUTER3:s\[[0-9:]+\]]], [[SAVEEXEC_OUTER2]]
145; GCN-NEXT: s_xor_b64 exec, exec, [[SAVEEXEC_OUTER3]]
146; GCN-NEXT: s_cbranch_execz [[ENDIF_OUTER:BB[0-9_]+]]
147; GCN-NEXT: ; %bb.{{[0-9]+}}:
148; GCN:      store_dword
149; GCN-NEXT: s_and_saveexec_b64 [[SAVEEXEC_INNER_IF_OUTER_THEN:s\[[0-9:]+\]]]
150; GCN-NEXT: s_cbranch_execz [[FLOW1:BB[0-9_]+]]
151; GCN-NEXT: ; %bb.{{[0-9]+}}:
152; GCN:      store_dword
153; GCN-NEXT: [[FLOW1]]:
154; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC_INNER_IF_OUTER_THEN]]
155; GCN-NEXT: {{^}}[[ENDIF_OUTER]]:
156; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC_OUTER]]
157; GCN: ds_write_b32
158; GCN: s_endpgm
159define amdgpu_kernel void @nested_if_else_if(i32 addrspace(1)* nocapture %arg) {
160bb:
161  %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()
162  %tmp1 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp
163  store i32 0, i32 addrspace(1)* %tmp1, align 4
164  %cc1 = icmp ugt i32 %tmp, 1
165  br i1 %cc1, label %bb.outer.then, label %bb.outer.else
166
167bb.outer.then:
168  %tmp2 = getelementptr inbounds i32, i32 addrspace(1)* %tmp1, i32 1
169  store i32 1, i32 addrspace(1)* %tmp2, align 4
170  %cc2 = icmp eq i32 %tmp, 2
171  br i1 %cc2, label %bb.inner.then, label %bb.outer.end
172
173bb.inner.then:
174  %tmp3 = getelementptr inbounds i32, i32 addrspace(1)* %tmp1, i32 2
175  store i32 2, i32 addrspace(1)* %tmp3, align 4
176  br label %bb.outer.end
177
178bb.outer.else:
179  %tmp4 = getelementptr inbounds i32, i32 addrspace(1)* %tmp1, i32 3
180  store i32 3, i32 addrspace(1)* %tmp4, align 4
181  %cc3 = icmp eq i32 %tmp, 2
182  br i1 %cc3, label %bb.inner.then2, label %bb.outer.end
183
184bb.inner.then2:
185  %tmp5 = getelementptr inbounds i32, i32 addrspace(1)* %tmp1, i32 4
186  store i32 4, i32 addrspace(1)* %tmp5, align 4
187  br label %bb.outer.end
188
189bb.outer.end:
190  store i32 3, i32 addrspace(3)* null
191  ret void
192}
193
194; ALL-LABEL: {{^}}s_endpgm_unsafe_barrier:
195; GCN:      s_and_saveexec_b64 [[SAVEEXEC:s\[[0-9:]+\]]]
196; GCN-NEXT: s_cbranch_execz [[ENDIF:BB[0-9_]+]]
197; GCN-NEXT: ; %bb.{{[0-9]+}}:
198; GCN:      store_dword
199; GCN-NEXT: {{^}}[[ENDIF]]:
200; GCN-NEXT: s_or_b64 exec, exec, [[SAVEEXEC]]
201; GCN:      s_barrier
202; GCN-NEXT: s_endpgm
203define amdgpu_kernel void @s_endpgm_unsafe_barrier(i32 addrspace(1)* nocapture %arg) {
204bb:
205  %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()
206  %tmp1 = icmp ugt i32 %tmp, 1
207  br i1 %tmp1, label %bb.then, label %bb.end
208
209bb.then:                                          ; preds = %bb
210  %tmp4 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i32 %tmp
211  store i32 0, i32 addrspace(1)* %tmp4, align 4
212  br label %bb.end
213
214bb.end:                                           ; preds = %bb.then, %bb
215  call void @llvm.amdgcn.s.barrier()
216  ret void
217}
218
219; Make sure scc liveness is updated if sor_b64 is removed
220; ALL-LABEL: {{^}}scc_liveness:
221
222; GCN: %bb10
223; GCN: s_or_b64 exec, exec, s{{\[[0-9]+:[0-9]+\]}}
224; GCN: s_andn2_b64
225; GCN-NEXT: s_cbranch_execz
226
227; GCN: [[BB1_LOOP:BB[0-9]+_[0-9]+]]:
228; GCN: s_andn2_b64 exec, exec,
229; GCN-NEXT: s_cbranch_execnz [[BB1_LOOP]]
230
231; GCN: buffer_load_dword v{{[0-9]+}}, v{{[0-9]+}}, s{{\[[0-9]+:[0-9]+\]}}, s{{[0-9]+}} offen
232; GCN: s_and_b64 exec, exec, {{vcc|s\[[0-9:]+\]}}
233
234; GCN-NOT: s_or_b64 exec, exec
235
236; GCN: s_or_b64 exec, exec, s{{\[[0-9]+:[0-9]+\]}}
237; GCN: buffer_store_dword
238; GCN: buffer_store_dword
239; GCN: buffer_store_dword
240; GCN: buffer_store_dword
241; GCN: s_setpc_b64
242define void @scc_liveness(i32 %arg) local_unnamed_addr #0 {
243bb:
244  br label %bb1
245
246bb1:                                              ; preds = %Flow1, %bb1, %bb
247  %tmp = icmp slt i32 %arg, 519
248  br i1 %tmp, label %bb2, label %bb1
249
250bb2:                                              ; preds = %bb1
251  %tmp3 = icmp eq i32 %arg, 0
252  br i1 %tmp3, label %bb4, label %bb10
253
254bb4:                                              ; preds = %bb2
255  %tmp6 = load float, float addrspace(5)* undef
256  %tmp7 = fcmp olt float %tmp6, 0.0
257  br i1 %tmp7, label %bb8, label %Flow
258
259bb8:                                              ; preds = %bb4
260  %tmp9 = insertelement <4 x float> undef, float 0.0, i32 1
261  br label %Flow
262
263Flow:                                             ; preds = %bb8, %bb4
264  %tmp8 = phi <4 x float> [ %tmp9, %bb8 ], [ zeroinitializer, %bb4 ]
265  br label %bb10
266
267bb10:                                             ; preds = %Flow, %bb2
268  %tmp11 = phi <4 x float> [ zeroinitializer, %bb2 ], [ %tmp8, %Flow ]
269  br i1 %tmp3, label %bb12, label %Flow1
270
271Flow1:                                            ; preds = %bb10
272  br label %bb1
273
274bb12:                                             ; preds = %bb10
275  store volatile <4 x float> %tmp11, <4 x float> addrspace(5)* undef, align 16
276  ret void
277}
278
279declare i32 @llvm.amdgcn.workitem.id.x() #0
280declare void @llvm.amdgcn.s.barrier() #1
281
282attributes #0 = { nounwind readnone speculatable }
283attributes #1 = { nounwind convergent }
284attributes #2 = { nounwind }
285