754 lines · plain
1; RUN: opt -mtriple=amdgcn-- -mcpu=gfx600 -S -lowerswitch -amdgpu-unify-divergent-exit-nodes -verify -structurizecfg -verify -si-annotate-control-flow -simplifycfg-require-and-preserve-domtree=1 %s | FileCheck -check-prefix=IR %s2; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1100 -mattr=+wavefrontsize64 -S -lowerswitch -amdgpu-unify-divergent-exit-nodes -verify -structurizecfg -verify -si-annotate-control-flow -simplifycfg-require-and-preserve-domtree=1 %s | FileCheck -check-prefix=IR %s3; RUN: llc -mtriple=amdgcn -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck -check-prefix=GCN %s4 5; Add an extra verifier runs. There were some cases where invalid IR6; was produced but happened to be fixed by the later passes.7 8; Make sure divergent control flow with multiple exits from a region9; is properly handled. UnifyFunctionExitNodes should be run before10; StructurizeCFG.11 12; IR-LABEL: @multi_divergent_region_exit_ret_ret(13; IR: %0 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %Pivot)14; IR: %1 = extractvalue { i1, i64 } %0, 015; IR: %2 = extractvalue { i1, i64 } %0, 116; IR: br i1 %1, label %LeafBlock1, label %Flow17 18; IR: Flow:19; IR: %3 = phi i1 [ true, %LeafBlock1 ], [ false, %entry ]20; IR: %4 = phi i1 [ %SwitchLeaf2, %LeafBlock1 ], [ false, %entry ]21; IR: %5 = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %2)22; IR: %6 = extractvalue { i1, i64 } %5, 023; IR: %7 = extractvalue { i1, i64 } %5, 124; IR: br i1 %6, label %LeafBlock, label %Flow125 26; IR: LeafBlock:27; IR: br label %Flow128 29; IR: LeafBlock1:30; IR: br label %Flow{{$}}31 32; IR: Flow2:33; IR: %8 = phi i1 [ false, %exit1 ], [ %12, %Flow1 ]34; IR: call void @llvm.amdgcn.end.cf.i64(i64 %16)35; IR: %9 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %8)36; IR: %10 = extractvalue { i1, i64 } %9, 037; IR: %11 = extractvalue { i1, i64 } %9, 138; IR: br i1 %10, label %exit0, label %UnifiedReturnBlock39 40; IR: exit0:41; IR: store volatile i32 9, ptr addrspace(1) poison42; IR: br label %UnifiedReturnBlock43 44; IR: Flow1:45; IR: %12 = phi i1 [ %SwitchLeaf, %LeafBlock ], [ %3, %Flow ]46; IR: %13 = phi i1 [ %SwitchLeaf.inv, %LeafBlock ], [ %4, %Flow ]47; IR: call void @llvm.amdgcn.end.cf.i64(i64 %7)48; IR: %14 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %13)49; IR: %15 = extractvalue { i1, i64 } %14, 050; IR: %16 = extractvalue { i1, i64 } %14, 151; IR: br i1 %15, label %exit1, label %Flow252 53; IR: exit1:54; IR: store volatile i32 17, ptr addrspace(3) poison55; IR: br label %Flow256 57; IR: UnifiedReturnBlock:58; IR: call void @llvm.amdgcn.end.cf.i64(i64 %11)59; IR: ret void60 61 62; GCN-LABEL: {{^}}multi_divergent_region_exit_ret_ret:63 64; GCN-DAG: s_mov_b64 [[EXIT1:s\[[0-9]+:[0-9]+\]]], 065; GCN-DAG: v_cmp_lt_i32_e32 vcc, 1,66; GCN-DAG: s_mov_b64 [[EXIT0:s\[[0-9]+:[0-9]+\]]], 067; GCN-DAG: s_and_saveexec_b6468; GCN-DAG: s_xor_b6469 70; GCN: ; %LeafBlock171; GCN-NEXT: s_mov_b64 [[EXIT0]], exec72; GCN-NEXT: v_cmp_ne_u32_e32 vcc, 2,73; GCN-NEXT: s_and_b64 [[EXIT1]], vcc, exec74 75; GCN: ; %Flow76; GCN-NEXT: s_andn2_saveexec_b6477 78; GCN: ; %LeafBlock79; GCN-DAG: v_cmp_eq_u32_e32 vcc, 1,80; GCN-DAG: v_cmp_ne_u32_e64 [[INV:s\[[0-9]+:[0-9]+\]]], 1,81; GCN-DAG: s_andn2_b64 [[EXIT0]], [[EXIT0]], exec82; GCN-DAG: s_andn2_b64 [[EXIT1]], [[EXIT1]], exec83; GCN-DAG: s_and_b64 [[TMP0:s\[[0-9]+:[0-9]+\]]], vcc, exec84; GCN-DAG: s_and_b64 [[TMP1:s\[[0-9]+:[0-9]+\]]], [[INV]], exec85; GCN-DAG: s_or_b64 [[EXIT0]], [[EXIT0]], [[TMP0]]86; GCN-DAG: s_or_b64 [[EXIT1]], [[EXIT1]], [[TMP1]]87 88; GCN: ; %Flow489; GCN-NEXT: s_or_b64 exec, exec,90; GCN-NEXT: s_and_saveexec_b64 {{s\[[0-9]+:[0-9]+\]}}, [[EXIT1]]91; GCN-NEXT: s_xor_b6492 93; GCN: ; %exit194; GCN-DAG: ds_write_b3295; GCN-DAG: s_andn2_b64 [[EXIT0]], [[EXIT0]], exec96 97; GCN: ; %Flow598; GCN-NEXT: s_or_b64 exec, exec,99; GCN-NEXT: s_and_saveexec_b64 {{s\[[0-9]+:[0-9]+\]}}, [[EXIT0]]100 101; GCN: ; %exit0102; GCN: buffer_store_dword103 104; GCN: ; %UnifiedReturnBlock105; GCN-NEXT: s_endpgm106define amdgpu_kernel void @multi_divergent_region_exit_ret_ret(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2) #0 {107entry:108 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1109 %tmp1 = add i32 0, %tmp110 %tmp2 = zext i32 %tmp1 to i64111 %tmp3 = add i64 0, %tmp2112 %tmp4 = shl i64 %tmp3, 32113 %tmp5 = ashr exact i64 %tmp4, 32114 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5115 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4116 %tmp8 = sext i32 %tmp7 to i64117 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8118 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4119 %tmp13 = zext i32 %tmp10 to i64120 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13121 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16122 %Pivot = icmp slt i32 %tmp16, 2123 br i1 %Pivot, label %LeafBlock, label %LeafBlock1124 125LeafBlock: ; preds = %entry126 %SwitchLeaf = icmp eq i32 %tmp16, 1127 br i1 %SwitchLeaf, label %exit0, label %exit1128 129LeafBlock1: ; preds = %entry130 %SwitchLeaf2 = icmp eq i32 %tmp16, 2131 br i1 %SwitchLeaf2, label %exit0, label %exit1132 133exit0: ; preds = %LeafBlock, %LeafBlock1134 store volatile i32 9, ptr addrspace(1) poison135 ret void136 137exit1: ; preds = %LeafBlock, %LeafBlock1138 store volatile i32 17, ptr addrspace(3) poison139 ret void140}141 142; IR-LABEL: @multi_divergent_region_exit_unreachable_unreachable(143; IR: %0 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %Pivot)144 145; IR: %5 = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %2)146 147; IR: %8 = phi i1 [ false, %exit1 ], [ %12, %Flow1 ]148; IR: call void @llvm.amdgcn.end.cf.i64(i64 %16)149; IR: %9 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %8)150; IR: br i1 %10, label %exit0, label %UnifiedUnreachableBlock151 152 153; IR: UnifiedUnreachableBlock:154; IR-NEXT: unreachable155 156 157; FIXME: Probably should insert an s_endpgm anyway.158; GCN-LABEL: {{^}}multi_divergent_region_exit_unreachable_unreachable:159; GCN: ; %UnifiedUnreachableBlock160; GCN-NEXT: .Lfunc_end161define amdgpu_kernel void @multi_divergent_region_exit_unreachable_unreachable(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2) #0 {162entry:163 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1164 %tmp1 = add i32 0, %tmp165 %tmp2 = zext i32 %tmp1 to i64166 %tmp3 = add i64 0, %tmp2167 %tmp4 = shl i64 %tmp3, 32168 %tmp5 = ashr exact i64 %tmp4, 32169 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5170 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4171 %tmp8 = sext i32 %tmp7 to i64172 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8173 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4174 %tmp13 = zext i32 %tmp10 to i64175 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13176 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16177 %Pivot = icmp slt i32 %tmp16, 2178 br i1 %Pivot, label %LeafBlock, label %LeafBlock1179 180LeafBlock: ; preds = %entry181 %SwitchLeaf = icmp eq i32 %tmp16, 1182 br i1 %SwitchLeaf, label %exit0, label %exit1183 184LeafBlock1: ; preds = %entry185 %SwitchLeaf2 = icmp eq i32 %tmp16, 2186 br i1 %SwitchLeaf2, label %exit0, label %exit1187 188exit0: ; preds = %LeafBlock, %LeafBlock1189 store volatile i32 9, ptr addrspace(1) poison190 unreachable191 192exit1: ; preds = %LeafBlock, %LeafBlock1193 store volatile i32 17, ptr addrspace(3) poison194 unreachable195}196 197; IR-LABEL: @multi_exit_region_divergent_ret_uniform_ret(198; IR: %divergent.cond0 = icmp sge i32 %tmp16, 2199; IR: llvm.amdgcn.if200; IR: br i1201 202; IR: {{^}}Flow:203; IR: %3 = phi i1 [ true, %LeafBlock1 ], [ false, %entry ]204; IR: %4 = phi i1 [ %uniform.cond0, %LeafBlock1 ], [ false, %entry ]205; IR: %5 = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %2)206; IR: br i1 %6, label %LeafBlock, label %Flow1207 208; IR: {{^}}LeafBlock:209; IR: %divergent.cond1 = icmp eq i32 %tmp16, 1210; IR: br label %Flow1211 212; IR: LeafBlock1:213; IR: %uniform.cond0 = icmp ne i32 %arg3, 2214; IR: br label %Flow215 216; IR: Flow2:217; IR: %8 = phi i1 [ false, %exit1 ], [ %12, %Flow1 ]218; IR: call void @llvm.amdgcn.end.cf.i64(i64 %16)219; IR: %9 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %8)220; IR: br i1 %10, label %exit0, label %UnifiedReturnBlock221 222; IR: exit0:223; IR: store volatile i32 9, ptr addrspace(1) poison224; IR: br label %UnifiedReturnBlock225 226; IR: {{^}}Flow1:227; IR: %12 = phi i1 [ %divergent.cond1, %LeafBlock ], [ %3, %Flow ]228; IR: %13 = phi i1 [ %divergent.cond1.inv, %LeafBlock ], [ %4, %Flow ]229; IR: call void @llvm.amdgcn.end.cf.i64(i64 %7)230; IR: %14 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %13)231; IR: %15 = extractvalue { i1, i64 } %14, 0232; IR: %16 = extractvalue { i1, i64 } %14, 1233; IR: br i1 %15, label %exit1, label %Flow2234 235; IR: exit1:236; IR: store volatile i32 17, ptr addrspace(3) poison237; IR: br label %Flow2238 239; IR: UnifiedReturnBlock:240; IR: call void @llvm.amdgcn.end.cf.i64(i64 %11)241; IR: ret void242define amdgpu_kernel void @multi_exit_region_divergent_ret_uniform_ret(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2, i32 %arg3) #0 {243entry:244 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1245 %tmp1 = add i32 0, %tmp246 %tmp2 = zext i32 %tmp1 to i64247 %tmp3 = add i64 0, %tmp2248 %tmp4 = shl i64 %tmp3, 32249 %tmp5 = ashr exact i64 %tmp4, 32250 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5251 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4252 %tmp8 = sext i32 %tmp7 to i64253 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8254 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4255 %tmp13 = zext i32 %tmp10 to i64256 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13257 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16258 %divergent.cond0 = icmp slt i32 %tmp16, 2259 br i1 %divergent.cond0, label %LeafBlock, label %LeafBlock1260 261LeafBlock: ; preds = %entry262 %divergent.cond1 = icmp eq i32 %tmp16, 1263 br i1 %divergent.cond1, label %exit0, label %exit1264 265LeafBlock1: ; preds = %entry266 %uniform.cond0 = icmp eq i32 %arg3, 2267 br i1 %uniform.cond0, label %exit0, label %exit1268 269exit0: ; preds = %LeafBlock, %LeafBlock1270 store volatile i32 9, ptr addrspace(1) poison271 ret void272 273exit1: ; preds = %LeafBlock, %LeafBlock1274 store volatile i32 17, ptr addrspace(3) poison275 ret void276}277 278; IR-LABEL: @multi_exit_region_uniform_ret_divergent_ret(279; IR: %0 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %Pivot)280; IR: br i1 %1, label %LeafBlock1, label %Flow281 282; IR: Flow:283; IR: %3 = phi i1 [ true, %LeafBlock1 ], [ false, %entry ]284; IR: %4 = phi i1 [ %SwitchLeaf2, %LeafBlock1 ], [ false, %entry ]285; IR: %5 = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %2)286 287; IR: %8 = phi i1 [ false, %exit1 ], [ %12, %Flow1 ]288; IR: call void @llvm.amdgcn.end.cf.i64(i64 %16)289; IR: %9 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %8)290 291define amdgpu_kernel void @multi_exit_region_uniform_ret_divergent_ret(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2, i32 %arg3) #0 {292entry:293 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1294 %tmp1 = add i32 0, %tmp295 %tmp2 = zext i32 %tmp1 to i64296 %tmp3 = add i64 0, %tmp2297 %tmp4 = shl i64 %tmp3, 32298 %tmp5 = ashr exact i64 %tmp4, 32299 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5300 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4301 %tmp8 = sext i32 %tmp7 to i64302 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8303 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4304 %tmp13 = zext i32 %tmp10 to i64305 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13306 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16307 %Pivot = icmp slt i32 %tmp16, 2308 br i1 %Pivot, label %LeafBlock, label %LeafBlock1309 310LeafBlock: ; preds = %entry311 %SwitchLeaf = icmp eq i32 %arg3, 1312 br i1 %SwitchLeaf, label %exit0, label %exit1313 314LeafBlock1: ; preds = %entry315 %SwitchLeaf2 = icmp eq i32 %tmp16, 2316 br i1 %SwitchLeaf2, label %exit0, label %exit1317 318exit0: ; preds = %LeafBlock, %LeafBlock1319 store volatile i32 9, ptr addrspace(1) poison320 ret void321 322exit1: ; preds = %LeafBlock, %LeafBlock1323 store volatile i32 17, ptr addrspace(3) poison324 ret void325}326 327; IR-LABEL: @multi_divergent_region_exit_ret_ret_return_value(328; IR: Flow2:329; IR: %8 = phi i1 [ false, %exit1 ], [ %12, %Flow1 ]330; IR: call void @llvm.amdgcn.end.cf.i64(i64 %16)331 332; IR: UnifiedReturnBlock:333; IR: %UnifiedRetVal = phi float [ 2.000000e+00, %Flow2 ], [ 1.000000e+00, %exit0 ]334; IR: call void @llvm.amdgcn.end.cf.i64(i64 %11)335; IR: ret float %UnifiedRetVal336define amdgpu_ps float @multi_divergent_region_exit_ret_ret_return_value(i32 %vgpr) #0 {337entry:338 %Pivot = icmp slt i32 %vgpr, 2339 br i1 %Pivot, label %LeafBlock, label %LeafBlock1340 341LeafBlock: ; preds = %entry342 %SwitchLeaf = icmp eq i32 %vgpr, 1343 br i1 %SwitchLeaf, label %exit0, label %exit1344 345LeafBlock1: ; preds = %entry346 %SwitchLeaf2 = icmp eq i32 %vgpr, 2347 br i1 %SwitchLeaf2, label %exit0, label %exit1348 349exit0: ; preds = %LeafBlock, %LeafBlock1350 store i32 9, ptr addrspace(1) poison351 ret float 1.0352 353exit1: ; preds = %LeafBlock, %LeafBlock1354 store i32 17, ptr addrspace(3) poison355 ret float 2.0356}357 358; IR-LABEL: @uniform_branch_to_multi_divergent_region_exit_ret_ret_return_value(359 360; GCN-LABEL: {{^}}uniform_branch_to_multi_divergent_region_exit_ret_ret_return_value:361; GCN: s_cmp_gt_i32 s0, 1362; GCN: s_cbranch_scc0 [[FLOW:.LBB[0-9]+_[0-9]+]]363 364; GCN: v_cmp_ne_u32_e32 vcc, 7, v0365 366; GCN: {{^}}[[FLOW]]:367 368; GCN: s_or_b64 exec, exec369; GCN: v_mov_b32_e32 v0, 2.0370; GCN-NOT: s_and_b64 exec, exec371; GCN: v_mov_b32_e32 v0, 1.0372 373; GCN: {{^.LBB[0-9]+_[0-9]+}}: ; %UnifiedReturnBlock374; GCN-NEXT: s_or_b64 exec, exec375; GCN-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0)376; GCN-NEXT: ; return377 378define amdgpu_ps float @uniform_branch_to_multi_divergent_region_exit_ret_ret_return_value(i32 inreg %sgpr, i32 %vgpr) #0 {379entry:380 %uniform.cond = icmp slt i32 %sgpr, 2381 br i1 %uniform.cond, label %LeafBlock, label %LeafBlock1382 383LeafBlock: ; preds = %entry384 %divergent.cond0 = icmp eq i32 %vgpr, 3385 br i1 %divergent.cond0, label %exit0, label %exit1386 387LeafBlock1: ; preds = %entry388 %divergent.cond1 = icmp eq i32 %vgpr, 7389 br i1 %divergent.cond1, label %exit0, label %exit1390 391exit0: ; preds = %LeafBlock, %LeafBlock1392 store i32 9, ptr addrspace(1) poison393 ret float 1.0394 395exit1: ; preds = %LeafBlock, %LeafBlock1396 store i32 17, ptr addrspace(3) poison397 ret float 2.0398}399 400; IR-LABEL: @multi_divergent_region_exit_ret_unreachable(401; IR: %0 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %Pivot)402 403; IR: Flow:404; IR: %3 = phi i1 [ true, %LeafBlock1 ], [ false, %entry ]405; IR: %4 = phi i1 [ %SwitchLeaf2, %LeafBlock1 ], [ false, %entry ]406; IR: %5 = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 %2)407 408; IR: Flow2:409; IR: %8 = phi i1 [ false, %exit1 ], [ %12, %Flow1 ]410; IR: call void @llvm.amdgcn.end.cf.i64(i64 %16)411; IR: %9 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %8)412; IR: br i1 %10, label %exit0, label %UnifiedReturnBlock413 414; IR: exit0:415; IR-NEXT: store volatile i32 17, ptr addrspace(3) poison416; IR-NEXT: br label %UnifiedReturnBlock417 418; IR: Flow1:419; IR: %12 = phi i1 [ %SwitchLeaf, %LeafBlock ], [ %3, %Flow ]420; IR: %13 = phi i1 [ %SwitchLeaf.inv, %LeafBlock ], [ %4, %Flow ]421; IR: call void @llvm.amdgcn.end.cf.i64(i64 %7)422; IR: %14 = call { i1, i64 } @llvm.amdgcn.if.i64(i1 %13)423; IR: %15 = extractvalue { i1, i64 } %14, 0424; IR: %16 = extractvalue { i1, i64 } %14, 1425; IR: br i1 %15, label %exit1, label %Flow2426 427; IR: exit1:428; IR-NEXT: store volatile i32 9, ptr addrspace(1) poison429; IR-NEXT: call void @llvm.amdgcn.unreachable()430; IR-NEXT: br label %Flow2431 432; IR: UnifiedReturnBlock:433; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 %11)434; IR-NEXT: ret void435define amdgpu_kernel void @multi_divergent_region_exit_ret_unreachable(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2) #0 {436entry:437 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1438 %tmp1 = add i32 0, %tmp439 %tmp2 = zext i32 %tmp1 to i64440 %tmp3 = add i64 0, %tmp2441 %tmp4 = shl i64 %tmp3, 32442 %tmp5 = ashr exact i64 %tmp4, 32443 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5444 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4445 %tmp8 = sext i32 %tmp7 to i64446 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8447 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4448 %tmp13 = zext i32 %tmp10 to i64449 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13450 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16451 %Pivot = icmp slt i32 %tmp16, 2452 br i1 %Pivot, label %LeafBlock, label %LeafBlock1453 454LeafBlock: ; preds = %entry455 %SwitchLeaf = icmp eq i32 %tmp16, 1456 br i1 %SwitchLeaf, label %exit0, label %exit1457 458LeafBlock1: ; preds = %entry459 %SwitchLeaf2 = icmp eq i32 %tmp16, 2460 br i1 %SwitchLeaf2, label %exit0, label %exit1461 462exit0: ; preds = %LeafBlock, %LeafBlock1463 store volatile i32 17, ptr addrspace(3) poison464 ret void465 466exit1: ; preds = %LeafBlock, %LeafBlock1467 store volatile i32 9, ptr addrspace(1) poison468 unreachable469}470 471; The non-uniformity of the branch to the exiting blocks requires472; looking at transitive predecessors.473 474; IR-LABEL: @indirect_multi_divergent_region_exit_ret_unreachable(475 476; IR: exit0: ; preds = %Flow2477; IR-NEXT: store volatile i32 17, ptr addrspace(3) poison478; IR-NEXT: br label %UnifiedReturnBlock479 480 481; IR: indirect.exit1:482; IR: %load = load volatile i32, ptr addrspace(1) poison483; IR: store volatile i32 %load, ptr addrspace(1) poison484; IR: store volatile i32 9, ptr addrspace(1) poison485; IR: call void @llvm.amdgcn.unreachable()486; IR-NEXT: br label %Flow2487 488; IR: UnifiedReturnBlock: ; preds = %exit0, %Flow2489; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 %11)490; IR-NEXT: ret void491define amdgpu_kernel void @indirect_multi_divergent_region_exit_ret_unreachable(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2) #0 {492entry:493 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1494 %tmp1 = add i32 0, %tmp495 %tmp2 = zext i32 %tmp1 to i64496 %tmp3 = add i64 0, %tmp2497 %tmp4 = shl i64 %tmp3, 32498 %tmp5 = ashr exact i64 %tmp4, 32499 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5500 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4501 %tmp8 = sext i32 %tmp7 to i64502 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8503 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4504 %tmp13 = zext i32 %tmp10 to i64505 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13506 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16507 %Pivot = icmp slt i32 %tmp16, 2508 br i1 %Pivot, label %LeafBlock, label %LeafBlock1509 510LeafBlock: ; preds = %entry511 %SwitchLeaf = icmp eq i32 %tmp16, 1512 br i1 %SwitchLeaf, label %exit0, label %indirect.exit1513 514LeafBlock1: ; preds = %entry515 %SwitchLeaf2 = icmp eq i32 %tmp16, 2516 br i1 %SwitchLeaf2, label %exit0, label %indirect.exit1517 518exit0: ; preds = %LeafBlock, %LeafBlock1519 store volatile i32 17, ptr addrspace(3) poison520 ret void521 522indirect.exit1:523 %load = load volatile i32, ptr addrspace(1) poison524 store volatile i32 %load, ptr addrspace(1) poison525 br label %exit1526 527exit1: ; preds = %LeafBlock, %LeafBlock1528 store volatile i32 9, ptr addrspace(1) poison529 unreachable530}531 532; IR-LABEL: @multi_divergent_region_exit_ret_switch(533define amdgpu_kernel void @multi_divergent_region_exit_ret_switch(ptr addrspace(1) nocapture %arg0, ptr addrspace(1) nocapture %arg1, ptr addrspace(1) nocapture %arg2) #0 {534entry:535 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x() #1536 %tmp1 = add i32 0, %tmp537 %tmp2 = zext i32 %tmp1 to i64538 %tmp3 = add i64 0, %tmp2539 %tmp4 = shl i64 %tmp3, 32540 %tmp5 = ashr exact i64 %tmp4, 32541 %tmp6 = getelementptr inbounds i32, ptr addrspace(1) %arg0, i64 %tmp5542 %tmp7 = load i32, ptr addrspace(1) %tmp6, align 4543 %tmp8 = sext i32 %tmp7 to i64544 %tmp9 = getelementptr inbounds i32, ptr addrspace(1) %arg1, i64 %tmp8545 %tmp10 = load i32, ptr addrspace(1) %tmp9, align 4546 %tmp13 = zext i32 %tmp10 to i64547 %tmp14 = getelementptr inbounds i32, ptr addrspace(1) %arg2, i64 %tmp13548 %tmp16 = load i32, ptr addrspace(1) %tmp14, align 16549 switch i32 %tmp16, label %exit1550 [ i32 1, label %LeafBlock551 i32 2, label %LeafBlock1552 i32 3, label %exit0 ]553 554LeafBlock: ; preds = %entry555 %SwitchLeaf = icmp eq i32 %tmp16, 1556 br i1 %SwitchLeaf, label %exit0, label %exit1557 558LeafBlock1: ; preds = %entry559 %SwitchLeaf2 = icmp eq i32 %tmp16, 2560 br i1 %SwitchLeaf2, label %exit0, label %exit1561 562exit0: ; preds = %LeafBlock, %LeafBlock1563 store volatile i32 17, ptr addrspace(3) poison564 ret void565 566exit1: ; preds = %LeafBlock, %LeafBlock1567 store volatile i32 9, ptr addrspace(1) poison568 unreachable569}570 571; IR-LABEL: @divergent_multi_ret_nest_in_uniform_triangle(572define amdgpu_kernel void @divergent_multi_ret_nest_in_uniform_triangle(i32 %arg0) #0 {573entry:574 %uniform.cond0 = icmp eq i32 %arg0, 4575 br i1 %uniform.cond0, label %divergent.multi.exit.region, label %uniform.ret576 577divergent.multi.exit.region:578 %id.x = tail call i32 @llvm.amdgcn.workitem.id.x()579 %divergent.cond0 = icmp eq i32 %id.x, 0580 br i1 %divergent.cond0, label %divergent.ret0, label %divergent.ret1581 582divergent.ret0:583 store volatile i32 11, ptr addrspace(3) poison584 ret void585 586divergent.ret1:587 store volatile i32 42, ptr addrspace(3) poison588 ret void589 590uniform.ret:591 store volatile i32 9, ptr addrspace(1) poison592 ret void593}594 595; IR-LABEL: @divergent_complex_multi_ret_nest_in_uniform_triangle(596define amdgpu_kernel void @divergent_complex_multi_ret_nest_in_uniform_triangle(i32 %arg0) #0 {597entry:598 %uniform.cond0 = icmp eq i32 %arg0, 4599 br i1 %uniform.cond0, label %divergent.multi.exit.region, label %uniform.ret600 601divergent.multi.exit.region:602 %id.x = tail call i32 @llvm.amdgcn.workitem.id.x()603 %divergent.cond0 = icmp eq i32 %id.x, 0604 br i1 %divergent.cond0, label %divergent.if, label %divergent.ret1605 606divergent.if:607 %vgpr0 = load volatile float, ptr addrspace(1) poison608 %divergent.cond1 = fcmp ogt float %vgpr0, 1.0609 br i1 %divergent.cond1, label %divergent.then, label %divergent.endif610 611divergent.then:612 %vgpr1 = load volatile float, ptr addrspace(1) poison613 %divergent.cond2 = fcmp olt float %vgpr1, 4.0614 store volatile i32 33, ptr addrspace(1) poison615 br i1 %divergent.cond2, label %divergent.ret0, label %divergent.endif616 617divergent.endif:618 store volatile i32 38, ptr addrspace(1) poison619 br label %divergent.ret0620 621divergent.ret0:622 store volatile i32 11, ptr addrspace(3) poison623 ret void624 625divergent.ret1:626 store volatile i32 42, ptr addrspace(3) poison627 ret void628 629uniform.ret:630 store volatile i32 9, ptr addrspace(1) poison631 ret void632}633 634; IR-LABEL: @uniform_complex_multi_ret_nest_in_divergent_triangle(635; IR: Flow1: ; preds = %uniform.ret1, %uniform.multi.exit.region636; IR: %6 = phi i1 [ false, %uniform.ret1 ], [ true, %uniform.multi.exit.region ]637; IR: br i1 %6, label %uniform.if, label %Flow2638 639; IR: Flow: ; preds = %uniform.then, %uniform.if640; IR: %7 = phi i1 [ %uniform.cond2, %uniform.then ], [ %uniform.cond1.inv, %uniform.if ]641; IR: br i1 %7, label %uniform.endif, label %uniform.ret0642 643; IR: UnifiedReturnBlock: ; preds = %Flow3, %Flow2644; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 %5)645; IR-NEXT: ret void646define amdgpu_kernel void @uniform_complex_multi_ret_nest_in_divergent_triangle(i32 %arg0) #0 {647entry:648 %id.x = tail call i32 @llvm.amdgcn.workitem.id.x()649 %divergent.cond0 = icmp eq i32 %id.x, 0650 br i1 %divergent.cond0, label %uniform.multi.exit.region, label %divergent.ret651 652uniform.multi.exit.region:653 %uniform.cond0 = icmp eq i32 %arg0, 4654 br i1 %uniform.cond0, label %uniform.if, label %uniform.ret1655 656uniform.if:657 %sgpr0 = load volatile i32, ptr addrspace(4) poison658 %uniform.cond1 = icmp slt i32 %sgpr0, 1659 br i1 %uniform.cond1, label %uniform.then, label %uniform.endif660 661uniform.then:662 %sgpr1 = load volatile i32, ptr addrspace(4) poison663 %uniform.cond2 = icmp sge i32 %sgpr1, 4664 store volatile i32 33, ptr addrspace(1) poison665 br i1 %uniform.cond2, label %uniform.ret0, label %uniform.endif666 667uniform.endif:668 store volatile i32 38, ptr addrspace(1) poison669 br label %uniform.ret0670 671uniform.ret0:672 store volatile i32 11, ptr addrspace(3) poison673 ret void674 675uniform.ret1:676 store volatile i32 42, ptr addrspace(3) poison677 ret void678 679divergent.ret:680 store volatile i32 9, ptr addrspace(1) poison681 ret void682}683 684; IR-LABEL: @multi_divergent_unreachable_exit(685; IR: UnifiedUnreachableBlock:686; IR-NEXT: call void @llvm.amdgcn.unreachable()687; IR-NEXT: br label %UnifiedReturnBlock688 689; IR: UnifiedReturnBlock:690; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64691; IR-NEXT: ret void692define amdgpu_kernel void @multi_divergent_unreachable_exit(i32 %switch) #0 {693bb:694 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()695 switch i32 %tmp, label %bb3 [696 i32 2, label %bb1697 i32 0, label %bb2698 ]699 700bb1: ; preds = %bb701 unreachable702 703bb2: ; preds = %bb704 unreachable705 706bb3: ; preds = %bb707 switch i32 %switch, label %bb5 [708 i32 2, label %bb4709 ]710 711bb4: ; preds = %bb3712 ret void713 714bb5: ; preds = %bb3715 unreachable716}717 718; Test that there is an extra export inserted after the normal export,719; if the normal export is inside a uniformly reached block and there is720; an infinite loop in the pixel shader.721 722; IR-LABEL: @uniformly_reached_export723; IR-NEXT: .entry:724; IR: br i1 [[CND:%.*]], label %[[LOOP:.*]], label %[[EXP:.*]]725 726; IR: [[LOOP]]:727; IR-NEXT: br i1 false, label %DummyReturnBlock, label %[[LOOP]]728 729; IR: [[EXP]]:730; IR-NEXT: call void @llvm.amdgcn.exp.compr.v2f16(i32 0, i32 15, <2 x half> <half 0xH3C00, half 0xH0000>, <2 x half> <half 0xH0000, half 0xH3C00>, i1 true, i1 true)731; IR-NEXT: ret void732 733; IR: DummyReturnBlock:734; IR-NEXT: ret void735 736define amdgpu_ps void @uniformly_reached_export(float inreg %tmp25) {737.entry:738 %tmp26 = fcmp olt float %tmp25, 0.000000e+00739 br i1 %tmp26, label %loop, label %bb27740 741loop: ; preds = %loop, %.entry742 br label %loop743 744bb27: ; preds = %.entry745 call void @llvm.amdgcn.exp.compr.v2f16(i32 0, i32 15, <2 x half> <half 0xH3C00, half 0xH0000>, <2 x half> <half 0xH0000, half 0xH3C00>, i1 true, i1 true)746 ret void747}748 749declare void @llvm.amdgcn.exp.compr.v2f16(i32 immarg, i32 immarg, <2 x half>, <2 x half>, i1 immarg, i1 immarg) #0750declare i32 @llvm.amdgcn.workitem.id.x() #1751 752attributes #0 = { nounwind }753attributes #1 = { nounwind readnone }754