SpirvShader: Use masked loads / stores when possible.

Bug: b/135609394
Change-Id: I0e337f99dacc997685fab39183f902ca3d988492
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/33170
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.cpp b/src/Pipeline/SpirvShader.cpp
index 12aa56f..83f12c2 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -294,6 +294,10 @@
 			mask &= ptr.isInBounds(sizeof(float)); // Disable OOB reads.
 			if (!atomic && order == std::memory_order_relaxed)
 			{
+				if (ptr.hasStaticSequentialOffsets(sizeof(float)))
+				{
+					return rr::MaskedLoad(rr::Pointer<T>(ptr.base + ptr.staticOffsets[0]), mask, sizeof(float));
+				}
 				return rr::Gather(rr::Pointer<EL>(ptr.base), offsets, mask, sizeof(float));
 			}
 			else
@@ -338,6 +342,10 @@
 			mask &= ptr.isInBounds(sizeof(float)); // Disable OOB writes.
 			if (!atomic && order == std::memory_order_relaxed)
 			{
+				if (ptr.hasStaticSequentialOffsets(sizeof(float)))
+				{
+					return rr::MaskedStore(rr::Pointer<T>(ptr.base + ptr.staticOffsets[0]), val, mask, sizeof(float));
+				}
 				return rr::Scatter(rr::Pointer<EL>(ptr.base), val, offsets, mask, sizeof(float));
 			}
 			else