431 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: llc -mtriple=amdgcn -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck -check-prefix=SI %s3; RUN: opt -mtriple=amdgcn-- -S -amdgpu-unify-divergent-exit-nodes -verify -simplifycfg-require-and-preserve-domtree=1 %s | FileCheck -check-prefix=IR %s4 5define amdgpu_kernel void @infinite_loop(ptr addrspace(1) %out) {6; SI-LABEL: infinite_loop:7; SI: ; %bb.0: ; %entry8; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x99; SI-NEXT: s_mov_b32 s3, 0xf00010; SI-NEXT: s_mov_b32 s2, -111; SI-NEXT: v_mov_b32_e32 v0, 0x3e712; SI-NEXT: s_and_b64 vcc, exec, -113; SI-NEXT: .LBB0_1: ; %loop14; SI-NEXT: ; =>This Inner Loop Header: Depth=115; SI-NEXT: s_waitcnt lgkmcnt(0)16; SI-NEXT: buffer_store_dword v0, off, s[0:3], 017; SI-NEXT: s_waitcnt vmcnt(0)18; SI-NEXT: s_mov_b64 vcc, vcc19; SI-NEXT: s_cbranch_vccnz .LBB0_120; SI-NEXT: ; %bb.2: ; %DummyReturnBlock21; SI-NEXT: s_endpgm22; IR-LABEL: @infinite_loop(23; IR-NEXT: entry:24; IR-NEXT: br label [[LOOP:%.*]]25; IR: loop:26; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 427; IR-NEXT: br i1 true, label [[LOOP]], label [[DUMMYRETURNBLOCK:%.*]]28; IR: DummyReturnBlock:29; IR-NEXT: ret void30;31entry:32 br label %loop33 34loop:35 store volatile i32 999, ptr addrspace(1) %out, align 436 br label %loop37}38 39define amdgpu_kernel void @infinite_loop_callbr(ptr addrspace(1) %out) {40; SI-LABEL: infinite_loop_callbr:41; SI: ; %bb.0: ; %entry42; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x943; SI-NEXT: ;;#ASMSTART44; SI-NEXT: ;;#ASMEND45; SI-NEXT: s_mov_b32 s3, 0xf00046; SI-NEXT: s_mov_b32 s2, -147; SI-NEXT: v_mov_b32_e32 v0, 0x3e748; SI-NEXT: s_waitcnt lgkmcnt(0)49; SI-NEXT: buffer_store_dword v0, off, s[0:3], 050; SI-NEXT: s_waitcnt vmcnt(0)51; SI-NEXT: s_endpgm52; IR-LABEL: @infinite_loop_callbr(53; IR-NEXT: entry:54; IR-NEXT: callbr void asm "", ""()55; IR-NEXT: to label [[LOOP:%.*]] []56; IR: loop:57; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 458; IR-NEXT: br i1 true, label [[TRANSITIONBLOCK:%.*]], label [[DUMMYRETURNBLOCK:%.*]]59; IR: TransitionBlock:60; IR-NEXT: callbr void asm "", ""()61; IR-NEXT: to label [[LOOP]] []62; IR: DummyReturnBlock:63; IR-NEXT: ret void64;65entry:66 callbr void asm "", ""() to label %loop []67 68loop:69 store volatile i32 999, ptr addrspace(1) %out, align 470 callbr void asm "", ""() to label %loop []71}72 73define amdgpu_kernel void @infinite_loop_ret(ptr addrspace(1) %out) {74; SI-LABEL: infinite_loop_ret:75; SI: ; %bb.0: ; %entry76; SI-NEXT: v_cmp_eq_u32_e32 vcc, 1, v077; SI-NEXT: s_and_saveexec_b64 s[0:1], vcc78; SI-NEXT: s_cbranch_execz .LBB2_379; SI-NEXT: ; %bb.1: ; %loop.preheader80; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x981; SI-NEXT: s_mov_b32 s3, 0xf00082; SI-NEXT: s_mov_b32 s2, -183; SI-NEXT: v_mov_b32_e32 v0, 0x3e784; SI-NEXT: s_and_b64 vcc, exec, -185; SI-NEXT: .LBB2_2: ; %loop86; SI-NEXT: ; =>This Inner Loop Header: Depth=187; SI-NEXT: s_waitcnt lgkmcnt(0)88; SI-NEXT: buffer_store_dword v0, off, s[0:3], 089; SI-NEXT: s_waitcnt vmcnt(0)90; SI-NEXT: s_mov_b64 vcc, vcc91; SI-NEXT: s_cbranch_vccnz .LBB2_292; SI-NEXT: .LBB2_3: ; %UnifiedReturnBlock93; SI-NEXT: s_endpgm94; IR-LABEL: @infinite_loop_ret(95; IR-NEXT: entry:96; IR-NEXT: [[TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()97; IR-NEXT: [[COND:%.*]] = icmp eq i32 [[TMP]], 198; IR-NEXT: br i1 [[COND]], label [[LOOP:%.*]], label [[UNIFIEDRETURNBLOCK:%.*]]99; IR: loop:100; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 4101; IR-NEXT: br i1 true, label [[LOOP]], label [[UNIFIEDRETURNBLOCK]]102; IR: UnifiedReturnBlock:103; IR-NEXT: ret void104;105entry:106 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()107 %cond = icmp eq i32 %tmp, 1108 br i1 %cond, label %loop, label %return109 110loop:111 store volatile i32 999, ptr addrspace(1) %out, align 4112 br label %loop113 114return:115 ret void116}117 118define amdgpu_kernel void @infinite_loop_ret_callbr(ptr addrspace(1) %out) {119; SI-LABEL: infinite_loop_ret_callbr:120; SI: ; %bb.0: ; %entry121; SI-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0122; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc123; SI-NEXT: ;;#ASMSTART124; SI-NEXT: ;;#ASMEND125; SI-NEXT: ; %bb.1: ; %loop.preheader126; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x9127; SI-NEXT: s_mov_b32 s3, 0xf000128; SI-NEXT: s_mov_b32 s2, -1129; SI-NEXT: v_mov_b32_e32 v0, 0x3e7130; SI-NEXT: s_waitcnt lgkmcnt(0)131; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0132; SI-NEXT: s_waitcnt vmcnt(0)133; SI-NEXT: .LBB3_2: ; Inline asm indirect target134; SI-NEXT: ; %UnifiedReturnBlock135; SI-NEXT: ; Label of block must be emitted136; SI-NEXT: s_endpgm137; IR-LABEL: @infinite_loop_ret_callbr(138; IR-NEXT: entry:139; IR-NEXT: [[TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()140; IR-NEXT: [[COND:%.*]] = icmp eq i32 [[TMP]], 1141; IR-NEXT: [[COND32:%.*]] = zext i1 [[COND]] to i32142; IR-NEXT: callbr void asm "", "r,!i"(i32 [[COND32]])143; IR-NEXT: to label [[LOOP:%.*]] [label %UnifiedReturnBlock]144; IR: loop:145; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 4146; IR-NEXT: br i1 true, label [[TRANSITIONBLOCK:%.*]], label [[UNIFIEDRETURNBLOCK:%.*]]147; IR: TransitionBlock:148; IR-NEXT: callbr void asm "", ""()149; IR-NEXT: to label [[LOOP]] []150; IR: UnifiedReturnBlock:151; IR-NEXT: ret void152;153entry:154 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()155 %cond = icmp eq i32 %tmp, 1156 %cond32 = zext i1 %cond to i32157 callbr void asm "", "r,!i"(i32 %cond32) to label %loop [label %return]158 159loop:160 store volatile i32 999, ptr addrspace(1) %out, align 4161 callbr void asm "", ""() to label %loop []162 163return:164 ret void165}166 167define amdgpu_kernel void @infinite_loops(ptr addrspace(1) %out) {168; SI-LABEL: infinite_loops:169; SI: ; %bb.0: ; %entry170; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x9171; SI-NEXT: s_mov_b64 s[2:3], -1172; SI-NEXT: s_cbranch_scc1 .LBB4_4173; SI-NEXT: ; %bb.1:174; SI-NEXT: s_mov_b32 s3, 0xf000175; SI-NEXT: s_mov_b32 s2, -1176; SI-NEXT: v_mov_b32_e32 v0, 0x378177; SI-NEXT: s_and_b64 vcc, exec, -1178; SI-NEXT: .LBB4_2: ; %loop2179; SI-NEXT: ; =>This Inner Loop Header: Depth=1180; SI-NEXT: s_waitcnt lgkmcnt(0)181; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0182; SI-NEXT: s_waitcnt vmcnt(0)183; SI-NEXT: s_mov_b64 vcc, vcc184; SI-NEXT: s_cbranch_vccnz .LBB4_2185; SI-NEXT: ; %bb.3: ; %Flow186; SI-NEXT: s_mov_b64 s[2:3], 0187; SI-NEXT: .LBB4_4: ; %Flow2188; SI-NEXT: s_and_b64 vcc, exec, s[2:3]189; SI-NEXT: s_waitcnt lgkmcnt(0)190; SI-NEXT: s_mov_b64 vcc, vcc191; SI-NEXT: s_cbranch_vccz .LBB4_7192; SI-NEXT: ; %bb.5:193; SI-NEXT: s_mov_b32 s3, 0xf000194; SI-NEXT: s_mov_b32 s2, -1195; SI-NEXT: s_waitcnt expcnt(0)196; SI-NEXT: v_mov_b32_e32 v0, 0x3e7197; SI-NEXT: s_and_b64 vcc, exec, 0198; SI-NEXT: .LBB4_6: ; %loop1199; SI-NEXT: ; =>This Inner Loop Header: Depth=1200; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0201; SI-NEXT: s_waitcnt vmcnt(0)202; SI-NEXT: s_mov_b64 vcc, vcc203; SI-NEXT: s_cbranch_vccz .LBB4_6204; SI-NEXT: .LBB4_7: ; %DummyReturnBlock205; SI-NEXT: s_endpgm206; IR-LABEL: @infinite_loops(207; IR-NEXT: entry:208; IR-NEXT: br i1 poison, label [[LOOP1:%.*]], label [[LOOP2:%.*]]209; IR: loop1:210; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 4211; IR-NEXT: br i1 true, label [[LOOP1]], label [[DUMMYRETURNBLOCK:%.*]]212; IR: loop2:213; IR-NEXT: store volatile i32 888, ptr addrspace(1) [[OUT]], align 4214; IR-NEXT: br i1 true, label [[LOOP2]], label [[DUMMYRETURNBLOCK]]215; IR: DummyReturnBlock:216; IR-NEXT: ret void217;218entry:219 br i1 poison, label %loop1, label %loop2220 221loop1:222 store volatile i32 999, ptr addrspace(1) %out, align 4223 br label %loop1224 225loop2:226 store volatile i32 888, ptr addrspace(1) %out, align 4227 br label %loop2228}229 230define amdgpu_kernel void @infinite_loops_callbr(ptr addrspace(1) %out) {231; SI-LABEL: infinite_loops_callbr:232; SI: ; %bb.0: ; %entry233; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x9234; SI-NEXT: s_waitcnt lgkmcnt(0)235; SI-NEXT: ;;#ASMSTART236; SI-NEXT: ;;#ASMEND237; SI-NEXT: ; %bb.1: ; %loop1238; SI-NEXT: s_mov_b32 s3, 0xf000239; SI-NEXT: s_mov_b32 s2, -1240; SI-NEXT: v_mov_b32_e32 v0, 0x3e7241; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0242; SI-NEXT: s_waitcnt vmcnt(0)243; SI-NEXT: s_endpgm244; SI-NEXT: .LBB5_2: ; Inline asm indirect target245; SI-NEXT: ; %loop2.preheader246; SI-NEXT: ; Label of block must be emitted247; SI-NEXT: s_mov_b32 s3, 0xf000248; SI-NEXT: s_mov_b32 s2, -1249; SI-NEXT: v_mov_b32_e32 v0, 0x378250; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0251; SI-NEXT: s_waitcnt vmcnt(0)252; SI-NEXT: s_endpgm253; IR-LABEL: @infinite_loops_callbr(254; IR-NEXT: entry:255; IR-NEXT: callbr void asm "", "r,!i"(i32 poison)256; IR-NEXT: to label [[LOOP1:%.*]] [label %loop2]257; IR: loop1:258; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 4259; IR-NEXT: br i1 true, label [[TRANSITIONBLOCK:%.*]], label [[DUMMYRETURNBLOCK:%.*]]260; IR: TransitionBlock:261; IR-NEXT: callbr void asm "", ""()262; IR-NEXT: to label [[LOOP1]] []263; IR: loop2:264; IR-NEXT: store volatile i32 888, ptr addrspace(1) [[OUT]], align 4265; IR-NEXT: br i1 true, label [[TRANSITIONBLOCK1:%.*]], label [[DUMMYRETURNBLOCK]]266; IR: TransitionBlock1:267; IR-NEXT: callbr void asm "", ""()268; IR-NEXT: to label [[LOOP2:%.*]] []269; IR: DummyReturnBlock:270; IR-NEXT: ret void271;272entry:273 callbr void asm "", "r,!i"(i32 poison) to label %loop1 [label %loop2]274 275loop1:276 store volatile i32 999, ptr addrspace(1) %out, align 4277 callbr void asm "", ""() to label %loop1 []278 279loop2:280 store volatile i32 888, ptr addrspace(1) %out, align 4281 callbr void asm "", ""() to label %loop2 []282}283 284define amdgpu_kernel void @infinite_loop_nest_ret(ptr addrspace(1) %out) {285; SI-LABEL: infinite_loop_nest_ret:286; SI: ; %bb.0: ; %entry287; SI-NEXT: v_cmp_ne_u32_e32 vcc, 1, v0288; SI-NEXT: s_and_saveexec_b64 s[0:1], vcc289; SI-NEXT: s_cbranch_execz .LBB6_5290; SI-NEXT: ; %bb.1: ; %outer_loop.preheader291; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x9292; SI-NEXT: v_cmp_ne_u32_e64 s[0:1], 3, v0293; SI-NEXT: s_mov_b32 s7, 0xf000294; SI-NEXT: s_mov_b32 s6, -1295; SI-NEXT: v_mov_b32_e32 v0, 0x3e7296; SI-NEXT: .LBB6_2: ; %outer_loop297; SI-NEXT: ; =>This Loop Header: Depth=1298; SI-NEXT: ; Child Loop BB6_3 Depth 2299; SI-NEXT: s_mov_b64 s[2:3], 0300; SI-NEXT: .LBB6_3: ; %inner_loop301; SI-NEXT: ; Parent Loop BB6_2 Depth=1302; SI-NEXT: ; => This Inner Loop Header: Depth=2303; SI-NEXT: s_and_b64 s[8:9], exec, s[0:1]304; SI-NEXT: s_or_b64 s[2:3], s[8:9], s[2:3]305; SI-NEXT: s_waitcnt lgkmcnt(0)306; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0307; SI-NEXT: s_waitcnt vmcnt(0)308; SI-NEXT: s_andn2_b64 exec, exec, s[2:3]309; SI-NEXT: s_cbranch_execnz .LBB6_3310; SI-NEXT: ; %bb.4: ; %loop.exit.guard311; SI-NEXT: ; in Loop: Header=BB6_2 Depth=1312; SI-NEXT: s_or_b64 exec, exec, s[2:3]313; SI-NEXT: s_mov_b64 vcc, 0314; SI-NEXT: s_branch .LBB6_2315; SI-NEXT: .LBB6_5: ; %UnifiedReturnBlock316; SI-NEXT: s_endpgm317; IR-LABEL: @infinite_loop_nest_ret(318; IR-NEXT: entry:319; IR-NEXT: [[TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()320; IR-NEXT: [[COND1:%.*]] = icmp ne i32 [[TMP]], 1321; IR-NEXT: br i1 [[COND1]], label [[OUTER_LOOP:%.*]], label [[UNIFIEDRETURNBLOCK:%.*]]322; IR: outer_loop:323; IR-NEXT: br label [[INNER_LOOP:%.*]]324; IR: inner_loop:325; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 4326; IR-NEXT: [[COND3:%.*]] = icmp eq i32 [[TMP]], 3327; IR-NEXT: br i1 true, label [[TRANSITIONBLOCK:%.*]], label [[UNIFIEDRETURNBLOCK]]328; IR: TransitionBlock:329; IR-NEXT: br i1 [[COND3]], label [[INNER_LOOP]], label [[OUTER_LOOP]]330; IR: UnifiedReturnBlock:331; IR-NEXT: ret void332;333entry:334 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()335 %cond1 = icmp ne i32 %tmp, 1 ; avoid following BB optimizing away through the domination336 br i1 %cond1, label %outer_loop, label %return337 338outer_loop:339 ; %cond2 = icmp eq i32 %tmp, 2340 ; br i1 %cond2, label %outer_loop, label %inner_loop341 br label %inner_loop342 343inner_loop: ; preds = %LeafBlock, %LeafBlock1344 store volatile i32 999, ptr addrspace(1) %out, align 4345 %cond3 = icmp eq i32 %tmp, 3346 br i1 %cond3, label %inner_loop, label %outer_loop347 348return:349 ret void350}351 352define amdgpu_kernel void @infinite_loop_nest_ret_callbr(ptr addrspace(1) %out) {353; SI-LABEL: infinite_loop_nest_ret_callbr:354; SI: ; %bb.0: ; %entry355; SI-NEXT: v_cmp_ne_u32_e32 vcc, 1, v0356; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc357; SI-NEXT: ;;#ASMSTART358; SI-NEXT: ;;#ASMEND359; SI-NEXT: ; %bb.1: ; %outer_loop.preheader360; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x9361; SI-NEXT: s_mov_b32 s7, 0xf000362; SI-NEXT: s_mov_b32 s6, -1363; SI-NEXT: v_mov_b32_e32 v0, 0x3e7364; SI-NEXT: s_and_b64 s[0:1], exec, 0365; SI-NEXT: s_branch .LBB7_3366; SI-NEXT: .LBB7_2: ; %loop.exit.guard367; SI-NEXT: ; in Loop: Header=BB7_3 Depth=1368; SI-NEXT: s_and_b64 vcc, exec, s[2:3]369; SI-NEXT: s_cbranch_vccnz .LBB7_5370; SI-NEXT: .LBB7_3: ; %outer_loop371; SI-NEXT: ; =>This Inner Loop Header: Depth=1372; SI-NEXT: ;;#ASMSTART373; SI-NEXT: ;;#ASMEND374; SI-NEXT: s_waitcnt lgkmcnt(0)375; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0376; SI-NEXT: s_waitcnt vmcnt(0)377; SI-NEXT: s_mov_b64 s[2:3], -1378; SI-NEXT: s_mov_b64 vcc, s[0:1]379; SI-NEXT: s_cbranch_vccz .LBB7_2380; SI-NEXT: ; %bb.4: ; %TransitionBlock.target.outer_loop381; SI-NEXT: ; in Loop: Header=BB7_3 Depth=1382; SI-NEXT: s_mov_b64 s[2:3], 0383; SI-NEXT: s_branch .LBB7_2384; SI-NEXT: .LBB7_5: ; Inline asm indirect target385; SI-NEXT: ; %UnifiedReturnBlock386; SI-NEXT: ; Label of block must be emitted387; SI-NEXT: s_endpgm388; IR-LABEL: @infinite_loop_nest_ret_callbr(389; IR-NEXT: entry:390; IR-NEXT: [[TMP:%.*]] = tail call i32 @llvm.amdgcn.workitem.id.x()391; IR-NEXT: [[COND1:%.*]] = icmp ne i32 [[TMP]], 1392; IR-NEXT: [[COND1_32:%.*]] = zext i1 [[COND1]] to i32393; IR-NEXT: callbr void asm "", "r,!i"(i32 [[COND1_32]])394; IR-NEXT: to label [[OUTER_LOOP:%.*]] [label %UnifiedReturnBlock]395; IR: outer_loop:396; IR-NEXT: callbr void asm "", ""()397; IR-NEXT: to label [[INNER_LOOP:%.*]] []398; IR: inner_loop:399; IR-NEXT: store volatile i32 999, ptr addrspace(1) [[OUT:%.*]], align 4400; IR-NEXT: [[COND3:%.*]] = icmp eq i32 [[TMP]], 3401; IR-NEXT: [[COND3_32:%.*]] = zext i1 [[COND3]] to i32402; IR-NEXT: br i1 true, label [[TRANSITIONBLOCK:%.*]], label [[UNIFIEDRETURNBLOCK:%.*]]403; IR: TransitionBlock:404; IR-NEXT: callbr void asm "", "r,!i"(i32 [[COND3_32]])405; IR-NEXT: to label [[INNER_LOOP]] [label %outer_loop]406; IR: UnifiedReturnBlock:407; IR-NEXT: ret void408;409entry:410 %tmp = tail call i32 @llvm.amdgcn.workitem.id.x()411 %cond1 = icmp ne i32 %tmp, 1 ; avoid following BB optimizing away through the domination412 %cond1_32 = zext i1 %cond1 to i32413 callbr void asm "", "r,!i"(i32 %cond1_32) to label %outer_loop [label %return]414 415outer_loop:416 ; %cond2 = icmp eq i32 %tmp, 2417 ; br i1 %cond2, label %outer_loop, label %inner_loop418 callbr void asm "", ""() to label %inner_loop []419 420inner_loop: ; preds = %LeafBlock, %LeafBlock1421 store volatile i32 999, ptr addrspace(1) %out, align 4422 %cond3 = icmp eq i32 %tmp, 3423 %cond3_32 = zext i1 %cond3 to i32424 callbr void asm "", "r,!i"(i32 %cond3_32) to label %inner_loop [label %outer_loop]425 426return:427 ret void428}429 430declare i32 @llvm.amdgcn.workitem.id.x()431