Commit 0179e5eb by Ben Clayton

SprivShader: Replace hand-rolled bitcount with LLVM intrinsic

Moved the hand-rolled implementation to Subzero. As we've started exposing bit intrinsics, we might as fix the TODOs. Bug: b/126873455 Tests: dEQP-VK.glsl.builtin.function.integer.bitcount.* Change-Id: Ic37dfd5d73187f2b3afa444abfd9e22439c871b1 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28792 Presubmit-Ready: Ben Clayton <bclayton@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent a786c4a2
...@@ -2771,25 +2771,11 @@ namespace sw ...@@ -2771,25 +2771,11 @@ namespace sw
break; break;
} }
case spv::OpBitReverse: case spv::OpBitReverse:
{
dst.move(i, BitReverse(src.UInt(i))); dst.move(i, BitReverse(src.UInt(i)));
break; break;
}
case spv::OpBitCount: case spv::OpBitCount:
{ dst.move(i, BitCount(src.UInt(i)));
// TODO: Add an intrinsic to reactor. Even if there isn't a
// single vector instruction, there may be target-dependent
// ways to make this faster.
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
auto v = src.UInt(i);
SIMD::UInt c = v - ((v >> 1) & SIMD::UInt(0x55555555));
c = ((c >> 2) & SIMD::UInt(0x33333333)) + (c & SIMD::UInt(0x33333333));
c = ((c >> 4) + c) & SIMD::UInt(0x0F0F0F0F);
c = ((c >> 8) + c) & SIMD::UInt(0x00FF00FF);
c = ((c >> 16) + c) & SIMD::UInt(0x0000FFFF);
dst.move(i, c);
break; break;
}
case spv::OpSNegate: case spv::OpSNegate:
dst.move(i, -src.Int(i)); dst.move(i, -src.Int(i));
break; break;
......
...@@ -3220,6 +3220,12 @@ namespace rr ...@@ -3220,6 +3220,12 @@ namespace rr
return RValue<UInt4>(V(::builder->CreateCall(func, { V(v.value) }))); return RValue<UInt4>(V(::builder->CreateCall(func, { V(v.value) })));
} }
RValue<UInt4> BitCount(RValue<UInt4> v)
{
auto func = llvm::Intrinsic::getDeclaration(::module, llvm::Intrinsic::ctpop, { T(UInt4::getType()) } );
return RValue<UInt4>(V(::builder->CreateCall(func, { V(v.value) })));
}
RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef) RValue<UInt4> Ctlz(RValue<UInt4> v, bool isZeroUndef)
{ {
#if REACTOR_LLVM_VERSION < 7 #if REACTOR_LLVM_VERSION < 7
......
...@@ -2233,6 +2233,7 @@ namespace rr ...@@ -2233,6 +2233,7 @@ namespace rr
// Bit Manipulation functions. // Bit Manipulation functions.
// TODO: Currentlhy unimplemented for Subzero. // TODO: Currentlhy unimplemented for Subzero.
RValue<UInt4> BitReverse(RValue<UInt4> x); RValue<UInt4> BitReverse(RValue<UInt4> x);
RValue<UInt4> BitCount(RValue<UInt4> x);
// Count leading zeros. // Count leading zeros.
// Returns 32 when: isZeroUndef && x == 0. // Returns 32 when: isZeroUndef && x == 0.
......
...@@ -3371,6 +3371,17 @@ namespace rr ...@@ -3371,6 +3371,17 @@ namespace rr
return v; return v;
} }
RValue<UInt4> BitCount(RValue<UInt4> x)
{
// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
UInt4 v = x - ((x >> 1) & UInt4(0x55555555));
v = ((v >> 2) & UInt4(0x33333333)) + (v & UInt4(0x33333333));
v = ((v >> 4) + v) & UInt4(0x0F0F0F0F);
v = ((v >> 8) + v) & UInt4(0x00FF00FF);
v = ((v >> 16) + v) & UInt4(0x0000FFFF);
return v;
}
Type *Float4::getType() Type *Float4::getType()
{ {
return T(Ice::IceType_v4f32); return T(Ice::IceType_v4f32);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment