616 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 32; RUN: llc -global-isel -mtriple=amdgcn-amd-amdpal -mcpu=gfx1010 -new-reg-bank-select < %s | FileCheck -check-prefix=GFX10 %s3 4; Simples case, if - then, that requires lane mask merging,5; %phi lane mask will hold %val_A at %A. Lanes that are active in %B6; will overwrite its own lane bit in lane mask with val_B7define amdgpu_ps void @divergent_i1_phi_if_then(ptr addrspace(1) %out, i32 %tid, i32 %cond) {8; GFX10-LABEL: divergent_i1_phi_if_then:9; GFX10: ; %bb.0: ; %A10; GFX10-NEXT: v_cmp_le_u32_e64 s0, 6, v211; GFX10-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v312; GFX10-NEXT: s_and_saveexec_b32 s1, vcc_lo13; GFX10-NEXT: ; %bb.1: ; %B14; GFX10-NEXT: v_cmp_gt_u32_e32 vcc_lo, 1, v215; GFX10-NEXT: s_andn2_b32 s0, s0, exec_lo16; GFX10-NEXT: s_and_b32 s2, exec_lo, vcc_lo17; GFX10-NEXT: s_or_b32 s0, s0, s218; GFX10-NEXT: ; %bb.2: ; %exit19; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s120; GFX10-NEXT: v_cndmask_b32_e64 v2, 0, -1, s021; GFX10-NEXT: v_add_nc_u32_e32 v2, 2, v222; GFX10-NEXT: global_store_dword v[0:1], v2, off23; GFX10-NEXT: s_endpgm24A:25 %val_A = icmp uge i32 %tid, 626 %cmp = icmp eq i32 %cond, 027 br i1 %cmp, label %B, label %exit28 29B:30 %val_B = icmp ult i32 %tid, 131 br label %exit32 33exit:34 %phi = phi i1 [ %val_A, %A ], [ %val_B, %B ]35 %sel = select i1 %phi, i32 1, i32 236 store i32 %sel, ptr addrspace(1) %out37 ret void38}39 40; if - else41define amdgpu_ps void @divergent_i1_phi_if_else(ptr addrspace(1) %out, i32 %tid, i32 %cond) {42; GFX10-LABEL: divergent_i1_phi_if_else:43; GFX10: ; %bb.0: ; %entry44; GFX10-NEXT: s_and_b32 s0, s0, 145; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v346; GFX10-NEXT: s_cmp_lg_u32 s0, 047; GFX10-NEXT: s_cselect_b32 s0, exec_lo, 048; GFX10-NEXT: s_and_saveexec_b32 s1, vcc_lo49; GFX10-NEXT: s_xor_b32 s1, exec_lo, s150; GFX10-NEXT: ; %bb.1: ; %B51; GFX10-NEXT: v_cmp_gt_u32_e32 vcc_lo, 2, v252; GFX10-NEXT: s_andn2_b32 s0, s0, exec_lo53; GFX10-NEXT: ; implicit-def: $vgpr254; GFX10-NEXT: s_and_b32 s2, exec_lo, vcc_lo55; GFX10-NEXT: s_or_b32 s0, s0, s256; GFX10-NEXT: ; %bb.2: ; %Flow57; GFX10-NEXT: s_andn2_saveexec_b32 s1, s158; GFX10-NEXT: ; %bb.3: ; %A59; GFX10-NEXT: v_cmp_le_u32_e32 vcc_lo, 1, v260; GFX10-NEXT: s_andn2_b32 s0, s0, exec_lo61; GFX10-NEXT: s_and_b32 s2, exec_lo, vcc_lo62; GFX10-NEXT: s_or_b32 s0, s0, s263; GFX10-NEXT: ; %bb.4: ; %exit64; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s165; GFX10-NEXT: v_cndmask_b32_e64 v2, 0, -1, s066; GFX10-NEXT: v_add_nc_u32_e32 v2, 2, v267; GFX10-NEXT: global_store_dword v[0:1], v2, off68; GFX10-NEXT: s_endpgm69entry:70 %cmp = icmp eq i32 %cond, 071 br i1 %cmp, label %A, label %B72 73A:74 %val_A = icmp uge i32 %tid, 175 br label %exit76 77B:78 %val_B = icmp ult i32 %tid, 279 br label %exit80 81exit:82 %phi = phi i1 [ %val_A, %A ], [ %val_B, %B ]83 %sel = select i1 %phi, i32 1, i32 284 store i32 %sel, ptr addrspace(1) %out85 ret void86}87 88; if - break;89 90; counter = 0;91; do {92; if (a[counter] == 0)93; break;94; if (b[counter] == 0)95; break;96; if (c[counter] == 0)97; break;98; x[counter++]+=1;99; } while (counter<100);100 101; Tests with multiple break conditions. Divergent phis will be used to track102; if any of the break conditions was reached. We only need to do simple lane103; mask merging (for current loop iteration only). There is an intrinsic,104; if_break, that will merge lane masks across all iterations of the loop.105 106define amdgpu_cs void @loop_with_1break(ptr addrspace(1) %x, ptr addrspace(1) %a) {107; GFX10-LABEL: loop_with_1break:108; GFX10: ; %bb.0: ; %entry109; GFX10-NEXT: s_mov_b32 s0, 0110; GFX10-NEXT: s_mov_b32 s4, 0111; GFX10-NEXT: ; implicit-def: $sgpr5112; GFX10-NEXT: s_branch .LBB2_2113; GFX10-NEXT: .LBB2_1: ; %Flow114; GFX10-NEXT: ; in Loop: Header=BB2_2 Depth=1115; GFX10-NEXT: s_waitcnt_depctr depctr_vm_vsrc(0)116; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s1117; GFX10-NEXT: s_and_b32 s1, exec_lo, s5118; GFX10-NEXT: s_or_b32 s4, s1, s4119; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4120; GFX10-NEXT: s_cbranch_execz .LBB2_4121; GFX10-NEXT: .LBB2_2: ; %A122; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1123; GFX10-NEXT: s_ashr_i32 s1, s0, 31124; GFX10-NEXT: s_lshl_b64 s[2:3], s[0:1], 2125; GFX10-NEXT: s_andn2_b32 s1, s5, exec_lo126; GFX10-NEXT: v_mov_b32_e32 v5, s3127; GFX10-NEXT: v_mov_b32_e32 v4, s2128; GFX10-NEXT: s_and_b32 s5, exec_lo, exec_lo129; GFX10-NEXT: s_or_b32 s5, s1, s5130; GFX10-NEXT: v_add_co_u32 v4, vcc_lo, v2, v4131; GFX10-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, v3, v5, vcc_lo132; GFX10-NEXT: global_load_dword v4, v[4:5], off133; GFX10-NEXT: s_waitcnt vmcnt(0)134; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v4135; GFX10-NEXT: s_and_saveexec_b32 s1, vcc_lo136; GFX10-NEXT: s_cbranch_execz .LBB2_1137; GFX10-NEXT: ; %bb.3: ; %loop.body138; GFX10-NEXT: ; in Loop: Header=BB2_2 Depth=1139; GFX10-NEXT: v_mov_b32_e32 v5, s3140; GFX10-NEXT: v_mov_b32_e32 v4, s2141; GFX10-NEXT: s_add_i32 s2, s0, 1142; GFX10-NEXT: s_cmpk_lt_u32 s0, 0x64143; GFX10-NEXT: s_cselect_b32 s0, exec_lo, 0144; GFX10-NEXT: v_add_co_u32 v4, vcc_lo, v0, v4145; GFX10-NEXT: v_add_co_ci_u32_e32 v5, vcc_lo, v1, v5, vcc_lo146; GFX10-NEXT: s_andn2_b32 s3, s5, exec_lo147; GFX10-NEXT: s_and_b32 s0, exec_lo, s0148; GFX10-NEXT: s_or_b32 s5, s3, s0149; GFX10-NEXT: global_load_dword v6, v[4:5], off150; GFX10-NEXT: s_mov_b32 s0, s2151; GFX10-NEXT: s_waitcnt vmcnt(0)152; GFX10-NEXT: v_add_nc_u32_e32 v6, 1, v6153; GFX10-NEXT: global_store_dword v[4:5], v6, off154; GFX10-NEXT: s_branch .LBB2_1155; GFX10-NEXT: .LBB2_4: ; %exit156; GFX10-NEXT: s_endpgm157entry:158 br label %A159 160A:161 %counter = phi i32 [ %counter.plus.1, %loop.body ], [ 0, %entry ]162 %a.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %a, i32 %counter163 %a.val = load i32, ptr addrspace(1) %a.plus.counter164 %a.cond = icmp eq i32 %a.val, 0165 br i1 %a.cond, label %exit, label %loop.body166 167loop.body:168 %x.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %x, i32 %counter169 %x.val = load i32, ptr addrspace(1) %x.plus.counter170 %x.val.plus.1 = add i32 %x.val, 1171 store i32 %x.val.plus.1, ptr addrspace(1) %x.plus.counter172 %counter.plus.1 = add i32 %counter, 1173 %x.cond = icmp ult i32 %counter, 100174 br i1 %x.cond, label %exit, label %A175 176exit:177 ret void178}179 180define amdgpu_cs void @loop_with_2breaks(ptr addrspace(1) %x, ptr addrspace(1) %a, ptr addrspace(1) %b) {181; GFX10-LABEL: loop_with_2breaks:182; GFX10: ; %bb.0: ; %entry183; GFX10-NEXT: s_mov_b32 s0, 0184; GFX10-NEXT: s_mov_b32 s4, 0185; GFX10-NEXT: ; implicit-def: $sgpr5186; GFX10-NEXT: s_branch .LBB3_3187; GFX10-NEXT: .LBB3_1: ; %Flow3188; GFX10-NEXT: ; in Loop: Header=BB3_3 Depth=1189; GFX10-NEXT: s_waitcnt_depctr depctr_vm_vsrc(0)190; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s7191; GFX10-NEXT: s_andn2_b32 s2, s5, exec_lo192; GFX10-NEXT: s_and_b32 s3, exec_lo, s6193; GFX10-NEXT: s_or_b32 s5, s2, s3194; GFX10-NEXT: .LBB3_2: ; %Flow195; GFX10-NEXT: ; in Loop: Header=BB3_3 Depth=1196; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s1197; GFX10-NEXT: s_and_b32 s1, exec_lo, s5198; GFX10-NEXT: s_or_b32 s4, s1, s4199; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4200; GFX10-NEXT: s_cbranch_execz .LBB3_6201; GFX10-NEXT: .LBB3_3: ; %A202; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1203; GFX10-NEXT: s_ashr_i32 s1, s0, 31204; GFX10-NEXT: s_lshl_b64 s[2:3], s[0:1], 2205; GFX10-NEXT: s_andn2_b32 s1, s5, exec_lo206; GFX10-NEXT: v_mov_b32_e32 v7, s3207; GFX10-NEXT: v_mov_b32_e32 v6, s2208; GFX10-NEXT: s_and_b32 s5, exec_lo, exec_lo209; GFX10-NEXT: s_or_b32 s5, s1, s5210; GFX10-NEXT: v_add_co_u32 v6, vcc_lo, v2, v6211; GFX10-NEXT: v_add_co_ci_u32_e32 v7, vcc_lo, v3, v7, vcc_lo212; GFX10-NEXT: global_load_dword v6, v[6:7], off213; GFX10-NEXT: s_waitcnt vmcnt(0)214; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v6215; GFX10-NEXT: s_and_saveexec_b32 s1, vcc_lo216; GFX10-NEXT: s_cbranch_execz .LBB3_2217; GFX10-NEXT: ; %bb.4: ; %B218; GFX10-NEXT: ; in Loop: Header=BB3_3 Depth=1219; GFX10-NEXT: v_mov_b32_e32 v7, s3220; GFX10-NEXT: v_mov_b32_e32 v6, s2221; GFX10-NEXT: s_mov_b32 s6, exec_lo222; GFX10-NEXT: v_add_co_u32 v6, vcc_lo, v4, v6223; GFX10-NEXT: v_add_co_ci_u32_e32 v7, vcc_lo, v5, v7, vcc_lo224; GFX10-NEXT: global_load_dword v6, v[6:7], off225; GFX10-NEXT: s_waitcnt vmcnt(0)226; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v6227; GFX10-NEXT: s_and_saveexec_b32 s7, vcc_lo228; GFX10-NEXT: s_cbranch_execz .LBB3_1229; GFX10-NEXT: ; %bb.5: ; %loop.body230; GFX10-NEXT: ; in Loop: Header=BB3_3 Depth=1231; GFX10-NEXT: v_mov_b32_e32 v7, s3232; GFX10-NEXT: v_mov_b32_e32 v6, s2233; GFX10-NEXT: s_add_i32 s2, s0, 1234; GFX10-NEXT: s_cmpk_lt_u32 s0, 0x64235; GFX10-NEXT: s_cselect_b32 s0, exec_lo, 0236; GFX10-NEXT: v_add_co_u32 v6, vcc_lo, v0, v6237; GFX10-NEXT: v_add_co_ci_u32_e32 v7, vcc_lo, v1, v7, vcc_lo238; GFX10-NEXT: s_andn2_b32 s3, s6, exec_lo239; GFX10-NEXT: s_and_b32 s0, exec_lo, s0240; GFX10-NEXT: s_or_b32 s6, s3, s0241; GFX10-NEXT: global_load_dword v8, v[6:7], off242; GFX10-NEXT: s_mov_b32 s0, s2243; GFX10-NEXT: s_waitcnt vmcnt(0)244; GFX10-NEXT: v_add_nc_u32_e32 v8, 1, v8245; GFX10-NEXT: global_store_dword v[6:7], v8, off246; GFX10-NEXT: s_branch .LBB3_1247; GFX10-NEXT: .LBB3_6: ; %exit248; GFX10-NEXT: s_endpgm249entry:250 br label %A251 252A:253 %counter = phi i32 [ %counter.plus.1, %loop.body ], [ 0, %entry ]254 %a.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %a, i32 %counter255 %a.val = load i32, ptr addrspace(1) %a.plus.counter256 %a.cond = icmp eq i32 %a.val, 0257 br i1 %a.cond, label %exit, label %B258 259B:260 %b.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %b, i32 %counter261 %b.val = load i32, ptr addrspace(1) %b.plus.counter262 %b.cond = icmp eq i32 %b.val, 0263 br i1 %b.cond, label %exit, label %loop.body264 265loop.body:266 %x.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %x, i32 %counter267 %x.val = load i32, ptr addrspace(1) %x.plus.counter268 %x.val.plus.1 = add i32 %x.val, 1269 store i32 %x.val.plus.1, ptr addrspace(1) %x.plus.counter270 %counter.plus.1 = add i32 %counter, 1271 %x.cond = icmp ult i32 %counter, 100272 br i1 %x.cond, label %exit, label %A273 274exit:275 ret void276}277 278define amdgpu_cs void @loop_with_3breaks(ptr addrspace(1) %x, ptr addrspace(1) %a, ptr addrspace(1) %b, ptr addrspace(1) %c) {279; GFX10-LABEL: loop_with_3breaks:280; GFX10: ; %bb.0: ; %entry281; GFX10-NEXT: s_mov_b32 s0, 0282; GFX10-NEXT: s_mov_b32 s4, 0283; GFX10-NEXT: ; implicit-def: $sgpr5284; GFX10-NEXT: s_branch .LBB4_4285; GFX10-NEXT: .LBB4_1: ; %Flow5286; GFX10-NEXT: ; in Loop: Header=BB4_4 Depth=1287; GFX10-NEXT: s_waitcnt_depctr depctr_vm_vsrc(0)288; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s9289; GFX10-NEXT: s_andn2_b32 s2, s6, exec_lo290; GFX10-NEXT: s_and_b32 s3, exec_lo, s8291; GFX10-NEXT: s_or_b32 s6, s2, s3292; GFX10-NEXT: .LBB4_2: ; %Flow4293; GFX10-NEXT: ; in Loop: Header=BB4_4 Depth=1294; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s7295; GFX10-NEXT: s_andn2_b32 s2, s5, exec_lo296; GFX10-NEXT: s_and_b32 s3, exec_lo, s6297; GFX10-NEXT: s_or_b32 s5, s2, s3298; GFX10-NEXT: .LBB4_3: ; %Flow299; GFX10-NEXT: ; in Loop: Header=BB4_4 Depth=1300; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s1301; GFX10-NEXT: s_and_b32 s1, exec_lo, s5302; GFX10-NEXT: s_or_b32 s4, s1, s4303; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4304; GFX10-NEXT: s_cbranch_execz .LBB4_8305; GFX10-NEXT: .LBB4_4: ; %A306; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1307; GFX10-NEXT: s_ashr_i32 s1, s0, 31308; GFX10-NEXT: s_lshl_b64 s[2:3], s[0:1], 2309; GFX10-NEXT: s_andn2_b32 s1, s5, exec_lo310; GFX10-NEXT: v_mov_b32_e32 v9, s3311; GFX10-NEXT: v_mov_b32_e32 v8, s2312; GFX10-NEXT: s_and_b32 s5, exec_lo, exec_lo313; GFX10-NEXT: s_or_b32 s5, s1, s5314; GFX10-NEXT: v_add_co_u32 v8, vcc_lo, v2, v8315; GFX10-NEXT: v_add_co_ci_u32_e32 v9, vcc_lo, v3, v9, vcc_lo316; GFX10-NEXT: global_load_dword v8, v[8:9], off317; GFX10-NEXT: s_waitcnt vmcnt(0)318; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v8319; GFX10-NEXT: s_and_saveexec_b32 s1, vcc_lo320; GFX10-NEXT: s_cbranch_execz .LBB4_3321; GFX10-NEXT: ; %bb.5: ; %B322; GFX10-NEXT: ; in Loop: Header=BB4_4 Depth=1323; GFX10-NEXT: v_mov_b32_e32 v9, s3324; GFX10-NEXT: v_mov_b32_e32 v8, s2325; GFX10-NEXT: s_mov_b32 s6, exec_lo326; GFX10-NEXT: v_add_co_u32 v8, vcc_lo, v4, v8327; GFX10-NEXT: v_add_co_ci_u32_e32 v9, vcc_lo, v5, v9, vcc_lo328; GFX10-NEXT: global_load_dword v8, v[8:9], off329; GFX10-NEXT: s_waitcnt vmcnt(0)330; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v8331; GFX10-NEXT: s_and_saveexec_b32 s7, vcc_lo332; GFX10-NEXT: s_cbranch_execz .LBB4_2333; GFX10-NEXT: ; %bb.6: ; %C334; GFX10-NEXT: ; in Loop: Header=BB4_4 Depth=1335; GFX10-NEXT: v_mov_b32_e32 v9, s3336; GFX10-NEXT: v_mov_b32_e32 v8, s2337; GFX10-NEXT: s_mov_b32 s8, exec_lo338; GFX10-NEXT: v_add_co_u32 v8, vcc_lo, v6, v8339; GFX10-NEXT: v_add_co_ci_u32_e32 v9, vcc_lo, v7, v9, vcc_lo340; GFX10-NEXT: global_load_dword v8, v[8:9], off341; GFX10-NEXT: s_waitcnt vmcnt(0)342; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v8343; GFX10-NEXT: s_and_saveexec_b32 s9, vcc_lo344; GFX10-NEXT: s_cbranch_execz .LBB4_1345; GFX10-NEXT: ; %bb.7: ; %loop.body346; GFX10-NEXT: ; in Loop: Header=BB4_4 Depth=1347; GFX10-NEXT: v_mov_b32_e32 v9, s3348; GFX10-NEXT: v_mov_b32_e32 v8, s2349; GFX10-NEXT: s_add_i32 s2, s0, 1350; GFX10-NEXT: s_cmpk_lt_u32 s0, 0x64351; GFX10-NEXT: s_cselect_b32 s0, exec_lo, 0352; GFX10-NEXT: v_add_co_u32 v8, vcc_lo, v0, v8353; GFX10-NEXT: v_add_co_ci_u32_e32 v9, vcc_lo, v1, v9, vcc_lo354; GFX10-NEXT: s_andn2_b32 s3, s8, exec_lo355; GFX10-NEXT: s_and_b32 s0, exec_lo, s0356; GFX10-NEXT: s_or_b32 s8, s3, s0357; GFX10-NEXT: global_load_dword v10, v[8:9], off358; GFX10-NEXT: s_mov_b32 s0, s2359; GFX10-NEXT: s_waitcnt vmcnt(0)360; GFX10-NEXT: v_add_nc_u32_e32 v10, 1, v10361; GFX10-NEXT: global_store_dword v[8:9], v10, off362; GFX10-NEXT: s_branch .LBB4_1363; GFX10-NEXT: .LBB4_8: ; %exit364; GFX10-NEXT: s_endpgm365entry:366 br label %A367 368A:369 %counter = phi i32 [ %counter.plus.1, %loop.body ], [ 0, %entry ]370 %a.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %a, i32 %counter371 %a.val = load i32, ptr addrspace(1) %a.plus.counter372 %a.cond = icmp eq i32 %a.val, 0373 br i1 %a.cond, label %exit, label %B374 375B:376 %b.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %b, i32 %counter377 %b.val = load i32, ptr addrspace(1) %b.plus.counter378 %b.cond = icmp eq i32 %b.val, 0379 br i1 %b.cond, label %exit, label %C380 381C:382 %c.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %c, i32 %counter383 %c.val = load i32, ptr addrspace(1) %c.plus.counter384 %c.cond = icmp eq i32 %c.val, 0385 br i1 %c.cond, label %exit, label %loop.body386 387loop.body:388 %x.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %x, i32 %counter389 %x.val = load i32, ptr addrspace(1) %x.plus.counter390 %x.val.plus.1 = add i32 %x.val, 1391 store i32 %x.val.plus.1, ptr addrspace(1) %x.plus.counter392 %counter.plus.1 = add i32 %counter, 1393 %x.cond = icmp ult i32 %counter, 100394 br i1 %x.cond, label %exit, label %A395 396exit:397 ret void398}399 400; Divergent condition if with body, ending with break. This is loop with two401; exits but structurizer will create phi that will track exit from break402; and move break.body after the loop. Loop will then have one exit and phi403; used outside of the loop by condition used to enter the break.body.404define amdgpu_cs void @loop_with_div_break_with_body(ptr addrspace(1) %x, ptr addrspace(1) %a, ptr addrspace(1) %a.break) {405; GFX10-LABEL: loop_with_div_break_with_body:406; GFX10: ; %bb.0: ; %entry407; GFX10-NEXT: s_mov_b32 s0, 0408; GFX10-NEXT: s_mov_b32 s4, 0409; GFX10-NEXT: ; implicit-def: $sgpr6410; GFX10-NEXT: ; implicit-def: $sgpr7411; GFX10-NEXT: ; implicit-def: $sgpr5412; GFX10-NEXT: s_branch .LBB5_2413; GFX10-NEXT: .LBB5_1: ; %Flow414; GFX10-NEXT: ; in Loop: Header=BB5_2 Depth=1415; GFX10-NEXT: s_waitcnt_depctr depctr_vm_vsrc(0)416; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s1417; GFX10-NEXT: s_and_b32 s1, exec_lo, s6418; GFX10-NEXT: s_or_b32 s4, s1, s4419; GFX10-NEXT: s_andn2_b32 s1, s5, exec_lo420; GFX10-NEXT: s_and_b32 s2, exec_lo, s7421; GFX10-NEXT: s_or_b32 s5, s1, s2422; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4423; GFX10-NEXT: s_cbranch_execz .LBB5_4424; GFX10-NEXT: .LBB5_2: ; %A425; GFX10-NEXT: ; =>This Inner Loop Header: Depth=1426; GFX10-NEXT: s_ashr_i32 s1, s0, 31427; GFX10-NEXT: s_mov_b32 s8, exec_lo428; GFX10-NEXT: s_lshl_b64 s[2:3], s[0:1], 2429; GFX10-NEXT: s_andn2_b32 s1, s7, exec_lo430; GFX10-NEXT: v_mov_b32_e32 v7, s3431; GFX10-NEXT: v_mov_b32_e32 v6, s2432; GFX10-NEXT: s_and_b32 s7, exec_lo, s8433; GFX10-NEXT: s_andn2_b32 s6, s6, exec_lo434; GFX10-NEXT: s_and_b32 s8, exec_lo, exec_lo435; GFX10-NEXT: s_or_b32 s7, s1, s7436; GFX10-NEXT: v_add_co_u32 v6, vcc_lo, v2, v6437; GFX10-NEXT: v_add_co_ci_u32_e32 v7, vcc_lo, v3, v7, vcc_lo438; GFX10-NEXT: s_or_b32 s6, s6, s8439; GFX10-NEXT: global_load_dword v6, v[6:7], off440; GFX10-NEXT: s_waitcnt vmcnt(0)441; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v6442; GFX10-NEXT: s_and_saveexec_b32 s1, vcc_lo443; GFX10-NEXT: s_cbranch_execz .LBB5_1444; GFX10-NEXT: ; %bb.3: ; %loop.body445; GFX10-NEXT: ; in Loop: Header=BB5_2 Depth=1446; GFX10-NEXT: v_mov_b32_e32 v7, s3447; GFX10-NEXT: v_mov_b32_e32 v6, s2448; GFX10-NEXT: s_add_i32 s2, s0, 1449; GFX10-NEXT: s_cmpk_lt_u32 s0, 0x64450; GFX10-NEXT: s_cselect_b32 s0, exec_lo, 0451; GFX10-NEXT: v_add_co_u32 v6, vcc_lo, v0, v6452; GFX10-NEXT: v_add_co_ci_u32_e32 v7, vcc_lo, v1, v7, vcc_lo453; GFX10-NEXT: s_andn2_b32 s3, s7, exec_lo454; GFX10-NEXT: s_and_b32 s7, exec_lo, 0455; GFX10-NEXT: s_andn2_b32 s6, s6, exec_lo456; GFX10-NEXT: global_load_dword v8, v[6:7], off457; GFX10-NEXT: s_and_b32 s0, exec_lo, s0458; GFX10-NEXT: s_or_b32 s7, s3, s7459; GFX10-NEXT: s_or_b32 s6, s6, s0460; GFX10-NEXT: s_mov_b32 s0, s2461; GFX10-NEXT: s_waitcnt vmcnt(0)462; GFX10-NEXT: v_add_nc_u32_e32 v8, 1, v8463; GFX10-NEXT: global_store_dword v[6:7], v8, off464; GFX10-NEXT: s_branch .LBB5_1465; GFX10-NEXT: .LBB5_4: ; %loop.exit.guard466; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s4467; GFX10-NEXT: s_and_saveexec_b32 s0, s5468; GFX10-NEXT: s_xor_b32 s0, exec_lo, s0469; GFX10-NEXT: s_cbranch_execz .LBB5_6470; GFX10-NEXT: ; %bb.5: ; %break.body471; GFX10-NEXT: v_mov_b32_e32 v0, 10472; GFX10-NEXT: global_store_dword v[4:5], v0, off473; GFX10-NEXT: .LBB5_6: ; %exit474; GFX10-NEXT: s_endpgm475entry:476 br label %A477 478A:479 %counter = phi i32 [ %counter.plus.1, %loop.body ], [ 0, %entry ]480 %a.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %a, i32 %counter481 %a.val = load i32, ptr addrspace(1) %a.plus.counter482 %a.cond = icmp eq i32 %a.val, 0483 br i1 %a.cond, label %break.body, label %loop.body484 485break.body:486 store i32 10, ptr addrspace(1) %a.break487 br label %exit488 489 490loop.body:491 %x.plus.counter = getelementptr inbounds i32, ptr addrspace(1) %x, i32 %counter492 %x.val = load i32, ptr addrspace(1) %x.plus.counter493 %x.val.plus.1 = add i32 %x.val, 1494 store i32 %x.val.plus.1, ptr addrspace(1) %x.plus.counter495 %counter.plus.1 = add i32 %counter, 1496 %x.cond = icmp ult i32 %counter, 100497 br i1 %x.cond, label %exit, label %A498 499exit:500 ret void501}502 503; Snippet from test generated by the GraphicsFuzz tool, frontend generates ir504; with irreducible control flow graph.505 506; int loop(int x, int y, int a0, int a1, int a2, int a3, int a4) {507; do {508; if (y < a2) {509; do {510; } while (x < a2);511; }512; if (x < a3) {513; return a1;514; }515; } while (y < a2);516; return a0;517; }518 519; This test is also interesting because it had phi with three incomings520; After fa4cc9ddd58eb9fef2497e678873ff3b495340a3, FixIrreducible does not521; generate phi with three incomings. There is a mir test with such phi.522define amdgpu_ps i32 @irreducible_cfg(i32 %x, i32 %y, i32 %a0, i32 %a1, i32 %a2, i32 %a3) {523; GFX10-LABEL: irreducible_cfg:524; GFX10: ; %bb.0: ; %.entry525; GFX10-NEXT: v_cmp_gt_i32_e32 vcc_lo, v4, v1526; GFX10-NEXT: s_mov_b32 s0, exec_lo527; GFX10-NEXT: s_mov_b32 s1, 0528; GFX10-NEXT: s_and_b32 s2, s0, 1529; GFX10-NEXT: s_xor_b32 s0, vcc_lo, s0530; GFX10-NEXT: s_cmp_lg_u32 s2, 0531; GFX10-NEXT: ; implicit-def: $sgpr2532; GFX10-NEXT: s_cselect_b32 s3, exec_lo, 0533; GFX10-NEXT: s_branch .LBB6_2534; GFX10-NEXT: .LBB6_1: ; %Flow2535; GFX10-NEXT: ; in Loop: Header=BB6_2 Depth=1536; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s6537; GFX10-NEXT: s_and_b32 s4, exec_lo, s5538; GFX10-NEXT: s_mov_b32 s0, exec_lo539; GFX10-NEXT: s_or_b32 s1, s4, s1540; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s1541; GFX10-NEXT: s_cbranch_execz .LBB6_8542; GFX10-NEXT: .LBB6_2: ; %irr.guard543; GFX10-NEXT: ; =>This Loop Header: Depth=1544; GFX10-NEXT: ; Child Loop BB6_6 Depth 2545; GFX10-NEXT: s_mov_b32 s4, exec_lo546; GFX10-NEXT: s_and_saveexec_b32 s5, s0547; GFX10-NEXT: s_xor_b32 s5, exec_lo, s5548; GFX10-NEXT: ; %bb.3: ; %.loopexit549; GFX10-NEXT: ; in Loop: Header=BB6_2 Depth=1550; GFX10-NEXT: v_cmp_gt_i32_e64 s0, v5, v0551; GFX10-NEXT: s_mov_b32 s6, exec_lo552; GFX10-NEXT: s_mov_b32 s7, exec_lo553; GFX10-NEXT: s_xor_b32 s6, vcc_lo, s6554; GFX10-NEXT: s_andn2_b32 s3, s3, exec_lo555; GFX10-NEXT: s_or_b32 s6, s0, s6556; GFX10-NEXT: s_and_b32 s0, exec_lo, s0557; GFX10-NEXT: s_xor_b32 s6, s6, s7558; GFX10-NEXT: s_andn2_b32 s4, s4, exec_lo559; GFX10-NEXT: s_and_b32 s6, exec_lo, s6560; GFX10-NEXT: s_or_b32 s3, s3, s0561; GFX10-NEXT: s_or_b32 s4, s4, s6562; GFX10-NEXT: ; %bb.4: ; %Flow1563; GFX10-NEXT: ; in Loop: Header=BB6_2 Depth=1564; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s5565; GFX10-NEXT: s_andn2_b32 s0, s2, exec_lo566; GFX10-NEXT: s_and_b32 s2, exec_lo, s3567; GFX10-NEXT: s_mov_b32 s5, exec_lo568; GFX10-NEXT: s_or_b32 s2, s0, s2569; GFX10-NEXT: s_and_saveexec_b32 s6, s4570; GFX10-NEXT: s_cbranch_execz .LBB6_1571; GFX10-NEXT: ; %bb.5: ; %.preheader572; GFX10-NEXT: ; in Loop: Header=BB6_2 Depth=1573; GFX10-NEXT: v_cmp_le_i32_e64 s0, v4, v0574; GFX10-NEXT: s_mov_b32 s4, 0575; GFX10-NEXT: .LBB6_6: ; %.inner_loop576; GFX10-NEXT: ; Parent Loop BB6_2 Depth=1577; GFX10-NEXT: ; => This Inner Loop Header: Depth=2578; GFX10-NEXT: s_and_b32 s7, exec_lo, s0579; GFX10-NEXT: s_or_b32 s4, s7, s4580; GFX10-NEXT: s_andn2_b32 exec_lo, exec_lo, s4581; GFX10-NEXT: s_cbranch_execnz .LBB6_6582; GFX10-NEXT: ; %bb.7: ; %Flow583; GFX10-NEXT: ; in Loop: Header=BB6_2 Depth=1584; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s4585; GFX10-NEXT: s_andn2_b32 s0, s5, exec_lo586; GFX10-NEXT: s_and_b32 s4, exec_lo, 0587; GFX10-NEXT: s_or_b32 s5, s0, s4588; GFX10-NEXT: s_branch .LBB6_1589; GFX10-NEXT: .LBB6_8: ; %.exit590; GFX10-NEXT: s_or_b32 exec_lo, exec_lo, s1591; GFX10-NEXT: v_cndmask_b32_e64 v0, v2, v3, s2592; GFX10-NEXT: v_readfirstlane_b32 s0, v0593; GFX10-NEXT: ; return to shader part epilog594.entry:595 %.y_lt_a2 = icmp sgt i32 %a2, %y596 %.x_lt_a2 = icmp sgt i32 %a2, %x597 %.x_lt_a3 = icmp sgt i32 %a3, %x598 br i1 %.y_lt_a2, label %.preheader, label %.loopexit ; first iteration, jump to inner loop if 'y < a2' or start with 'if (x < a3)'599 600.preheader: ; if (y < a2),601 br label %.inner_loop602 603.inner_loop: ; do while x < a2604 br i1 %.x_lt_a2, label %.inner_loop, label %.loopexit605 606.loopexit: ; if x < a3607 %not.inner_loop = xor i1 %.y_lt_a2, true608 %brmerge = select i1 %.x_lt_a3, i1 true, i1 %not.inner_loop ; exit loop if 'x < a3' or 'loop ends since !(y < a2)'609 %.ret = select i1 %.x_lt_a3, i32 %a1, i32 %a0 ; select retrun value a1 'x < a3' or a0 'loop ends'610 br i1 %brmerge, label %.exit, label %.preheader611 612.exit:613 ret i32 %.ret614}615 616