tint: Remove ConversionFailure::kTooSmall
Nothing errors on this. Simplifies code.
Also: Disable MSVC warnings about constant overflow.
Fixed: tint:1564
Change-Id: I5bb2c2ebb89966f5b3f7cbcd73672e110b1b98cd
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/91622
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/number.cc b/src/tint/number.cc
index 33b2af5..3ead5b0 100644
--- a/src/tint/number.cc
+++ b/src/tint/number.cc
@@ -26,8 +26,6 @@
return out << "value exceeds positive limit for type";
case ConversionFailure::kExceedsNegativeLimit:
return out << "value exceeds negative limit for type";
- case ConversionFailure::kTooSmall:
- return out << "value is too small for type";
}
return out << "<unknown>";
}
diff --git a/src/tint/number.h b/src/tint/number.h
index 4154462..6efb023 100644
--- a/src/tint/number.h
+++ b/src/tint/number.h
@@ -188,7 +188,6 @@
enum class ConversionFailure {
kExceedsPositiveLimit, // The value was too big (+'ve) to fit in the target type
kExceedsNegativeLimit, // The value was too big (-'ve) to fit in the target type
- kTooSmall, // The value was too small to fit in the target type
};
/// Writes the conversion failure message to the ostream.
@@ -209,12 +208,6 @@
if (value < static_cast<T>(TO::kLowest)) {
return ConversionFailure::kExceedsNegativeLimit;
}
- if constexpr (IsFloatingPoint<UnwrapNumber<TO>>) {
- if ((value < T(0) && value > static_cast<T>(-TO::kSmallest)) ||
- (value > T(0) && value < static_cast<T>(TO::kSmallest))) {
- return ConversionFailure::kTooSmall;
- }
- }
return TO(value); // Success
}
diff --git a/src/tint/number_test.cc b/src/tint/number_test.cc
index 615be0e..a7bb2fe 100644
--- a/src/tint/number_test.cc
+++ b/src/tint/number_test.cc
@@ -15,6 +15,7 @@
#include <cmath>
#include "src/tint/program_builder.h"
+#include "src/tint/utils/compiler_macros.h"
#include "gtest/gtest.h"
@@ -28,43 +29,40 @@
constexpr int64_t kLowestI32 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
constexpr int64_t kLowestU32 = static_cast<int64_t>(std::numeric_limits<uint32_t>::min());
-// Highest float32 value. Calculated as:
-// (2^127)×(1+(0x7fffff÷0x800000))
-constexpr double kHighestF32 = 340282346638528859811704183484516925440.0;
+// Highest float32 value.
+constexpr double kHighestF32 = 0x1.fffffep+127;
-// Next ULP up from kHighestF32 for a float64. Calculated as:
-// (2^127)×(1+(0xfffffe0000001÷0x10000000000000))
-constexpr double kHighestF32NextULP = 340282346638528897590636046441678635008.0;
+// Next ULP up from kHighestF32 for a float64.
+constexpr double kHighestF32NextULP = 0x1.fffffe0000001p+127;
-// Smallest positive normal float32 value. Calculated as:
-// 2^-126
-constexpr double kSmallestF32 = 1.1754943508222875e-38;
+// Smallest positive normal float32 value.
+constexpr double kSmallestF32 = 0x1p-126;
-// Next ULP down from kSmallestF32 for a float64. Calculated as:
-// (2^-127)×(1+(0xfffffffffffff÷0x10000000000000))
-constexpr double kSmallestF32PrevULP = 1.1754943508222874e-38;
+// Highest subnormal value for a float32.
+constexpr double kHighestF32Subnormal = 0x0.fffffep-126;
-// Highest float16 value. Calculated as:
-// (2^15)×(1+(0x3ff÷0x400))
-constexpr double kHighestF16 = 65504.0;
+// Highest float16 value.
+constexpr double kHighestF16 = 0x1.ffcp+15;
-// Next ULP up from kHighestF16 for a float64. Calculated as:
-// (2^15)×(1+(0xffc0000000001÷0x10000000000000))
-constexpr double kHighestF16NextULP = 65504.00000000001;
+// Next ULP up from kHighestF16 for a float64.
+constexpr double kHighestF16NextULP = 0x1.ffc0000000001p+15;
-// Smallest positive normal float16 value. Calculated as:
-// 2^-14
-constexpr double kSmallestF16 = 0.00006103515625;
+// Smallest positive normal float16 value.
+constexpr double kSmallestF16 = 0x1p-14;
-// Next ULP down from kSmallestF16 for a float64. Calculated as:
-// (2^-15)×(1+(0xfffffffffffff÷0x10000000000000))
-constexpr double kSmallestF16PrevULP = 0.00006103515624999999;
+// Highest subnormal value for a float32.
+constexpr double kHighestF16Subnormal = 0x0.ffcp-14;
constexpr double kLowestF32 = -kHighestF32;
constexpr double kLowestF32NextULP = -kHighestF32NextULP;
constexpr double kLowestF16 = -kHighestF16;
constexpr double kLowestF16NextULP = -kHighestF16NextULP;
+// MSVC (only in release builds) can grumble about some of the inlined numerical overflow /
+// underflow that's done in this file. We like to think we know what we're doing, so silence the
+// warning.
+TINT_BEGIN_DISABLE_WARNING(CONSTANT_OVERFLOW);
+
TEST(NumberTest, CheckedConvertIdentity) {
EXPECT_EQ(CheckedConvert<AInt>(0_a), 0_a);
EXPECT_EQ(CheckedConvert<AFloat>(0_a), 0.0_a);
@@ -120,9 +118,11 @@
ConversionFailure::kExceedsNegativeLimit);
}
-TEST(NumberTest, CheckedConvertTooSmall) {
- EXPECT_EQ(CheckedConvert<f32>(AFloat(kSmallestF32PrevULP)), ConversionFailure::kTooSmall);
- EXPECT_EQ(CheckedConvert<f16>(AFloat(kSmallestF16PrevULP)), ConversionFailure::kTooSmall);
+TEST(NumberTest, CheckedConvertSubnormals) {
+ EXPECT_EQ(CheckedConvert<f32>(AFloat(kHighestF32Subnormal)), f32(kHighestF32Subnormal));
+ EXPECT_EQ(CheckedConvert<f16>(AFloat(kHighestF16Subnormal)), f16(kHighestF16Subnormal));
+ EXPECT_EQ(CheckedConvert<f32>(AFloat(-kHighestF32Subnormal)), f32(-kHighestF32Subnormal));
+ EXPECT_EQ(CheckedConvert<f16>(AFloat(-kHighestF16Subnormal)), f16(-kHighestF16Subnormal));
}
TEST(NumberTest, QuantizeF16) {
@@ -141,5 +141,7 @@
EXPECT_TRUE(std::isnan(f16(nan)));
}
+TINT_END_DISABLE_WARNING(CONSTANT_OVERFLOW);
+
} // namespace
} // namespace tint
diff --git a/src/tint/reader/wgsl/lexer.cc b/src/tint/reader/wgsl/lexer.cc
index a97b162..1b69152 100644
--- a/src/tint/reader/wgsl/lexer.cc
+++ b/src/tint/reader/wgsl/lexer.cc
@@ -364,8 +364,6 @@
if (has_f_suffix) {
if (auto f = CheckedConvert<f32>(AFloat(value))) {
return {Token::Type::kFloatLiteral_F, source, static_cast<double>(f.Get())};
- } else if (f.Failure() == ConversionFailure::kTooSmall) {
- return {Token::Type::kFloatLiteral_F, source, 0.0};
} else {
return {Token::Type::kError, source, "value cannot be represented as 'f32'"};
}
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index 9f7be54..9f04a18 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -376,59 +376,60 @@
constexpr double kPiF64 = 3.141592653589793;
constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32
-// (2^-127)×(1+(0xfffffffffffff÷0x10000000000000))
-constexpr double kTooSmallF32 = 1.1754943508222874e-38;
+constexpr double kSubnormalF32 = 0x1.0p-128;
INSTANTIATE_TEST_SUITE_P(
MaterializeScalar,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kScalarMethods), //
- testing::Values(Types<i32, AInt>(0_a, 0.0), //
- Types<i32, AInt>(2147483647_a, 2147483647.0), //
- Types<i32, AInt>(-2147483648_a, -2147483648.0), //
- Types<u32, AInt>(0_a, 0.0), //
- Types<u32, AInt>(4294967295_a, 4294967295.0), //
- Types<f32, AFloat>(0.0_a, 0.0), //
- Types<f32, AFloat>(AFloat(kMaxF32), kMaxF32), //
- Types<f32, AFloat>(AFloat(-kMaxF32), -kMaxF32), //
- Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
- Types<f32, AFloat>(0.0_a, kTooSmallF32), //
- Types<f32, AFloat>(-0.0_a, -kTooSmallF32) //
- /* Types<f16, AFloat>(1.0_a), */ //
+ MaterializeAbstractNumeric, //
+ testing::Combine(testing::Values(Expectation::kMaterialize), //
+ testing::ValuesIn(kScalarMethods), //
+ testing::Values(Types<i32, AInt>(0_a, 0.0), //
+ Types<i32, AInt>(2147483647_a, 2147483647.0), //
+ Types<i32, AInt>(-2147483648_a, -2147483648.0), //
+ Types<u32, AInt>(0_a, 0.0), //
+ Types<u32, AInt>(4294967295_a, 4294967295.0), //
+ Types<f32, AFloat>(0.0_a, 0.0), //
+ Types<f32, AFloat>(AFloat(kMaxF32), kMaxF32), //
+ Types<f32, AFloat>(AFloat(-kMaxF32), -kMaxF32), //
+ Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
+ Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32) //
+ /* Types<f16, AFloat>(1.0_a), */ //
/* Types<f16, AFloat>(1.0_a), */)));
INSTANTIATE_TEST_SUITE_P(
MaterializeVector,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kVectorMethods), //
- testing::Values(Types<i32V, AIntV>(0_a, 0.0), //
- Types<i32V, AIntV>(2147483647_a, 2147483647.0), //
- Types<i32V, AIntV>(-2147483648_a, -2147483648.0), //
- Types<u32V, AIntV>(0_a, 0.0), //
- Types<u32V, AIntV>(4294967295_a, 4294967295.0), //
- Types<f32V, AFloatV>(0.0_a, 0.0), //
- Types<f32V, AFloatV>(AFloat(kMaxF32), kMaxF32), //
- Types<f32V, AFloatV>(AFloat(-kMaxF32), -kMaxF32), //
- Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
- Types<f32V, AFloatV>(0.0_a, kTooSmallF32), //
- Types<f32V, AFloatV>(-0.0_a, -kTooSmallF32) //
- /* Types<f16V, AFloatV>(1.0_a), */ //
+ MaterializeAbstractNumeric, //
+ testing::Combine(testing::Values(Expectation::kMaterialize), //
+ testing::ValuesIn(kVectorMethods), //
+ testing::Values(Types<i32V, AIntV>(0_a, 0.0), //
+ Types<i32V, AIntV>(2147483647_a, 2147483647.0), //
+ Types<i32V, AIntV>(-2147483648_a, -2147483648.0), //
+ Types<u32V, AIntV>(0_a, 0.0), //
+ Types<u32V, AIntV>(4294967295_a, 4294967295.0), //
+ Types<f32V, AFloatV>(0.0_a, 0.0), //
+ Types<f32V, AFloatV>(AFloat(kMaxF32), kMaxF32), //
+ Types<f32V, AFloatV>(AFloat(-kMaxF32), -kMaxF32), //
+ Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
+ Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32V, AFloatV>(AFloat(-kSubnormalF32),
+ -kSubnormalF32) //
+ /* Types<f16V, AFloatV>(1.0_a), */ //
/* Types<f16V, AFloatV>(1.0_a), */)));
INSTANTIATE_TEST_SUITE_P(
MaterializeMatrix,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kMatrixMethods), //
- testing::Values(Types<f32M, AFloatM>(0.0_a, 0.0), //
- Types<f32M, AFloatM>(AFloat(kMaxF32), kMaxF32), //
- Types<f32M, AFloatM>(AFloat(-kMaxF32), -kMaxF32), //
- Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
- Types<f32M, AFloatM>(0.0_a, kTooSmallF32), //
- Types<f32M, AFloatM>(-0.0_a, -kTooSmallF32) //
- /* Types<f16V, AFloatM>(1.0_a), */ //
+ MaterializeAbstractNumeric, //
+ testing::Combine(testing::Values(Expectation::kMaterialize), //
+ testing::ValuesIn(kMatrixMethods), //
+ testing::Values(Types<f32M, AFloatM>(0.0_a, 0.0), //
+ Types<f32M, AFloatM>(AFloat(kMaxF32), kMaxF32), //
+ Types<f32M, AFloatM>(AFloat(-kMaxF32), -kMaxF32), //
+ Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
+ Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32M, AFloatM>(AFloat(-kSubnormalF32),
+ -kSubnormalF32) //
+ /* Types<f16V, AFloatM>(1.0_a), */ //
)));
INSTANTIATE_TEST_SUITE_P(
diff --git a/src/tint/resolver/resolver_constants.cc b/src/tint/resolver/resolver_constants.cc
index 3bf8df0..b281f91 100644
--- a/src/tint/resolver/resolver_constants.cc
+++ b/src/tint/resolver/resolver_constants.cc
@@ -39,7 +39,7 @@
/// @returns the elements converted to type T.
template <typename T, typename ELEMENTS_IN, typename CONVERTER>
sem::Constant::Elements Transform(const ELEMENTS_IN& elements_in, CONVERTER&& converter) {
- TINT_BEGIN_DISABLE_WARNING_UNREACHABLE_CODE();
+ TINT_BEGIN_DISABLE_WARNING(UNREACHABLE_CODE);
return utils::Transform(elements_in, [&](auto value_in) {
if constexpr (std::is_same_v<UnwrapNumber<T>, bool>) {
@@ -55,7 +55,7 @@
}
});
- TINT_END_DISABLE_WARNING_UNREACHABLE_CODE();
+ TINT_END_DISABLE_WARNING(UNREACHABLE_CODE);
}
/// Converts and returns all the element values of `in` to the semantic type `el_ty`, using the
@@ -112,9 +112,6 @@
case ConversionFailure::kExceedsPositiveLimit:
el_out = IsFloatingPoint<UnwrapNumber<OUT>> ? OUT(kInf) : OUT::kHighest;
break;
- case ConversionFailure::kTooSmall:
- el_out = OUT(el_in < 0 ? -0.0 : 0.0);
- break;
}
}
});
@@ -137,8 +134,6 @@
using OUT = std::decay_t<decltype(el_out)>;
if (auto conv = CheckedConvert<OUT>(el_in)) {
el_out = conv.Get();
- } else if (conv.Failure() == ConversionFailure::kTooSmall) {
- el_out = OUT(el_in < 0 ? -0.0 : 0.0);
} else if (!failure.has_value()) {
std::stringstream ss;
ss << "value " << el_in << " cannot be represented as ";
diff --git a/src/tint/utils/compiler_macros.h b/src/tint/utils/compiler_macros.h
index 8b360ff..ada138e 100644
--- a/src/tint/utils/compiler_macros.h
+++ b/src/tint/utils/compiler_macros.h
@@ -12,27 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/utils/concat.h"
+
#ifndef SRC_TINT_UTILS_COMPILER_MACROS_H_
#define SRC_TINT_UTILS_COMPILER_MACROS_H_
-#define TINT_REQUIRE_SEMICOLON \
- do { \
- } while (false)
+#define TINT_REQUIRE_SEMICOLON static_assert(true)
#if defined(_MSC_VER)
+#define TINT_WARNING_UNREACHABLE_CODE 4702
+#define TINT_WARNING_CONSTANT_OVERFLOW 4756
+
// clang-format off
-#define TINT_BEGIN_DISABLE_WARNING_UNREACHABLE_CODE() \
- __pragma(warning(push)) \
- __pragma(warning(disable:4702)) \
+#define TINT_BEGIN_DISABLE_WARNING(name) \
+ __pragma(warning(push)) \
+ __pragma(warning(disable:TINT_CONCAT(TINT_WARNING_, name))) \
TINT_REQUIRE_SEMICOLON
-#define TINT_END_DISABLE_WARNING_UNREACHABLE_CODE() \
- __pragma(warning(pop)) \
+#define TINT_END_DISABLE_WARNING(name) \
+ __pragma(warning(pop)) \
TINT_REQUIRE_SEMICOLON
// clang-format on
#else
// clang-format off
-#define TINT_BEGIN_DISABLE_WARNING_UNREACHABLE_CODE() TINT_REQUIRE_SEMICOLON
-#define TINT_END_DISABLE_WARNING_UNREACHABLE_CODE() TINT_REQUIRE_SEMICOLON
+#define TINT_BEGIN_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON
+#define TINT_END_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON
// clang-format on
#endif // defined(_MSC_VER)