259 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 -stop-after=amdgpu-unify-divergent-exit-nodes | FileCheck %s --check-prefix=UNIFY3; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx906 | FileCheck %s4 5declare void @llvm.trap()6declare i32 @llvm.amdgcn.workitem.id.x()7 8define amdgpu_kernel void @kernel(i32 %a, ptr addrspace(1) %x, i32 noundef %n) {9; This used to bypass the structurization process because structurizer is unable to10; handle multiple-exits CFG. This should be correctly structurized.11; CHECK-LABEL: kernel:12; CHECK: ; %bb.0: ; %entry13; CHECK-NEXT: s_load_dword s0, s[8:9], 0x1014; CHECK-NEXT: s_load_dword s10, s[8:9], 0x015; CHECK-NEXT: s_waitcnt lgkmcnt(0)16; CHECK-NEXT: s_cmpk_lg_i32 s0, 0x10017; CHECK-NEXT: s_cbranch_scc0 .LBB0_618; CHECK-NEXT: ; %bb.1: ; %if.else19; CHECK-NEXT: v_cmp_gt_u32_e32 vcc, 10, v020; CHECK-NEXT: s_mov_b64 s[4:5], 021; CHECK-NEXT: s_mov_b64 s[2:3], 022; CHECK-NEXT: s_mov_b64 s[0:1], 023; CHECK-NEXT: s_and_saveexec_b64 s[6:7], vcc24; CHECK-NEXT: s_cbranch_execz .LBB0_525; CHECK-NEXT: ; %bb.2: ; %if.then326; CHECK-NEXT: s_cmp_lg_u32 s10, 027; CHECK-NEXT: s_cbranch_scc1 .LBB0_1428; CHECK-NEXT: ; %bb.3:29; CHECK-NEXT: s_mov_b64 s[0:1], -130; CHECK-NEXT: .LBB0_4: ; %Flow331; CHECK-NEXT: s_and_b64 s[0:1], s[0:1], exec32; CHECK-NEXT: s_and_b64 s[2:3], s[2:3], exec33; CHECK-NEXT: .LBB0_5: ; %Flow234; CHECK-NEXT: s_or_b64 exec, exec, s[6:7]35; CHECK-NEXT: s_and_b64 vcc, exec, s[4:5]36; CHECK-NEXT: s_cbranch_vccz .LBB0_837; CHECK-NEXT: s_branch .LBB0_738; CHECK-NEXT: .LBB0_6:39; CHECK-NEXT: s_mov_b64 s[2:3], 040; CHECK-NEXT: s_mov_b64 s[0:1], 041; CHECK-NEXT: s_cbranch_execz .LBB0_842; CHECK-NEXT: .LBB0_7: ; %if.then43; CHECK-NEXT: s_cmp_lg_u32 s10, 044; CHECK-NEXT: s_mov_b64 s[0:1], -145; CHECK-NEXT: s_cbranch_scc1 .LBB0_1346; CHECK-NEXT: .LBB0_8: ; %Flow447; CHECK-NEXT: s_and_saveexec_b64 s[4:5], s[2:3]48; CHECK-NEXT: .LBB0_9: ; %UnifiedUnreachableBlock49; CHECK-NEXT: ; divergent unreachable50; CHECK-NEXT: .LBB0_10: ; %Flow651; CHECK-NEXT: s_or_b64 exec, exec, s[4:5]52; CHECK-NEXT: s_and_saveexec_b64 s[2:3], s[0:1]53; CHECK-NEXT: s_cbranch_execz .LBB0_1254; CHECK-NEXT: ; %bb.11: ; %if.end6.sink.split55; CHECK-NEXT: s_load_dwordx2 s[0:1], s[8:9], 0x856; CHECK-NEXT: v_lshlrev_b32_e32 v0, 2, v057; CHECK-NEXT: v_mov_b32_e32 v1, s1058; CHECK-NEXT: s_waitcnt lgkmcnt(0)59; CHECK-NEXT: global_store_dword v0, v1, s[0:1]60; CHECK-NEXT: .LBB0_12: ; %UnifiedReturnBlock61; CHECK-NEXT: s_endpgm62; CHECK-NEXT: .LBB0_13: ; %cond.false63; CHECK-NEXT: s_mov_b64 s[0:1], 064; CHECK-NEXT: s_or_b64 s[2:3], s[2:3], exec65; CHECK-NEXT: s_trap 266; CHECK-NEXT: s_and_saveexec_b64 s[4:5], s[2:3]67; CHECK-NEXT: s_cbranch_execnz .LBB0_968; CHECK-NEXT: s_branch .LBB0_1069; CHECK-NEXT: .LBB0_14: ; %cond.false.i870; CHECK-NEXT: s_mov_b64 s[2:3], -171; CHECK-NEXT: s_trap 272; CHECK-NEXT: s_branch .LBB0_473; UNIFY-LABEL: @kernel(74; UNIFY-NEXT: entry:75; UNIFY-NEXT: [[TID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()76; UNIFY-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 25677; UNIFY-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]78; UNIFY: if.then:79; UNIFY-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 080; UNIFY-NEXT: br i1 [[CMP1]], label [[IF_END6_SINK_SPLIT:%.*]], label [[COND_FALSE:%.*]]81; UNIFY: cond.false:82; UNIFY-NEXT: call void @llvm.trap()83; UNIFY-NEXT: unreachable84; UNIFY: if.else:85; UNIFY-NEXT: [[CMP2:%.*]] = icmp ult i32 [[TID]], 1086; UNIFY-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END6:%.*]]87; UNIFY: if.then3:88; UNIFY-NEXT: [[CMP1_I7:%.*]] = icmp eq i32 [[A]], 089; UNIFY-NEXT: br i1 [[CMP1_I7]], label [[IF_END6_SINK_SPLIT]], label [[COND_FALSE_I8:%.*]]90; UNIFY: cond.false.i8:91; UNIFY-NEXT: call void @llvm.trap()92; UNIFY-NEXT: unreachable93; UNIFY: if.end6.sink.split:94; UNIFY-NEXT: [[X1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[X:%.*]], i32 [[TID]]95; UNIFY-NEXT: store i32 [[A]], ptr addrspace(1) [[X1]], align 496; UNIFY-NEXT: br label [[IF_END6]]97; UNIFY: if.end6:98; UNIFY-NEXT: ret void99;100entry:101 %tid = call i32 @llvm.amdgcn.workitem.id.x()102 %cmp = icmp eq i32 %n, 256103 br i1 %cmp, label %if.then, label %if.else104 105if.then:106 %cmp1 = icmp eq i32 %a, 0107 br i1 %cmp1, label %if.end6.sink.split, label %cond.false108 109cond.false:110 call void @llvm.trap()111 unreachable112 113if.else:114 %cmp2 = icmp ult i32 %tid, 10115 br i1 %cmp2, label %if.then3, label %if.end6116 117if.then3:118 %cmp1.i7 = icmp eq i32 %a, 0119 br i1 %cmp1.i7, label %if.end6.sink.split, label %cond.false.i8120 121cond.false.i8:122 call void @llvm.trap()123 unreachable124 125if.end6.sink.split:126 %x1 = getelementptr inbounds i32, ptr addrspace(1) %x, i32 %tid127 store i32 %a, ptr addrspace(1) %x1, align 4128 br label %if.end6129 130if.end6:131 ret void132}133 134define amdgpu_kernel void @kernel_callbr(i32 %a, ptr addrspace(1) %x, i32 noundef %n) {135; CHECK-LABEL: kernel_callbr:136; CHECK: ; %bb.0: ; %entry137; CHECK-NEXT: s_load_dword s1, s[8:9], 0x10138; CHECK-NEXT: s_load_dword s0, s[8:9], 0x0139; CHECK-NEXT: s_waitcnt lgkmcnt(0)140; CHECK-NEXT: s_cmpk_eq_i32 s1, 0x100141; CHECK-NEXT: s_cselect_b64 s[2:3], -1, 0142; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[2:3]143; CHECK-NEXT: ;;#ASMSTART144; CHECK-NEXT: ;;#ASMEND145; CHECK-NEXT: ; %bb.1: ; %if.then146; CHECK-NEXT: s_cmp_eq_u32 s0, 0147; CHECK-NEXT: s_cselect_b64 s[2:3], -1, 0148; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[2:3]149; CHECK-NEXT: ;;#ASMSTART150; CHECK-NEXT: ;;#ASMEND151; CHECK-NEXT: .LBB1_2: ; %if.end6.sink.split152; CHECK-NEXT: s_load_dwordx2 s[2:3], s[8:9], 0x8153; CHECK-NEXT: v_lshlrev_b32_e32 v0, 2, v0154; CHECK-NEXT: v_mov_b32_e32 v1, s0155; CHECK-NEXT: s_waitcnt lgkmcnt(0)156; CHECK-NEXT: global_store_dword v0, v1, s[2:3]157; CHECK-NEXT: ;;#ASMSTART158; CHECK-NEXT: ;;#ASMEND159; CHECK-NEXT: .LBB1_3: ; Inline asm indirect target160; CHECK-NEXT: ; %UnifiedReturnBlock161; CHECK-NEXT: ; Label of block must be emitted162; CHECK-NEXT: s_endpgm163; CHECK-NEXT: .LBB1_4: ; Inline asm indirect target164; CHECK-NEXT: ; %if.else165; CHECK-NEXT: ; Label of block must be emitted166; CHECK-NEXT: v_cmp_gt_u32_e32 vcc, 10, v0167; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc168; CHECK-NEXT: ;;#ASMSTART169; CHECK-NEXT: ;;#ASMEND170; CHECK-NEXT: ; %bb.5: ; %if.then3171; CHECK-NEXT: s_cmp_eq_u32 s0, 0172; CHECK-NEXT: s_cselect_b64 s[2:3], -1, 0173; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[2:3]174; CHECK-NEXT: ;;#ASMSTART175; CHECK-NEXT: ;;#ASMEND176; CHECK-NEXT: s_branch .LBB1_2177; CHECK-NEXT: .LBB1_6: ; Inline asm indirect target178; CHECK-NEXT: ; %cond.false.i8179; CHECK-NEXT: ; Label of block must be emitted180; CHECK-NEXT: .LBB1_7: ; Inline asm indirect target181; CHECK-NEXT: ; %cond.false182; CHECK-NEXT: ; Label of block must be emitted183; CHECK-NEXT: s_trap 2184; CHECK-NEXT: ; divergent unreachable185; CHECK-NEXT: s_branch .LBB1_3186; UNIFY-LABEL: @kernel_callbr(187; UNIFY-NEXT: entry:188; UNIFY-NEXT: [[TID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()189; UNIFY-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 256190; UNIFY-NEXT: [[CMP32:%.*]] = zext i1 [[CMP]] to i32191; UNIFY-NEXT: callbr void asm "", "r,!i"(i32 [[CMP32]])192; UNIFY-NEXT: to label [[IF_THEN:%.*]] [label %if.else]193; UNIFY: if.then:194; UNIFY-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0195; UNIFY-NEXT: [[CMP1_32:%.*]] = zext i1 [[CMP1]] to i32196; UNIFY-NEXT: callbr void asm "", "r,!i"(i32 [[CMP1_32]])197; UNIFY-NEXT: to label [[IF_END6_SINK_SPLIT:%.*]] [label %cond.false]198; UNIFY: cond.false:199; UNIFY-NEXT: call void @llvm.trap()200; UNIFY-NEXT: unreachable201; UNIFY: if.else:202; UNIFY-NEXT: [[CMP2:%.*]] = icmp ult i32 [[TID]], 10203; UNIFY-NEXT: [[CMP2_32:%.*]] = zext i1 [[CMP2]] to i32204; UNIFY-NEXT: callbr void asm "", "r,!i"(i32 [[CMP2_32]])205; UNIFY-NEXT: to label [[IF_THEN3:%.*]] [label %if.end6]206; UNIFY: if.then3:207; UNIFY-NEXT: [[CMP1_I7:%.*]] = icmp eq i32 [[A]], 0208; UNIFY-NEXT: [[CMP1_I7_32:%.*]] = zext i1 [[CMP1_I7]] to i32209; UNIFY-NEXT: callbr void asm "", "r,!i"(i32 [[CMP1_I7_32]])210; UNIFY-NEXT: to label [[IF_END6_SINK_SPLIT]] [label %cond.false.i8]211; UNIFY: cond.false.i8:212; UNIFY-NEXT: call void @llvm.trap()213; UNIFY-NEXT: unreachable214; UNIFY: if.end6.sink.split:215; UNIFY-NEXT: [[X1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[X:%.*]], i32 [[TID]]216; UNIFY-NEXT: store i32 [[A]], ptr addrspace(1) [[X1]], align 4217; UNIFY-NEXT: callbr void asm "", ""()218; UNIFY-NEXT: to label [[IF_END6:%.*]] []219; UNIFY: if.end6:220; UNIFY-NEXT: ret void221;222entry:223 %tid = call i32 @llvm.amdgcn.workitem.id.x()224 %cmp = icmp eq i32 %n, 256225 %cmp32 = zext i1 %cmp to i32226 callbr void asm "", "r,!i"(i32 %cmp32) to label %if.then [label %if.else]227 228if.then:229 %cmp1 = icmp eq i32 %a, 0230 %cmp1_32 = zext i1 %cmp1 to i32231 callbr void asm "", "r,!i"(i32 %cmp1_32) to label %if.end6.sink.split [label %cond.false]232 233cond.false:234 call void @llvm.trap()235 unreachable236 237if.else:238 %cmp2 = icmp ult i32 %tid, 10239 %cmp2_32 = zext i1 %cmp2 to i32240 callbr void asm "", "r,!i"(i32 %cmp2_32) to label %if.then3 [label %if.end6]241 242if.then3:243 %cmp1.i7 = icmp eq i32 %a, 0244 %cmp1.i7_32 = zext i1 %cmp1.i7 to i32245 callbr void asm "", "r,!i"(i32 %cmp1.i7_32) to label %if.end6.sink.split [label %cond.false.i8]246 247cond.false.i8:248 call void @llvm.trap()249 unreachable250 251if.end6.sink.split:252 %x1 = getelementptr inbounds i32, ptr addrspace(1) %x, i32 %tid253 store i32 %a, ptr addrspace(1) %x1, align 4254 callbr void asm "", ""() to label %if.end6 []255 256if.end6:257 ret void258}259