tint/sem: Add range overload of Constant::AllZero()

Checks whether the range of elements are all zero.

Change-Id: I22b91bff25f3fb7fd0e89abd690f139614300e81
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94328
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/sem/constant.cc b/src/tint/sem/constant.cc
index 921e9a7..26367d4 100644
--- a/src/tint/sem/constant.cc
+++ b/src/tint/sem/constant.cc
@@ -67,10 +67,11 @@
     });
 }
 
-bool Constant::AllZero() const {
+bool Constant::AllZero(size_t start, size_t end) const {
     return WithElements([&](auto&& vec) {
         using T = typename std::decay_t<decltype(vec)>::value_type;
-        for (auto el : vec) {
+        for (size_t i = start; i < end; i++) {
+            auto el = vec[i];
             if (el != T(0) || IsNegativeFloat(el.value)) {
                 return false;
             }
diff --git a/src/tint/sem/constant.h b/src/tint/sem/constant.h
index 42683cf..be2803d 100644
--- a/src/tint/sem/constant.h
+++ b/src/tint/sem/constant.h
@@ -136,13 +136,18 @@
     bool AnyZero() const;
 
     /// @returns true if all elements are positive zero
-    bool AllZero() const;
+    bool AllZero() const { return AllZero(0, ElementCount()); }
 
     /// @returns true if all elements are the same value, with the same sign-bit.
     bool AllEqual() const { return AllEqual(0, ElementCount()); }
 
     /// @param start the first element index
     /// @param end one past the last element index
+    /// @returns true if all elements between `[start, end)` are zero
+    bool AllZero(size_t start, size_t end) const;
+
+    /// @param start the first element index
+    /// @param end one past the last element index
     /// @returns true if all elements between `[start, end)` are the same value
     bool AllEqual(size_t start, size_t end) const;
 
diff --git a/src/tint/sem/constant_test.cc b/src/tint/sem/constant_test.cc
index ed9fef8..27cea72 100644
--- a/src/tint/sem/constant_test.cc
+++ b/src/tint/sem/constant_test.cc
@@ -268,6 +268,48 @@
     EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllEqual(), false);
 }
 
+TEST_F(ConstantTest, AllZeroRange) {
+    auto* vec3_ai = create<Vector>(create<AbstractInt>(), 3u);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 2_a, 3_a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 3_a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 2_a, 0_a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 0_a}).AllZero(1, 3), true);
+
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 2_a, 3_a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 3_a}).AllZero(0, 2), true);
+    EXPECT_EQ(Constant(vec3_ai, {0_a, 2_a, 0_a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 0_a}).AllZero(0, 2), false);
+
+    auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 3._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 0._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 3._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 0._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 0._a}).AllZero(1, 3), true);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 0._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, -0._a}).AllZero(1, 3), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, -0._a}).AllZero(1, 3), false);
+
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 3._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 0._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 3._a}).AllZero(0, 2), true);
+    EXPECT_EQ(Constant(vec3_af, {-0._a, 0._a, 1._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 1._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, 1._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 0._a}).AllZero(0, 2), false);
+    EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 0._a}).AllZero(0, 2), false);
+}
+
 TEST_F(ConstantTest, AllEqualRange) {
     auto* vec3_ai = create<Vector>(create<AbstractInt>(), 3u);
     EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AllEqual(1, 3), false);