brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.1 KiB · 5c57d35 Raw
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