226 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py3; RUN: llc -mtriple=amdgcn-amd-amdhsa %s -o - | FileCheck -check-prefix=GCN %s4; RUN: opt -mtriple=amdgcn-amd-amdhsa -lowerswitch -amdgpu-unify-divergent-exit-nodes -verify -structurizecfg -verify -si-annotate-control-flow -verify -S %s -o - | FileCheck -check-prefix=IR %s5 6; A test with a divergent unreachable block and uniform return block. The7; compiler needs to create a regions that includes them so that8; StructurizeCFG correctly transform the CFG, and then SI Annotate Control9; Flow does not fail during annotation.10 11define void @my_func(i32 %0) {12; IR-LABEL: @my_func(13; IR-NEXT: entry:14; IR-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(4) null, align 815; IR-NEXT: br label [[NODEBLOCK:%.*]]16; IR: NodeBlock:17; IR-NEXT: [[PIVOT:%.*]] = icmp sge i32 [[TMP1]], 118; IR-NEXT: br i1 [[PIVOT]], label [[LEAFBLOCK1:%.*]], label [[FLOW:%.*]]19; IR: LeafBlock1:20; IR-NEXT: [[SWITCHLEAF2:%.*]] = icmp ne i32 [[TMP1]], 121; IR-NEXT: br label [[FLOW]]22; IR: Flow:23; IR-NEXT: [[TMP2:%.*]] = phi i1 [ [[SWITCHLEAF2]], [[LEAFBLOCK1]] ], [ false, [[NODEBLOCK]] ]24; IR-NEXT: [[TMP3:%.*]] = phi i1 [ false, [[LEAFBLOCK1]] ], [ true, [[NODEBLOCK]] ]25; IR-NEXT: br i1 [[TMP3]], label [[LEAFBLOCK:%.*]], label [[FLOW11:%.*]]26; IR: LeafBlock:27; IR-NEXT: [[SWITCHLEAF:%.*]] = icmp eq i32 [[TMP1]], 028; IR-NEXT: br i1 [[SWITCHLEAF]], label [[SW_BB2:%.*]], label [[FLOW12:%.*]]29; IR: Flow11:30; IR-NEXT: [[TMP4:%.*]] = phi i1 [ [[TMP9:%.*]], [[FLOW12]] ], [ false, [[FLOW]] ]31; IR-NEXT: [[TMP5:%.*]] = phi i1 [ [[TMP10:%.*]], [[FLOW12]] ], [ [[TMP2]], [[FLOW]] ]32; IR-NEXT: [[TMP6:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP5]])33; IR-NEXT: [[TMP7:%.*]] = extractvalue { i1, i64 } [[TMP6]], 034; IR-NEXT: [[TMP8:%.*]] = extractvalue { i1, i64 } [[TMP6]], 135; IR-NEXT: br i1 [[TMP7]], label [[DO_BODY:%.*]], label [[FLOW17:%.*]]36; IR: sw.bb2:37; IR-NEXT: br label [[NODEBLOCK7:%.*]]38; IR: Flow12:39; IR-NEXT: [[TMP9]] = phi i1 [ [[TMP24:%.*]], [[FLOW15:%.*]] ], [ false, [[LEAFBLOCK]] ]40; IR-NEXT: [[TMP10]] = phi i1 [ [[TMP25:%.*]], [[FLOW15]] ], [ true, [[LEAFBLOCK]] ]41; IR-NEXT: br label [[FLOW11]]42; IR: NodeBlock7:43; IR-NEXT: [[PIVOT8:%.*]] = icmp sge i32 [[TMP0:%.*]], 244; IR-NEXT: [[TMP11:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[PIVOT8]])45; IR-NEXT: [[TMP12:%.*]] = extractvalue { i1, i64 } [[TMP11]], 046; IR-NEXT: [[TMP13:%.*]] = extractvalue { i1, i64 } [[TMP11]], 147; IR-NEXT: br i1 [[TMP12]], label [[LEAFBLOCK5:%.*]], label [[FLOW13:%.*]]48; IR: LeafBlock5:49; IR-NEXT: [[SWITCHLEAF6:%.*]] = icmp eq i32 [[TMP0]], 250; IR-NEXT: br label [[FLOW13]]51; IR: Flow13:52; IR-NEXT: [[TMP14:%.*]] = phi i1 [ true, [[LEAFBLOCK5]] ], [ false, [[NODEBLOCK7]] ]53; IR-NEXT: [[TMP15:%.*]] = phi i1 [ [[SWITCHLEAF6]], [[LEAFBLOCK5]] ], [ false, [[NODEBLOCK7]] ]54; IR-NEXT: [[TMP16:%.*]] = call { i1, i64 } @llvm.amdgcn.else.i64.i64(i64 [[TMP13]])55; IR-NEXT: [[TMP17:%.*]] = extractvalue { i1, i64 } [[TMP16]], 056; IR-NEXT: [[TMP18:%.*]] = extractvalue { i1, i64 } [[TMP16]], 157; IR-NEXT: br i1 [[TMP17]], label [[LEAFBLOCK3:%.*]], label [[FLOW14:%.*]]58; IR: LeafBlock3:59; IR-NEXT: [[SWITCHLEAF4:%.*]] = icmp eq i32 [[TMP0]], 060; IR-NEXT: [[SWITCHLEAF4_INV:%.*]] = xor i1 [[SWITCHLEAF4]], true61; IR-NEXT: br label [[FLOW14]]62; IR: Flow14:63; IR-NEXT: [[TMP19:%.*]] = phi i1 [ [[SWITCHLEAF4_INV]], [[LEAFBLOCK3]] ], [ [[TMP14]], [[FLOW13]] ]64; IR-NEXT: [[TMP20:%.*]] = phi i1 [ [[SWITCHLEAF4]], [[LEAFBLOCK3]] ], [ [[TMP15]], [[FLOW13]] ]65; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP18]])66; IR-NEXT: [[TMP21:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP20]])67; IR-NEXT: [[TMP22:%.*]] = extractvalue { i1, i64 } [[TMP21]], 068; IR-NEXT: [[TMP23:%.*]] = extractvalue { i1, i64 } [[TMP21]], 169; IR-NEXT: br i1 [[TMP22]], label [[LAND_LHS_TRUE_I:%.*]], label [[FLOW15]]70; IR: land.lhs.true.i:71; IR-NEXT: br label [[LEAFBLOCK9:%.*]]72; IR: Flow15:73; IR-NEXT: [[TMP24]] = phi i1 [ [[TMP29:%.*]], [[FLOW16:%.*]] ], [ false, [[FLOW14]] ]74; IR-NEXT: [[TMP25]] = phi i1 [ [[TMP30:%.*]], [[FLOW16]] ], [ [[TMP19]], [[FLOW14]] ]75; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP23]])76; IR-NEXT: br label [[FLOW12]]77; IR: LeafBlock9:78; IR-NEXT: [[SWITCHLEAF10:%.*]] = icmp sgt i32 [[TMP0]], 179; IR-NEXT: [[TMP26:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[SWITCHLEAF10]])80; IR-NEXT: [[TMP27:%.*]] = extractvalue { i1, i64 } [[TMP26]], 081; IR-NEXT: [[TMP28:%.*]] = extractvalue { i1, i64 } [[TMP26]], 182; IR-NEXT: br i1 [[TMP27]], label [[DO_BODY_I_I_I_I:%.*]], label [[FLOW16]]83; IR: do.body.i.i.i.i:84; IR-NEXT: tail call fastcc void null()85; IR-NEXT: br label [[FLOW16]]86; IR: Flow16:87; IR-NEXT: [[TMP29]] = phi i1 [ true, [[DO_BODY_I_I_I_I]] ], [ false, [[LEAFBLOCK9]] ]88; IR-NEXT: [[TMP30]] = phi i1 [ false, [[DO_BODY_I_I_I_I]] ], [ true, [[LEAFBLOCK9]] ]89; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP28]])90; IR-NEXT: br label [[FLOW15]]91; IR: do.body:92; IR-NEXT: tail call fastcc void null()93; IR-NEXT: br label [[FLOW17]]94; IR: Flow17:95; IR-NEXT: [[TMP31:%.*]] = phi i1 [ true, [[DO_BODY]] ], [ [[TMP4]], [[FLOW11]] ]96; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP8]])97; IR-NEXT: [[TMP32:%.*]] = call { i1, i64 } @llvm.amdgcn.if.i64(i1 [[TMP31]])98; IR-NEXT: [[TMP33:%.*]] = extractvalue { i1, i64 } [[TMP32]], 099; IR-NEXT: [[TMP34:%.*]] = extractvalue { i1, i64 } [[TMP32]], 1100; IR-NEXT: br i1 [[TMP33]], label [[UNIFIEDUNREACHABLEBLOCK:%.*]], label [[UNIFIEDRETURNBLOCK:%.*]]101; IR: UnifiedUnreachableBlock:102; IR-NEXT: call void @llvm.amdgcn.unreachable()103; IR-NEXT: br label [[UNIFIEDRETURNBLOCK]]104; IR: UnifiedReturnBlock:105; IR-NEXT: call void @llvm.amdgcn.end.cf.i64(i64 [[TMP34]])106; IR-NEXT: ret void107;108; GCN-LABEL: my_func:109; GCN: ; %bb.0: ; %entry110; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)111; GCN-NEXT: s_mov_b64 s[4:5], 0112; GCN-NEXT: s_load_dword s10, s[4:5], 0x0113; GCN-NEXT: s_mov_b64 s[8:9], -1114; GCN-NEXT: s_waitcnt lgkmcnt(0)115; GCN-NEXT: s_cmp_lt_i32 s10, 1116; GCN-NEXT: s_mov_b64 s[6:7], 0117; GCN-NEXT: s_cbranch_scc1 .LBB0_7118; GCN-NEXT: ; %bb.1: ; %LeafBlock1119; GCN-NEXT: s_cmp_lg_u32 s10, 1120; GCN-NEXT: s_cselect_b64 s[6:7], -1, 0121; GCN-NEXT: s_mov_b64 vcc, exec122; GCN-NEXT: s_cbranch_execz .LBB0_8123; GCN-NEXT: .LBB0_2: ; %Flow11124; GCN-NEXT: s_and_saveexec_b64 s[8:9], s[6:7]125; GCN-NEXT: s_cbranch_execz .LBB0_4126; GCN-NEXT: .LBB0_3: ; %do.body127; GCN-NEXT: s_or_b64 s[4:5], s[4:5], exec128; GCN-NEXT: .LBB0_4: ; %Flow17129; GCN-NEXT: s_or_b64 exec, exec, s[8:9]130; GCN-NEXT: s_and_saveexec_b64 s[6:7], s[4:5]131; GCN-NEXT: s_cbranch_execz .LBB0_6132; GCN-NEXT: ; %bb.5: ; %UnifiedUnreachableBlock133; GCN-NEXT: ; divergent unreachable134; GCN-NEXT: .LBB0_6: ; %UnifiedReturnBlock135; GCN-NEXT: s_or_b64 exec, exec, s[6:7]136; GCN-NEXT: s_setpc_b64 s[30:31]137; GCN-NEXT: .LBB0_7: ; %Flow138; GCN-NEXT: s_andn2_b64 vcc, exec, s[8:9]139; GCN-NEXT: s_cbranch_vccnz .LBB0_2140; GCN-NEXT: .LBB0_8: ; %LeafBlock141; GCN-NEXT: s_cmp_eq_u32 s10, 0142; GCN-NEXT: s_cbranch_scc1 .LBB0_10143; GCN-NEXT: ; %bb.9:144; GCN-NEXT: s_mov_b64 s[6:7], -1145; GCN-NEXT: s_and_saveexec_b64 s[8:9], s[6:7]146; GCN-NEXT: s_cbranch_execnz .LBB0_3147; GCN-NEXT: s_branch .LBB0_4148; GCN-NEXT: .LBB0_10: ; %NodeBlock7149; GCN-NEXT: v_cmp_lt_i32_e32 vcc, 1, v0150; GCN-NEXT: s_mov_b64 s[8:9], 0151; GCN-NEXT: s_mov_b64 s[6:7], 0152; GCN-NEXT: s_and_saveexec_b64 s[4:5], vcc153; GCN-NEXT: s_xor_b64 s[4:5], exec, s[4:5]154; GCN-NEXT: s_cbranch_execz .LBB0_12155; GCN-NEXT: ; %bb.11: ; %LeafBlock5156; GCN-NEXT: s_mov_b64 s[6:7], exec157; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 2, v0158; GCN-NEXT: s_and_b64 s[8:9], vcc, exec159; GCN-NEXT: .LBB0_12: ; %Flow13160; GCN-NEXT: s_andn2_saveexec_b64 s[10:11], s[4:5]161; GCN-NEXT: s_cbranch_execz .LBB0_14162; GCN-NEXT: ; %bb.13: ; %LeafBlock3163; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0164; GCN-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v0165; GCN-NEXT: s_andn2_b64 s[6:7], s[6:7], exec166; GCN-NEXT: s_andn2_b64 s[8:9], s[8:9], exec167; GCN-NEXT: s_and_b64 s[4:5], s[4:5], exec168; GCN-NEXT: s_and_b64 s[12:13], vcc, exec169; GCN-NEXT: s_or_b64 s[6:7], s[6:7], s[4:5]170; GCN-NEXT: s_or_b64 s[8:9], s[8:9], s[12:13]171; GCN-NEXT: .LBB0_14: ; %Flow14172; GCN-NEXT: s_or_b64 exec, exec, s[10:11]173; GCN-NEXT: s_mov_b64 s[4:5], 0174; GCN-NEXT: s_and_saveexec_b64 s[10:11], s[8:9]175; GCN-NEXT: s_cbranch_execz .LBB0_18176; GCN-NEXT: ; %bb.15: ; %LeafBlock9177; GCN-NEXT: v_cmp_lt_i32_e32 vcc, 1, v0178; GCN-NEXT: s_mov_b64 s[8:9], -1179; GCN-NEXT: s_and_saveexec_b64 s[12:13], vcc180; GCN-NEXT: s_cbranch_execz .LBB0_17181; GCN-NEXT: ; %bb.16: ; %do.body.i.i.i.i182; GCN-NEXT: s_mov_b64 s[4:5], exec183; GCN-NEXT: s_xor_b64 s[8:9], exec, -1184; GCN-NEXT: .LBB0_17: ; %Flow16185; GCN-NEXT: s_or_b64 exec, exec, s[12:13]186; GCN-NEXT: s_and_b64 s[4:5], s[4:5], exec187; GCN-NEXT: s_andn2_b64 s[6:7], s[6:7], exec188; GCN-NEXT: s_and_b64 s[8:9], s[8:9], exec189; GCN-NEXT: s_or_b64 s[6:7], s[6:7], s[8:9]190; GCN-NEXT: .LBB0_18: ; %Flow15191; GCN-NEXT: s_or_b64 exec, exec, s[10:11]192; GCN-NEXT: s_and_saveexec_b64 s[8:9], s[6:7]193; GCN-NEXT: s_cbranch_execnz .LBB0_3194; GCN-NEXT: s_branch .LBB0_4195entry:196 %1 = load i32, ptr addrspace(4) null, align 8197 switch i32 %1, label %do.body [198 i32 1, label %sw.bb199 i32 0, label %sw.bb2200 ]201 202sw.bb:203 ret void204 205sw.bb2:206 switch i32 %0, label %do.body [207 i32 0, label %land.lhs.true.i208 i32 2, label %land.lhs.true.i209 ]210 211land.lhs.true.i:212 switch i32 %0, label %do.body.i.i.i.i [213 i32 0, label %do.body214 i32 1, label %do.body215 ]216 217do.body.i.i.i.i:218 tail call fastcc void null()219 unreachable220 221do.body:222 tail call fastcc void null()223 unreachable224 225}226