226 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=amdgcn -mcpu=tahiti < %s | FileCheck -enable-var-scope -check-prefix=SI %s3;4; Most SALU instructions ignore control flow, so we need to make sure5; they don't overwrite values from other blocks.6 7; If the branch decision is made based on a value in an SGPR then all8; threads will execute the same code paths, so we don't need to worry9; about instructions in different blocks overwriting each other.10 11define amdgpu_kernel void @sgpr_if_else_salu_br(ptr addrspace(1) %out, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {12; SI-LABEL: sgpr_if_else_salu_br:13; SI: ; %bb.0: ; %entry14; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0xb15; SI-NEXT: s_load_dword s6, s[4:5], 0xf16; SI-NEXT: s_waitcnt lgkmcnt(0)17; SI-NEXT: s_cmp_lg_u32 s0, 018; SI-NEXT: s_cbranch_scc0 .LBB0_419; SI-NEXT: ; %bb.1: ; %else20; SI-NEXT: s_add_i32 s3, s3, s621; SI-NEXT: s_cbranch_execnz .LBB0_322; SI-NEXT: .LBB0_2: ; %if23; SI-NEXT: s_sub_i32 s3, s1, s224; SI-NEXT: .LBB0_3: ; %endif25; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x926; SI-NEXT: s_add_i32 s0, s3, s027; SI-NEXT: s_mov_b32 s7, 0xf00028; SI-NEXT: s_mov_b32 s6, -129; SI-NEXT: v_mov_b32_e32 v0, s030; SI-NEXT: s_waitcnt lgkmcnt(0)31; SI-NEXT: buffer_store_dword v0, off, s[4:7], 032; SI-NEXT: s_endpgm33; SI-NEXT: .LBB0_4:34; SI-NEXT: ; implicit-def: $sgpr335; SI-NEXT: s_branch .LBB0_236 37entry:38 %0 = icmp eq i32 %a, 039 br i1 %0, label %if, label %else40 41if:42 %1 = sub i32 %b, %c43 br label %endif44 45else:46 %2 = add i32 %d, %e47 br label %endif48 49endif:50 %3 = phi i32 [%1, %if], [%2, %else]51 %4 = add i32 %3, %a52 store i32 %4, ptr addrspace(1) %out53 ret void54}55 56define amdgpu_kernel void @sgpr_if_else_salu_br_opt(ptr addrspace(1) %out, [8 x i32], i32 %a, [8 x i32], i32 %b, [8 x i32], i32 %c, [8 x i32], i32 %d, [8 x i32], i32 %e) {57; SI-LABEL: sgpr_if_else_salu_br_opt:58; SI: ; %bb.0: ; %entry59; SI-NEXT: s_load_dword s2, s[4:5], 0x1360; SI-NEXT: s_waitcnt lgkmcnt(0)61; SI-NEXT: s_cmp_lg_u32 s2, 062; SI-NEXT: s_cbranch_scc0 .LBB1_463; SI-NEXT: ; %bb.1: ; %else64; SI-NEXT: s_load_dword s0, s[4:5], 0x2e65; SI-NEXT: s_load_dword s1, s[4:5], 0x3766; SI-NEXT: s_waitcnt lgkmcnt(0)67; SI-NEXT: s_add_i32 s3, s0, s168; SI-NEXT: s_cbranch_execnz .LBB1_369; SI-NEXT: .LBB1_2: ; %if70; SI-NEXT: s_load_dword s0, s[4:5], 0x1c71; SI-NEXT: s_load_dword s1, s[4:5], 0x2572; SI-NEXT: s_waitcnt lgkmcnt(0)73; SI-NEXT: s_add_i32 s3, s0, s174; SI-NEXT: .LBB1_3: ; %endif75; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0x976; SI-NEXT: s_add_i32 s0, s3, s277; SI-NEXT: s_mov_b32 s7, 0xf00078; SI-NEXT: s_mov_b32 s6, -179; SI-NEXT: v_mov_b32_e32 v0, s080; SI-NEXT: s_waitcnt lgkmcnt(0)81; SI-NEXT: buffer_store_dword v0, off, s[4:7], 082; SI-NEXT: s_endpgm83; SI-NEXT: .LBB1_4:84; SI-NEXT: ; implicit-def: $sgpr385; SI-NEXT: s_branch .LBB1_286 87entry:88 %cmp0 = icmp eq i32 %a, 089 br i1 %cmp0, label %if, label %else90 91if:92 %add0 = add i32 %b, %c93 br label %endif94 95else:96 %add1 = add i32 %d, %e97 br label %endif98 99endif:100 %phi = phi i32 [%add0, %if], [%add1, %else]101 %add2 = add i32 %phi, %a102 store i32 %add2, ptr addrspace(1) %out103 ret void104}105 106; The two S_ADD instructions should write to different registers, since107; different threads will take different control flow paths.108define amdgpu_kernel void @sgpr_if_else_valu_br(ptr addrspace(1) %out, float %a, i32 %b, i32 %c, i32 %d, i32 %e) {109; SI-LABEL: sgpr_if_else_valu_br:110; SI: ; %bb.0: ; %entry111; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0xc112; SI-NEXT: v_cvt_f32_u32_e32 v0, v0113; SI-NEXT: ; implicit-def: $sgpr8114; SI-NEXT: v_cmp_lg_f32_e32 vcc, 0, v0115; SI-NEXT: s_and_saveexec_b64 s[6:7], vcc116; SI-NEXT: s_xor_b64 s[6:7], exec, s[6:7]117; SI-NEXT: s_cbranch_execz .LBB2_2118; SI-NEXT: ; %bb.1: ; %else119; SI-NEXT: s_waitcnt lgkmcnt(0)120; SI-NEXT: s_add_i32 s8, s2, s3121; SI-NEXT: .LBB2_2: ; %Flow122; SI-NEXT: s_waitcnt lgkmcnt(0)123; SI-NEXT: s_or_saveexec_b64 s[2:3], s[6:7]124; SI-NEXT: v_mov_b32_e32 v0, s8125; SI-NEXT: s_xor_b64 exec, exec, s[2:3]126; SI-NEXT: ; %bb.3: ; %if127; SI-NEXT: s_add_i32 s0, s0, s1128; SI-NEXT: v_mov_b32_e32 v0, s0129; SI-NEXT: ; %bb.4: ; %endif130; SI-NEXT: s_or_b64 exec, exec, s[2:3]131; SI-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x9132; SI-NEXT: s_mov_b32 s3, 0xf000133; SI-NEXT: s_mov_b32 s2, -1134; SI-NEXT: s_waitcnt lgkmcnt(0)135; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0136; SI-NEXT: s_endpgm137entry:138 %tid = call i32 @llvm.amdgcn.workitem.id.x() #0139 %tid_f = uitofp i32 %tid to float140 %tmp1 = fcmp ueq float %tid_f, 0.0141 br i1 %tmp1, label %if, label %else142 143if:144 %tmp2 = add i32 %b, %c145 br label %endif146 147else:148 %tmp3 = add i32 %d, %e149 br label %endif150 151endif:152 %tmp4 = phi i32 [%tmp2, %if], [%tmp3, %else]153 store i32 %tmp4, ptr addrspace(1) %out154 ret void155}156 157define amdgpu_kernel void @sgpr_if_else_valu_cmp_phi_br(ptr addrspace(1) %out, ptr addrspace(1) %a, ptr addrspace(1) %b) {158; SI-LABEL: sgpr_if_else_valu_cmp_phi_br:159; SI: ; %bb.0: ; %entry160; SI-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x9161; SI-NEXT: s_load_dwordx2 s[4:5], s[4:5], 0xd162; SI-NEXT: s_mov_b32 s6, 0163; SI-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0164; SI-NEXT: v_lshlrev_b32_e32 v0, 2, v0165; SI-NEXT: ; implicit-def: $sgpr8_sgpr9166; SI-NEXT: s_and_saveexec_b64 s[10:11], vcc167; SI-NEXT: s_xor_b64 s[10:11], exec, s[10:11]168; SI-NEXT: s_cbranch_execz .LBB3_2169; SI-NEXT: ; %bb.1: ; %else170; SI-NEXT: s_mov_b32 s7, 0xf000171; SI-NEXT: v_mov_b32_e32 v1, 0172; SI-NEXT: s_waitcnt lgkmcnt(0)173; SI-NEXT: buffer_load_dword v0, v[0:1], s[4:7], 0 addr64174; SI-NEXT: s_waitcnt vmcnt(0)175; SI-NEXT: v_cmp_gt_i32_e64 s[8:9], 0, v0176; SI-NEXT: ; implicit-def: $vgpr0177; SI-NEXT: .LBB3_2: ; %Flow178; SI-NEXT: s_waitcnt lgkmcnt(0)179; SI-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11]180; SI-NEXT: s_cbranch_execz .LBB3_4181; SI-NEXT: ; %bb.3: ; %if182; SI-NEXT: s_mov_b32 s15, 0xf000183; SI-NEXT: s_mov_b32 s14, 0184; SI-NEXT: s_mov_b64 s[12:13], s[2:3]185; SI-NEXT: v_mov_b32_e32 v1, 0186; SI-NEXT: buffer_load_dword v0, v[0:1], s[12:15], 0 addr64187; SI-NEXT: s_andn2_b64 s[2:3], s[8:9], exec188; SI-NEXT: s_waitcnt vmcnt(0)189; SI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0190; SI-NEXT: s_and_b64 s[6:7], vcc, exec191; SI-NEXT: s_or_b64 s[8:9], s[2:3], s[6:7]192; SI-NEXT: .LBB3_4: ; %endif193; SI-NEXT: s_or_b64 exec, exec, s[4:5]194; SI-NEXT: s_mov_b32 s3, 0xf000195; SI-NEXT: s_mov_b32 s2, -1196; SI-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[8:9]197; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0198; SI-NEXT: s_endpgm199entry:200 %tid = call i32 @llvm.amdgcn.workitem.id.x() #0201 %tmp1 = icmp eq i32 %tid, 0202 br i1 %tmp1, label %if, label %else203 204if:205 %gep.if = getelementptr i32, ptr addrspace(1) %a, i32 %tid206 %a.val = load i32, ptr addrspace(1) %gep.if207 %cmp.if = icmp eq i32 %a.val, 0208 br label %endif209 210else:211 %gep.else = getelementptr i32, ptr addrspace(1) %b, i32 %tid212 %b.val = load i32, ptr addrspace(1) %gep.else213 %cmp.else = icmp slt i32 %b.val, 0214 br label %endif215 216endif:217 %tmp4 = phi i1 [%cmp.if, %if], [%cmp.else, %else]218 %ext = sext i1 %tmp4 to i32219 store i32 %ext, ptr addrspace(1) %out220 ret void221}222 223declare i32 @llvm.amdgcn.workitem.id.x() #0224 225attributes #0 = { readnone }226