brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.5 KiB · d6cc833 Raw
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