SpirvShader: Optimize pointer OOB masking
Reduces the amount of LLVM IR produced when the limits are compile-time known.
Reduces full test execution time of dEQP-VK.ubo.random.all_out_of_order_offsets.45 by about half.
For dEQP-VK.ubo.random.all_shared_buffer.48:
• Reduces number of pre-opt LLVM IR instructions by about 40%.
• Reduces full test execution time by about 30%
Bug: b/135609394
Change-Id: I3c46d56910bb8373a355ab8d570d3093944afc84
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/33053
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 4400542..ba8f399 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -142,6 +142,22 @@
{
ASSERT(accessSize > 0);
+ if (!hasDynamicOffsets && !hasDynamicLimit)
+ {
+ // Common fast paths.
+ if (hasStaticEqualOffsets())
+ {
+ return SIMD::Int((staticOffsets[0] + accessSize - 1 < staticLimit) ? 0xffffffff : 0);
+ }
+
+ static_assert(SIMD::Width == 4, "Expects SIMD::Width to be 4");
+ return SIMD::Int(
+ (staticOffsets[0] + accessSize - 1 < staticLimit) ? 0xffffffff : 0,
+ (staticOffsets[1] + accessSize - 1 < staticLimit) ? 0xffffffff : 0,
+ (staticOffsets[2] + accessSize - 1 < staticLimit) ? 0xffffffff : 0,
+ (staticOffsets[3] + accessSize - 1 < staticLimit) ? 0xffffffff : 0);
+ }
+
return CmpLT(offsets() + SIMD::Int(accessSize - 1), SIMD::Int(limit()));
}
@@ -178,14 +194,22 @@
static_assert(SIMD::Width == 4, "Expects SIMD::Width to be 4");
return rr::SignMask(~CmpEQ(o, o.yzwx)) == 0;
}
- else
+ return hasStaticEqualOffsets();
+ }
+
+ // Returns true if all offsets are compile-time static and are equal
+ // (N, N, N, N)
+ inline bool hasStaticEqualOffsets() const
+ {
+ if (hasDynamicOffsets)
{
- for (int i = 1; i < SIMD::Width; i++)
- {
- if (staticOffsets[i-1] != staticOffsets[i]) { return false; }
- }
- return true;
+ return false;
}
+ for (int i = 1; i < SIMD::Width; i++)
+ {
+ if (staticOffsets[i-1] != staticOffsets[i]) { return false; }
+ }
+ return true;
}
// Base address for the pointer, common across all lanes.