255 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -mtriple=amdgcn-- -lowerswitch -structurizecfg -si-annotate-control-flow < %s | FileCheck -check-prefix=OPT %s3; RUN: llc -mtriple=amdgcn < %s | FileCheck -check-prefix=GCN %s4 5; Ensure two if.break calls, for both the inner and outer loops6; FIXME: duplicate comparison7define amdgpu_vs void @multi_else_break(<4 x float> %vec, i32 %ub, i32 %cont) {8; OPT-LABEL: define amdgpu_vs void @multi_else_break(9; OPT-SAME: <4 x float> [[VEC:%.*]], i32 [[UB:%.*]], i32 [[CONT:%.*]]) {10; OPT-NEXT: [[MAIN_BODY:.*]]:11; OPT-NEXT: br label %[[LOOP_OUTER:.*]]12; OPT: [[LOOP_OUTER]]:13; OPT-NEXT: [[PHI_BROKEN2:%.*]] = phi i64 [ [[TMP8:%.*]], %[[FLOW1:.*]] ], [ 0, %[[MAIN_BODY]] ]14; OPT-NEXT: [[TMP43:%.*]] = phi i32 [ 0, %[[MAIN_BODY]] ], [ [[TMP3:%.*]], %[[FLOW1]] ]15; OPT-NEXT: br label %[[LOOP:.*]]16; OPT: [[LOOP]]:17; OPT-NEXT: [[PHI_BROKEN:%.*]] = phi i64 [ [[TMP6:%.*]], %[[FLOW:.*]] ], [ 0, %[[LOOP_OUTER]] ]18; OPT-NEXT: [[TMP45:%.*]] = phi i32 [ [[TMP43]], %[[LOOP_OUTER]] ], [ [[TMP3]], %[[FLOW]] ]19; OPT-NEXT: [[TMP48:%.*]] = icmp slt i32 [[TMP45]], [[UB]]20; OPT-NEXT: [[TMP0:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP48]])21; OPT-NEXT: [[TMP1:%.*]] = extractvalue { i1, i64 } [[TMP0]], 022; OPT-NEXT: [[TMP2:%.*]] = extractvalue { i1, i64 } [[TMP0]], 123; OPT-NEXT: br i1 [[TMP1]], label %[[ENDIF:.*]], label %[[FLOW]]24; OPT: [[FLOW]]:25; OPT-NEXT: [[TMP3]] = phi i32 [ [[TMP47:%.*]], %[[ENDIF]] ], [ poison, %[[LOOP]] ]26; OPT-NEXT: [[TMP4:%.*]] = phi i1 [ [[TMP51:%.*]], %[[ENDIF]] ], [ true, %[[LOOP]] ]27; OPT-NEXT: [[TMP5:%.*]] = phi i1 [ [[TMP51_INV:%.*]], %[[ENDIF]] ], [ true, %[[LOOP]] ]28; OPT-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP2]])29; OPT-NEXT: [[TMP6]] = call i64 @llvm.amdgcn.if.break.i64(i1 [[TMP5]], i64 [[PHI_BROKEN]])30; OPT-NEXT: [[TMP7:%.*]] = call i1 @llvm.amdgcn.loop.i64(i64 [[TMP6]])31; OPT-NEXT: br i1 [[TMP7]], label %[[FLOW1]], label %[[LOOP]]32; OPT: [[FLOW1]]:33; OPT-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP6]])34; OPT-NEXT: [[TMP8]] = call i64 @llvm.amdgcn.if.break.i64(i1 [[TMP4]], i64 [[PHI_BROKEN2]])35; OPT-NEXT: [[TMP9:%.*]] = call i1 @llvm.amdgcn.loop.i64(i64 [[TMP8]])36; OPT-NEXT: br i1 [[TMP9]], label %[[IF:.*]], label %[[LOOP_OUTER]]37; OPT: [[IF]]:38; OPT-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP8]])39; OPT-NEXT: ret void40; OPT: [[ENDIF]]:41; OPT-NEXT: [[TMP47]] = add i32 [[TMP45]], 142; OPT-NEXT: [[TMP51]] = icmp eq i32 [[TMP47]], [[CONT]]43; OPT-NEXT: [[TMP51_INV]] = xor i1 [[TMP51]], true44; OPT-NEXT: br label %[[FLOW]]45;46; GCN-LABEL: multi_else_break:47; GCN: ; %bb.0: ; %main_body48; GCN-NEXT: v_mov_b32_e32 v0, 049; GCN-NEXT: s_mov_b64 s[0:1], 050; GCN-NEXT: s_branch .LBB0_251; GCN-NEXT: .LBB0_1: ; %loop.exit.guard52; GCN-NEXT: ; in Loop: Header=BB0_2 Depth=153; GCN-NEXT: s_or_b64 exec, exec, s[4:5]54; GCN-NEXT: s_and_b64 s[2:3], exec, s[2:3]55; GCN-NEXT: s_or_b64 s[0:1], s[2:3], s[0:1]56; GCN-NEXT: s_andn2_b64 exec, exec, s[0:1]57; GCN-NEXT: s_cbranch_execz .LBB0_658; GCN-NEXT: .LBB0_2: ; %LOOP.outer59; GCN-NEXT: ; =>This Loop Header: Depth=160; GCN-NEXT: ; Child Loop BB0_4 Depth 261; GCN-NEXT: ; implicit-def: $sgpr2_sgpr362; GCN-NEXT: ; implicit-def: $sgpr8_sgpr963; GCN-NEXT: ; implicit-def: $sgpr6_sgpr764; GCN-NEXT: s_mov_b64 s[4:5], 065; GCN-NEXT: s_branch .LBB0_466; GCN-NEXT: .LBB0_3: ; %Flow67; GCN-NEXT: ; in Loop: Header=BB0_4 Depth=268; GCN-NEXT: s_or_b64 exec, exec, s[10:11]69; GCN-NEXT: s_and_b64 s[10:11], exec, s[8:9]70; GCN-NEXT: s_or_b64 s[4:5], s[10:11], s[4:5]71; GCN-NEXT: s_andn2_b64 s[2:3], s[2:3], exec72; GCN-NEXT: s_and_b64 s[10:11], s[6:7], exec73; GCN-NEXT: s_or_b64 s[2:3], s[2:3], s[10:11]74; GCN-NEXT: s_andn2_b64 exec, exec, s[4:5]75; GCN-NEXT: s_cbranch_execz .LBB0_176; GCN-NEXT: .LBB0_4: ; %LOOP77; GCN-NEXT: ; Parent Loop BB0_2 Depth=178; GCN-NEXT: ; => This Inner Loop Header: Depth=279; GCN-NEXT: v_cmp_lt_i32_e32 vcc, v0, v480; GCN-NEXT: s_or_b64 s[6:7], s[6:7], exec81; GCN-NEXT: s_or_b64 s[8:9], s[8:9], exec82; GCN-NEXT: s_and_saveexec_b64 s[10:11], vcc83; GCN-NEXT: s_cbranch_execz .LBB0_384; GCN-NEXT: ; %bb.5: ; %ENDIF85; GCN-NEXT: ; in Loop: Header=BB0_4 Depth=286; GCN-NEXT: v_add_i32_e32 v0, vcc, 1, v087; GCN-NEXT: s_andn2_b64 s[6:7], s[6:7], exec88; GCN-NEXT: v_cmp_ne_u32_e32 vcc, v5, v089; GCN-NEXT: s_andn2_b64 s[8:9], s[8:9], exec90; GCN-NEXT: s_and_b64 s[12:13], vcc, exec91; GCN-NEXT: s_or_b64 s[8:9], s[8:9], s[12:13]92; GCN-NEXT: s_branch .LBB0_393; GCN-NEXT: .LBB0_6: ; %IF94; GCN-NEXT: s_endpgm95main_body:96 br label %LOOP.outer97 98LOOP.outer: ; preds = %ENDIF, %main_body99 %tmp43 = phi i32 [ 0, %main_body ], [ %tmp47, %ENDIF ]100 br label %LOOP101 102LOOP: ; preds = %ENDIF, %LOOP.outer103 %tmp45 = phi i32 [ %tmp43, %LOOP.outer ], [ %tmp47, %ENDIF ]104 %tmp48 = icmp slt i32 %tmp45, %ub105 br i1 %tmp48, label %ENDIF, label %IF106 107IF: ; preds = %LOOP108 ret void109 110ENDIF: ; preds = %LOOP111 %tmp47 = add i32 %tmp45, 1112 %tmp51 = icmp eq i32 %tmp47, %cont113 br i1 %tmp51, label %LOOP, label %LOOP.outer114}115 116define amdgpu_kernel void @multi_if_break_loop(i32 %arg) #0 {117; OPT-LABEL: define amdgpu_kernel void @multi_if_break_loop(118; OPT-SAME: i32 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] {119; OPT-NEXT: [[BB:.*]]:120; OPT-NEXT: [[ID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()121; OPT-NEXT: [[TMP:%.*]] = sub i32 [[ID]], [[ARG]]122; OPT-NEXT: br label %[[BB1:.*]]123; OPT: [[BB1]]:124; OPT-NEXT: [[PHI_BROKEN:%.*]] = phi i64 [ [[TMP4:%.*]], %[[FLOW4:.*]] ], [ 0, %[[BB]] ]125; OPT-NEXT: [[LSR_IV:%.*]] = phi i32 [ poison, %[[BB]] ], [ [[TMP2:%.*]], %[[FLOW4]] ]126; OPT-NEXT: [[TMP2]] = add i32 [[LSR_IV]], 1127; OPT-NEXT: [[CMP0:%.*]] = icmp slt i32 [[TMP2]], 0128; OPT-NEXT: [[LOAD0:%.*]] = load volatile i32, ptr addrspace(1) poison, align 4129; OPT-NEXT: br label %[[NODEBLOCK:.*]]130; OPT: [[NODEBLOCK]]:131; OPT-NEXT: [[PIVOT:%.*]] = icmp sge i32 [[LOAD0]], 1132; OPT-NEXT: br i1 [[PIVOT]], label %[[LEAFBLOCK1:.*]], label %[[FLOW:.*]]133; OPT: [[LEAFBLOCK1]]:134; OPT-NEXT: [[SWITCHLEAF2:%.*]] = icmp eq i32 [[LOAD0]], 1135; OPT-NEXT: br i1 [[SWITCHLEAF2]], label %[[CASE1:.*]], label %[[FLOW3:.*]]136; OPT: [[FLOW3]]:137; OPT-NEXT: [[TMP1:%.*]] = phi i1 [ [[CMP2:%.*]], %[[CASE1]] ], [ true, %[[LEAFBLOCK1]] ]138; OPT-NEXT: br label %[[FLOW]]139; OPT: [[LEAFBLOCK:.*]]:140; OPT-NEXT: [[SWITCHLEAF:%.*]] = icmp eq i32 [[LOAD0]], 0141; OPT-NEXT: br i1 [[SWITCHLEAF]], label %[[CASE0:.*]], label %[[FLOW5:.*]]142; OPT: [[FLOW4]]:143; OPT-NEXT: [[TMP3:%.*]] = phi i1 [ [[TMP10:%.*]], %[[FLOW5]] ], [ [[TMP7:%.*]], %[[FLOW]] ]144; OPT-NEXT: [[TMP4]] = call i64 @llvm.amdgcn.if.break.i64(i1 [[TMP3]], i64 [[PHI_BROKEN]])145; OPT-NEXT: [[TMP5:%.*]] = call i1 @llvm.amdgcn.loop.i64(i64 [[TMP4]])146; OPT-NEXT: br i1 [[TMP5]], label %[[BB9:.*]], label %[[BB1]]147; OPT: [[CASE0]]:148; OPT-NEXT: [[LOAD1:%.*]] = load volatile i32, ptr addrspace(1) poison, align 4149; OPT-NEXT: [[CMP1:%.*]] = icmp sge i32 [[TMP]], [[LOAD1]]150; OPT-NEXT: br label %[[FLOW5]]151; OPT: [[FLOW]]:152; OPT-NEXT: [[TMP7]] = phi i1 [ [[TMP1]], %[[FLOW3]] ], [ true, %[[NODEBLOCK]] ]153; OPT-NEXT: [[TMP8:%.*]] = phi i1 [ false, %[[FLOW3]] ], [ true, %[[NODEBLOCK]] ]154; OPT-NEXT: br i1 [[TMP8]], label %[[LEAFBLOCK]], label %[[FLOW4]]155; OPT: [[CASE1]]:156; OPT-NEXT: [[LOAD2:%.*]] = load volatile i32, ptr addrspace(1) poison, align 4157; OPT-NEXT: [[CMP2]] = icmp sge i32 [[TMP]], [[LOAD2]]158; OPT-NEXT: br label %[[FLOW3]]159; OPT: [[FLOW5]]:160; OPT-NEXT: [[TMP10]] = phi i1 [ [[CMP1]], %[[CASE0]] ], [ [[TMP7]], %[[LEAFBLOCK]] ]161; OPT-NEXT: br label %[[FLOW4]]162; OPT: [[BB9]]:163; OPT-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP4]])164; OPT-NEXT: ret void165;166; GCN-LABEL: multi_if_break_loop:167; GCN: ; %bb.0: ; %bb168; GCN-NEXT: s_load_dword s2, s[4:5], 0x9169; GCN-NEXT: s_mov_b64 s[0:1], 0170; GCN-NEXT: s_mov_b32 s3, 0xf000171; GCN-NEXT: s_waitcnt lgkmcnt(0)172; GCN-NEXT: v_subrev_i32_e32 v0, vcc, s2, v0173; GCN-NEXT: s_mov_b32 s2, -1174; GCN-NEXT: s_branch .LBB1_2175; GCN-NEXT: .LBB1_1: ; %Flow4176; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1177; GCN-NEXT: s_and_b64 s[4:5], exec, s[4:5]178; GCN-NEXT: s_or_b64 s[0:1], s[4:5], s[0:1]179; GCN-NEXT: s_andn2_b64 exec, exec, s[0:1]180; GCN-NEXT: s_cbranch_execz .LBB1_9181; GCN-NEXT: .LBB1_2: ; %bb1182; GCN-NEXT: ; =>This Inner Loop Header: Depth=1183; GCN-NEXT: buffer_load_dword v1, off, s[0:3], 0 glc184; GCN-NEXT: s_waitcnt vmcnt(0)185; GCN-NEXT: v_readfirstlane_b32 s8, v1186; GCN-NEXT: s_mov_b64 s[4:5], -1187; GCN-NEXT: s_cmp_lt_i32 s8, 1188; GCN-NEXT: s_mov_b64 s[6:7], -1189; GCN-NEXT: s_cbranch_scc1 .LBB1_6190; GCN-NEXT: ; %bb.3: ; %LeafBlock1191; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1192; GCN-NEXT: s_cmp_eq_u32 s8, 1193; GCN-NEXT: s_cbranch_scc0 .LBB1_5194; GCN-NEXT: ; %bb.4: ; %case1195; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1196; GCN-NEXT: buffer_load_dword v1, off, s[0:3], 0 glc197; GCN-NEXT: s_waitcnt vmcnt(0)198; GCN-NEXT: v_cmp_ge_i32_e32 vcc, v0, v1199; GCN-NEXT: s_orn2_b64 s[4:5], vcc, exec200; GCN-NEXT: .LBB1_5: ; %Flow3201; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1202; GCN-NEXT: s_mov_b64 s[6:7], 0203; GCN-NEXT: .LBB1_6: ; %Flow204; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1205; GCN-NEXT: s_and_b64 vcc, exec, s[6:7]206; GCN-NEXT: s_cbranch_vccz .LBB1_1207; GCN-NEXT: ; %bb.7: ; %LeafBlock208; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1209; GCN-NEXT: s_cmp_eq_u32 s8, 0210; GCN-NEXT: s_cbranch_scc0 .LBB1_1211; GCN-NEXT: ; %bb.8: ; %case0212; GCN-NEXT: ; in Loop: Header=BB1_2 Depth=1213; GCN-NEXT: buffer_load_dword v1, off, s[0:3], 0 glc214; GCN-NEXT: s_waitcnt vmcnt(0)215; GCN-NEXT: v_cmp_ge_i32_e32 vcc, v0, v1216; GCN-NEXT: s_andn2_b64 s[4:5], s[4:5], exec217; GCN-NEXT: s_and_b64 s[6:7], vcc, exec218; GCN-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]219; GCN-NEXT: s_branch .LBB1_1220; GCN-NEXT: .LBB1_9: ; %bb9221; GCN-NEXT: s_endpgm222bb:223 %id = call i32 @llvm.amdgcn.workitem.id.x()224 %tmp = sub i32 %id, %arg225 br label %bb1226 227bb1:228 %lsr.iv = phi i32 [ poison, %bb ], [ %lsr.iv.next, %case0 ], [ %lsr.iv.next, %case1 ]229 %lsr.iv.next = add i32 %lsr.iv, 1230 %cmp0 = icmp slt i32 %lsr.iv.next, 0231 %load0 = load volatile i32, ptr addrspace(1) poison, align 4232 switch i32 %load0, label %bb9 [233 i32 0, label %case0234 i32 1, label %case1235 ]236 237case0:238 %load1 = load volatile i32, ptr addrspace(1) poison, align 4239 %cmp1 = icmp slt i32 %tmp, %load1240 br i1 %cmp1, label %bb1, label %bb9241 242case1:243 %load2 = load volatile i32, ptr addrspace(1) poison, align 4244 %cmp2 = icmp slt i32 %tmp, %load2245 br i1 %cmp2, label %bb1, label %bb9246 247bb9:248 ret void249}250 251declare i32 @llvm.amdgcn.workitem.id.x() #1252 253attributes #0 = { nounwind }254attributes #1 = { nounwind readnone }255