diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td index 1931e0be15152..68f20cae50825 100644 --- a/llvm/lib/Target/AMDGPU/SOPInstructions.td +++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td @@ -264,7 +264,9 @@ def S_BREV_B64 : SOP1_64 <"s_brev_b64", } // End isReMaterializable = 1, isAsCheapAsAMove = 1 let Defs = [SCC] in { -def S_BCNT0_I32_B32 : SOP1_32 <"s_bcnt0_i32_b32">; +def S_BCNT0_I32_B32 : SOP1_32 <"s_bcnt0_i32_b32", + [(set i32:$sdst, (UniformBinFrag 32, (ctpop i32:$src0)))] +>; def S_BCNT0_I32_B64 : SOP1_32_64 <"s_bcnt0_i32_b64">; def S_BCNT1_I32_B32 : SOP1_32 <"s_bcnt1_i32_b32", [(set i32:$sdst, (UniformUnaryFrag i32:$src0))] @@ -1885,6 +1887,13 @@ def : GCNPat < (S_MOV_B32 (i32 0)), sub1)) >; +def : GCNPat < + (i64 (UniformBinFrag 64, (ctpop i64:$src))), + (i64 (REG_SEQUENCE SReg_64, + (i32 (COPY_TO_REGCLASS (S_BCNT0_I32_B64 $src), SReg_32)), sub0, + (S_MOV_B32 (i32 0)), sub1)) +>; + def : GCNPat < (i32 (UniformBinFrag i32:$x, (i32 (ineg i32:$x)))), (S_ABS_I32 SReg_32:$x) diff --git a/llvm/test/CodeGen/AMDGPU/s_bcnt0.ll b/llvm/test/CodeGen/AMDGPU/s_bcnt0.ll new file mode 100644 index 0000000000000..89bef87f900f2 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/s_bcnt0.ll @@ -0,0 +1,85 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc -mtriple=amdgcn -mcpu=gfx900 < %s | FileCheck %s + +define i32 @bcnt032_not_for_vregs(i32 %val0) { +; CHECK-LABEL: bcnt032_not_for_vregs: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_bcnt_u32_b32 v0, v0, 0 +; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 32, v0 +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = call i32 @llvm.ctpop.i32(i32 %val0) + %result2 = sub i32 32, %result + %cmp = icmp ne i32 %result2, 0 + %zext = zext i1 %cmp to i32 + ret i32 %zext +} + +define i32 @bcnt064_not_for_vregs(i64 %val0) { +; CHECK-LABEL: bcnt064_not_for_vregs: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_bcnt_u32_b32 v0, v0, 0 +; CHECK-NEXT: v_bcnt_u32_b32 v0, v1, v0 +; CHECK-NEXT: v_mov_b32_e32 v1, 0 +; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 64, v[0:1] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = call i64 @llvm.ctpop.i64(i64 %val0) + %result2 = sub i64 64, %result + %cmp = icmp ne i64 %result2, 0 + %zext = zext i1 %cmp to i32 + ret i32 %zext +} + +define amdgpu_ps i32 @bcnt032_ctpop_multiple_uses(i32 inreg %val0) { +; CHECK-LABEL: bcnt032_ctpop_multiple_uses: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_bcnt1_i32_b32 s1, s0 +; CHECK-NEXT: s_bcnt0_i32_b32 s0, s0 +; CHECK-NEXT: ;;#ASMSTART +; CHECK-NEXT: ; use s1 +; CHECK-NEXT: ;;#ASMEND +; CHECK-NEXT: ;;#ASMSTART +; CHECK-NEXT: ; use s0 +; CHECK-NEXT: ;;#ASMEND +; CHECK-NEXT: s_cselect_b64 s[0:1], -1, 0 +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1] +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: ; return to shader part epilog + %result = call i32 @llvm.ctpop.i32(i32 %val0) + %result2 = sub i32 32, %result + call void asm "; use $0", "s"(i32 %result) + call void asm "; use $0", "s"(i32 %result2) + %cmp = icmp ne i32 %result2, 0 + %zext = zext i1 %cmp to i32 + ret i32 %zext +} + +define amdgpu_ps i32 @bcnt064_ctpop_multiple_uses(i64 inreg %val0) { +; CHECK-LABEL: bcnt064_ctpop_multiple_uses: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_mov_b32 s3, 0 +; CHECK-NEXT: s_bcnt1_i32_b64 s2, s[0:1] +; CHECK-NEXT: s_bcnt0_i32_b64 s0, s[0:1] +; CHECK-NEXT: s_mov_b32 s1, s3 +; CHECK-NEXT: s_cmp_lg_u64 s[0:1], 0 +; CHECK-NEXT: ;;#ASMSTART +; CHECK-NEXT: ; use s[0:1] +; CHECK-NEXT: ;;#ASMEND +; CHECK-NEXT: s_cselect_b64 s[0:1], -1, 0 +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1] +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: ;;#ASMSTART +; CHECK-NEXT: ; use s[2:3] +; CHECK-NEXT: ;;#ASMEND +; CHECK-NEXT: ; return to shader part epilog + %result = call i64 @llvm.ctpop.i64(i64 %val0) + %result2 = sub i64 64, %result + call void asm "; use $0", "s"(i64 %result) + call void asm "; use $0", "s"(i64 %result2) + %cmp = icmp ne i64 %result2, 0 + %zext = zext i1 %cmp to i32 + ret i32 %zext +} diff --git a/llvm/test/CodeGen/AMDGPU/s_cmp_0.ll b/llvm/test/CodeGen/AMDGPU/s_cmp_0.ll index 0166d7ac7ddc2..fb48f5706feeb 100644 --- a/llvm/test/CodeGen/AMDGPU/s_cmp_0.ll +++ b/llvm/test/CodeGen/AMDGPU/s_cmp_0.ll @@ -459,9 +459,7 @@ define amdgpu_ps i32 @bfe_u64(i64 inreg %val0) { define amdgpu_ps i32 @bcnt032(i32 inreg %val0) { ; CHECK-LABEL: bcnt032: ; CHECK: ; %bb.0: -; CHECK-NEXT: s_bcnt1_i32_b32 s0, s0 -; CHECK-NEXT: s_sub_i32 s0, 32, s0 -; CHECK-NEXT: s_cmp_lg_u32 s0, 0 +; CHECK-NEXT: s_bcnt0_i32_b32 s0, s0 ; CHECK-NEXT: ;;#ASMSTART ; CHECK-NEXT: ; use s0 ; CHECK-NEXT: ;;#ASMEND @@ -480,9 +478,8 @@ define amdgpu_ps i32 @bcnt032(i32 inreg %val0) { define amdgpu_ps i32 @bcnt064(i64 inreg %val0) { ; CHECK-LABEL: bcnt064: ; CHECK: ; %bb.0: -; CHECK-NEXT: s_bcnt1_i32_b64 s0, s[0:1] -; CHECK-NEXT: s_sub_u32 s0, 64, s0 -; CHECK-NEXT: s_subb_u32 s1, 0, 0 +; CHECK-NEXT: s_bcnt0_i32_b64 s0, s[0:1] +; CHECK-NEXT: s_mov_b32 s1, 0 ; CHECK-NEXT: s_cmp_lg_u64 s[0:1], 0 ; CHECK-NEXT: ;;#ASMSTART ; CHECK-NEXT: ; use s[0:1]