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>
This commit is contained in:
parent
4b04721075
commit
572eaf271e
|
@ -26,8 +26,6 @@ std::ostream& operator<<(std::ostream& out, ConversionFailure failure) {
|
|||
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>";
|
||||
}
|
||||
|
|
|
@ -188,7 +188,6 @@ std::enable_if_t<IsNumeric<A>, bool> operator!=(A a, Number<B> b) {
|
|||
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 @@ utils::Result<TO, ConversionFailure> CheckedConvert(Number<FROM> num) {
|
|||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 kHighestU32 = static_cast<int64_t>(std::numeric_limits<uint32_
|
|||
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 @@ TEST(NumberTest, CheckedConvertExceedsNegativeLimit) {
|
|||
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 @@ TEST(NumberTest, QuantizeF16) {
|
|||
EXPECT_TRUE(std::isnan(f16(nan)));
|
||||
}
|
||||
|
||||
TINT_END_DISABLE_WARNING(CONSTANT_OVERFLOW);
|
||||
|
||||
} // namespace
|
||||
} // namespace tint
|
||||
|
|
|
@ -364,8 +364,6 @@ Token Lexer::try_float() {
|
|||
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'"};
|
||||
}
|
||||
|
|
|
@ -376,59 +376,60 @@ constexpr double kMaxF32 = static_cast<double>(f32::kHighest);
|
|||
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(
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace {
|
|||
/// @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 @@ sem::Constant::Elements Transform(const ELEMENTS_IN& elements_in, CONVERTER&& co
|
|||
}
|
||||
});
|
||||
|
||||
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 @@ sem::Constant::Elements ConvertElements(const sem::Constant::Elements& in, const
|
|||
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 @@ utils::Result<sem::Constant::Elements> MaterializeElements(const sem::Constant::
|
|||
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 ";
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
fn foo() {
|
||||
let b = 1e-40f;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#version 310 es
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
||||
void foo() {
|
||||
float b = 9.9999461e-41f;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
[numthreads(1, 1, 1)]
|
||||
void unused_entry_point() {
|
||||
return;
|
||||
}
|
||||
|
||||
void foo() {
|
||||
const float b = 9.9999461e-41f;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
void foo() {
|
||||
float const b = 9.9999461e-41f;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
; SPIR-V
|
||||
; Version: 1.3
|
||||
; Generator: Google Tint Compiler; 0
|
||||
; Bound: 9
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
|
||||
OpExecutionMode %unused_entry_point LocalSize 1 1 1
|
||||
OpName %unused_entry_point "unused_entry_point"
|
||||
OpName %foo "foo"
|
||||
%void = OpTypeVoid
|
||||
%1 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%float_0x1_16c2pn133 = OpConstant %float 0x1.16c2p-133
|
||||
%unused_entry_point = OpFunction %void None %1
|
||||
%4 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%foo = OpFunction %void None %1
|
||||
%6 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
|
@ -0,0 +1,3 @@
|
|||
fn foo() {
|
||||
let b = 0x1.16c2p-133;
|
||||
}
|
Loading…
Reference in New Issue