tint/sem: Consider sign bit for Constant helpers.

Constant::AnyZero(), Constant::AllZero() now consider -0.0 as non-zero,
as this is different from WGSL's zero-initializer value for floating
point numbers.

Also consider FP sign for Constant::AllEqual().

Bug: tint:1504
Change-Id: I00503880ee29bd741b94cc98909a8a823e32522a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/92243
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2022-06-01 15:35:50 +00:00 committed by Dawn LUCI CQ
parent e9f8b09063
commit 609ce6de8d
3 changed files with 80 additions and 6 deletions

View File

@ -14,6 +14,7 @@
#include "src/tint/sem/constant.h"
#include <cmath>
#include <utility>
#include "src/tint/debug.h"
@ -26,6 +27,17 @@ namespace {
size_t CountElements(const Constant::Elements& elements) {
return std::visit([](auto&& vec) { return vec.size(); }, elements);
}
template <typename T>
bool IsNegativeFloat(T value) {
(void)value;
if constexpr (IsFloatingPoint<T>) {
return std::signbit(value);
} else {
return false;
}
}
} // namespace
Constant::Constant() {}
@ -47,7 +59,7 @@ bool Constant::AnyZero() const {
return WithElements([&](auto&& vec) {
using T = typename std::decay_t<decltype(vec)>::value_type;
for (auto el : vec) {
if (el == T(0)) {
if (el == T(0) && !IsNegativeFloat(el.value)) {
return true;
}
}
@ -59,7 +71,7 @@ bool Constant::AllZero() const {
return WithElements([&](auto&& vec) {
using T = typename std::decay_t<decltype(vec)>::value_type;
for (auto el : vec) {
if (el != T(0)) {
if (el != T(0) || IsNegativeFloat(el.value)) {
return false;
}
}
@ -71,8 +83,9 @@ bool Constant::AllEqual(size_t start, size_t end) const {
return WithElements([&](auto&& vec) {
if (!vec.empty()) {
auto value = vec[start];
bool float_sign = IsNegativeFloat(vec[start].value);
for (size_t i = start + 1; i < end; i++) {
if (vec[i] != value) {
if (vec[i] != value || float_sign != IsNegativeFloat(vec[i].value)) {
return false;
}
}

View File

@ -129,13 +129,13 @@ class Constant {
/// @returns the elements as a vector of AFloat
inline const AFloats& FElements() const { return std::get<AFloats>(elems_); }
/// @returns true if any element is zero
/// @returns true if any element is positive zero
bool AnyZero() const;
/// @returns true if all elements are zero
/// @returns true if all elements are positive zero
bool AllZero() const;
/// @returns true if all elements are the same value
/// @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

View File

@ -202,6 +202,20 @@ TEST_F(ConstantTest, AnyZero) {
EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 3_a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AnyZero(), true);
auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AnyZero(), false);
EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 3._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 3._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 0._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 3._a}).AnyZero(), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -2._a, 3._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 3._a}).AnyZero(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 0._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AnyZero(), true);
EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, -0._a}).AnyZero(), false);
}
TEST_F(ConstantTest, AllZero) {
@ -211,6 +225,20 @@ TEST_F(ConstantTest, AllZero) {
EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 3_a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AllZero(), true);
auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {0._a, 2._a, 3._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 3._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 0._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AllZero(), true);
EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 3._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -2._a, 3._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 3._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, -2._a, 0._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllZero(), false);
EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, -0._a}).AllZero(), false);
}
TEST_F(ConstantTest, AllEqual) {
@ -221,6 +249,17 @@ TEST_F(ConstantTest, AllEqual) {
EXPECT_EQ(Constant(vec3_ai, {1_a, 1_a, 1_a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_ai, {2_a, 2_a, 2_a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_ai, {3_a, 3_a, 3_a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AllEqual(), true);
auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllEqual(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 3._a}).AllEqual(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 3._a, 3._a}).AllEqual(), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 1._a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_af, {2._a, 2._a, 2._a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_af, {3._a, 3._a, 3._a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AllEqual(), true);
EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllEqual(), false);
}
TEST_F(ConstantTest, AllEqualRange) {
@ -231,6 +270,28 @@ TEST_F(ConstantTest, AllEqualRange) {
EXPECT_EQ(Constant(vec3_ai, {1_a, 1_a, 1_a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_ai, {2_a, 2_a, 2_a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_ai, {2_a, 2_a, 3_a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_ai, {1_a, 0_a, 0_a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_ai, {0_a, 1_a, 0_a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 1_a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_ai, {0_a, 0_a, 0_a}).AllEqual(1, 3), true);
auto* vec3_af = create<Vector>(create<AbstractFloat>(), 3u);
EXPECT_EQ(Constant(vec3_af, {1._a, 2._a, 3._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 3._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 3._a, 3._a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_af, {1._a, 1._a, 1._a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_af, {2._a, 2._a, 2._a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_af, {2._a, 2._a, 3._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {1._a, 0._a, 0._a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_af, {0._a, 1._a, 0._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 1._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {0._a, 0._a, 0._a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_af, {1._a, -0._a, 0._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -1._a, 0._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 1._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, 0._a}).AllEqual(1, 3), false);
EXPECT_EQ(Constant(vec3_af, {0._a, -0._a, -0._a}).AllEqual(1, 3), true);
EXPECT_EQ(Constant(vec3_af, {-0._a, -0._a, -0._a}).AllEqual(1, 3), true);
}
} // namespace