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:
parent
e9f8b09063
commit
609ce6de8d
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "src/tint/sem/constant.h"
|
#include "src/tint/sem/constant.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "src/tint/debug.h"
|
#include "src/tint/debug.h"
|
||||||
|
@ -26,6 +27,17 @@ namespace {
|
||||||
size_t CountElements(const Constant::Elements& elements) {
|
size_t CountElements(const Constant::Elements& elements) {
|
||||||
return std::visit([](auto&& vec) { return vec.size(); }, 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
|
} // namespace
|
||||||
|
|
||||||
Constant::Constant() {}
|
Constant::Constant() {}
|
||||||
|
@ -47,7 +59,7 @@ bool Constant::AnyZero() const {
|
||||||
return WithElements([&](auto&& vec) {
|
return WithElements([&](auto&& vec) {
|
||||||
using T = typename std::decay_t<decltype(vec)>::value_type;
|
using T = typename std::decay_t<decltype(vec)>::value_type;
|
||||||
for (auto el : vec) {
|
for (auto el : vec) {
|
||||||
if (el == T(0)) {
|
if (el == T(0) && !IsNegativeFloat(el.value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +71,7 @@ bool Constant::AllZero() const {
|
||||||
return WithElements([&](auto&& vec) {
|
return WithElements([&](auto&& vec) {
|
||||||
using T = typename std::decay_t<decltype(vec)>::value_type;
|
using T = typename std::decay_t<decltype(vec)>::value_type;
|
||||||
for (auto el : vec) {
|
for (auto el : vec) {
|
||||||
if (el != T(0)) {
|
if (el != T(0) || IsNegativeFloat(el.value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +83,9 @@ bool Constant::AllEqual(size_t start, size_t end) const {
|
||||||
return WithElements([&](auto&& vec) {
|
return WithElements([&](auto&& vec) {
|
||||||
if (!vec.empty()) {
|
if (!vec.empty()) {
|
||||||
auto value = vec[start];
|
auto value = vec[start];
|
||||||
|
bool float_sign = IsNegativeFloat(vec[start].value);
|
||||||
for (size_t i = start + 1; i < end; i++) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,13 +129,13 @@ class Constant {
|
||||||
/// @returns the elements as a vector of AFloat
|
/// @returns the elements as a vector of AFloat
|
||||||
inline const AFloats& FElements() const { return std::get<AFloats>(elems_); }
|
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;
|
bool AnyZero() const;
|
||||||
|
|
||||||
/// @returns true if all elements are zero
|
/// @returns true if all elements are positive zero
|
||||||
bool AllZero() const;
|
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()); }
|
bool AllEqual() const { return AllEqual(0, ElementCount()); }
|
||||||
|
|
||||||
/// @param start the first element index
|
/// @param start the first element index
|
||||||
|
|
|
@ -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, 0_a, 3_a}).AnyZero(), true);
|
||||||
EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_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);
|
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) {
|
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, 0_a, 3_a}).AllZero(), false);
|
||||||
EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 0_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);
|
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) {
|
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, {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, {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, {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) {
|
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, {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, 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, {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
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue