tint: make const eval of binary ops on concrete values fail on NaN/Inf

With this CL, binary ops add, subtract, multiply, and divide of concrete
values will now produce an error if the result is inf/NaN, as it was
doing with abstract values. This also affects the cross builtin, which
is written in terms of subtract and multiply.

Bug: tint:1581
Bug: tint:1747
Change-Id: Ib1d0d8deddc82c67ab53729a6011937636fcc1a5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/110163
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Antonio Maiorano 2022-11-18 05:45:17 +00:00
parent e956a04daf
commit 0da91e06c5
13 changed files with 145 additions and 165 deletions

View File

@ -375,7 +375,7 @@ TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, TwoParams_Vector_f32) {
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Scalar_f32) { TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Scalar_f32) {
auto param = GetParam(); auto param = GetParam();
auto* call = Call(param.name, 1_f, 1_f, 1_f); auto* call = Call(param.name, 0_f, 1_f, 2_f);
WrapInFunction(call); WrapInFunction(call);
if (param.args_number == 3u) { if (param.args_number == 3u) {
@ -396,8 +396,8 @@ TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Scalar_f32) {
TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Vector_f32) { TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Vector_f32) {
auto param = GetParam(); auto param = GetParam();
auto* call = Call(param.name, vec3<f32>(1_f, 1_f, 3_f), vec3<f32>(1_f, 1_f, 3_f), auto* call = Call(param.name, vec3<f32>(0_f, 0_f, 0_f), vec3<f32>(1_f, 1_f, 1_f),
vec3<f32>(1_f, 1_f, 3_f)); vec3<f32>(2_f, 2_f, 2_f));
WrapInFunction(call); WrapInFunction(call);
if (param.args_number == 3u) { if (param.args_number == 3u) {
@ -577,7 +577,7 @@ TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Scalar_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* call = Call(param.name, 1_h, 1_h, 1_h); auto* call = Call(param.name, 0_h, 1_h, 2_h);
WrapInFunction(call); WrapInFunction(call);
if (param.args_number == 3u) { if (param.args_number == 3u) {
@ -600,8 +600,8 @@ TEST_P(ResolverBuiltinTest_FloatBuiltin_IdenticalType, ThreeParams_Vector_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* call = Call(param.name, vec3<f16>(1_h, 1_h, 3_h), vec3<f16>(1_h, 1_h, 3_h), auto* call = Call(param.name, vec3<f16>(0_h, 0_h, 0_h), vec3<f16>(1_h, 1_h, 1_h),
vec3<f16>(1_h, 1_h, 3_h)); vec3<f16>(2_h, 2_h, 2_h));
WrapInFunction(call); WrapInFunction(call);
if (param.args_number == 3u) { if (param.args_number == 3u) {

View File

@ -1099,7 +1099,7 @@ TEST_P(FloatAllMatching, Scalar) {
utils::Vector<const ast::Expression*, 8> params; utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) { for (uint32_t i = 0; i < num_params; ++i) {
params.Push(Expr(1_f)); params.Push(Expr(f32(i)));
} }
auto* builtin = Call(name, params); auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(), Func("func", utils::Empty, ty.void_(),
@ -1120,7 +1120,7 @@ TEST_P(FloatAllMatching, Vec2) {
utils::Vector<const ast::Expression*, 8> params; utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) { for (uint32_t i = 0; i < num_params; ++i) {
params.Push(vec2<f32>(1_f, 1_f)); params.Push(vec2<f32>(f32(i), f32(i)));
} }
auto* builtin = Call(name, params); auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(), Func("func", utils::Empty, ty.void_(),
@ -1141,7 +1141,7 @@ TEST_P(FloatAllMatching, Vec3) {
utils::Vector<const ast::Expression*, 8> params; utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) { for (uint32_t i = 0; i < num_params; ++i) {
params.Push(vec3<f32>(1_f, 1_f, 1_f)); params.Push(vec3<f32>(f32(i), f32(i), f32(i)));
} }
auto* builtin = Call(name, params); auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(), Func("func", utils::Empty, ty.void_(),
@ -1162,7 +1162,7 @@ TEST_P(FloatAllMatching, Vec4) {
utils::Vector<const ast::Expression*, 8> params; utils::Vector<const ast::Expression*, 8> params;
for (uint32_t i = 0; i < num_params; ++i) { for (uint32_t i = 0; i < num_params; ++i) {
params.Push(vec4<f32>(1_f, 1_f, 1_f, 1_f)); params.Push(vec4<f32>(f32(i), f32(i), f32(i), f32(i)));
} }
auto* builtin = Call(name, params); auto* builtin = Call(name, params);
Func("func", utils::Empty, ty.void_(), Func("func", utils::Empty, ty.void_(),

View File

@ -655,8 +655,7 @@ ConstEval::ConstEval(ProgramBuilder& b) : builder(b) {}
template <typename NumberT> template <typename NumberT>
utils::Result<NumberT> ConstEval::Add(NumberT a, NumberT b) { utils::Result<NumberT> ConstEval::Add(NumberT a, NumberT b) {
NumberT result; NumberT result;
if constexpr (IsAbstract<NumberT>) { if constexpr (IsAbstract<NumberT> || IsFloatingPoint<NumberT>) {
// Check for over/underflow for abstract values
if (auto r = CheckedAdd(a, b)) { if (auto r = CheckedAdd(a, b)) {
result = r->value; result = r->value;
} else { } else {
@ -682,8 +681,7 @@ utils::Result<NumberT> ConstEval::Add(NumberT a, NumberT b) {
template <typename NumberT> template <typename NumberT>
utils::Result<NumberT> ConstEval::Sub(NumberT a, NumberT b) { utils::Result<NumberT> ConstEval::Sub(NumberT a, NumberT b) {
NumberT result; NumberT result;
if constexpr (IsAbstract<NumberT>) { if constexpr (IsAbstract<NumberT> || IsFloatingPoint<NumberT>) {
// Check for over/underflow for abstract values
if (auto r = CheckedSub(a, b)) { if (auto r = CheckedSub(a, b)) {
result = r->value; result = r->value;
} else { } else {
@ -710,7 +708,7 @@ template <typename NumberT>
utils::Result<NumberT> ConstEval::Mul(NumberT a, NumberT b) { utils::Result<NumberT> ConstEval::Mul(NumberT a, NumberT b) {
using T = UnwrapNumber<NumberT>; using T = UnwrapNumber<NumberT>;
NumberT result; NumberT result;
if constexpr (IsAbstract<NumberT>) { if constexpr (IsAbstract<NumberT> || IsFloatingPoint<NumberT>) {
// Check for over/underflow for abstract values // Check for over/underflow for abstract values
if (auto r = CheckedMul(a, b)) { if (auto r = CheckedMul(a, b)) {
result = r->value; result = r->value;
@ -736,7 +734,7 @@ utils::Result<NumberT> ConstEval::Mul(NumberT a, NumberT b) {
template <typename NumberT> template <typename NumberT>
utils::Result<NumberT> ConstEval::Div(NumberT a, NumberT b) { utils::Result<NumberT> ConstEval::Div(NumberT a, NumberT b) {
NumberT result; NumberT result;
if constexpr (IsAbstract<NumberT>) { if constexpr (IsAbstract<NumberT> || IsFloatingPoint<NumberT>) {
// Check for over/underflow for abstract values // Check for over/underflow for abstract values
if (auto r = CheckedDiv(a, b)) { if (auto r = CheckedDiv(a, b)) {
result = r->value; result = r->value;
@ -1922,8 +1920,6 @@ ConstEval::Result ConstEval::cross(const sem::Type* ty,
auto* v1 = v->Index(1); auto* v1 = v->Index(1);
auto* v2 = v->Index(2); auto* v2 = v->Index(2);
// auto x = Dispatch_fa_f32_f16(ab_minus_cd_func(elem_ty), u->Index(1), v->Index(2),
// v->Index(1), u->Index(2));
auto x = Dispatch_fa_f32_f16(Det2Func(elem_ty), u1, u2, v1, v2); auto x = Dispatch_fa_f32_f16(Det2Func(elem_ty), u1, u2, v1, v2);
if (!x) { if (!x) {
return utils::Failure; return utils::Failure;

View File

@ -144,46 +144,41 @@ std::vector<Case> OpAddIntCases() {
C(T::Highest(), Negate(T{1}), T{T::Highest() - 1}), C(T::Highest(), Negate(T{1}), T{T::Highest() - 1}),
C(T::Lowest(), T::Highest(), Negate(T{1})), C(T::Lowest(), T::Highest(), Negate(T{1})),
}; };
ConcatIntoIf<!IsAbstract<T>>( // if constexpr (IsAbstract<T>) {
r, std::vector<Case>{
C(T::Highest(), T{1}, T::Lowest()),
C(T::Lowest(), Negate(T{1}), T::Highest()),
});
auto error_msg = [](auto a, auto b) { auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "+", b); return "12:34 error: " + OverflowErrorMessage(a, "+", b);
}; };
ConcatIntoIf<IsAbstract<T>>( // ConcatInto( //
r, std::vector<Case>{ r, std::vector<Case>{
E(T::Highest(), T{1}, error_msg(T::Highest(), T{1})), E(T::Highest(), T{1}, error_msg(T::Highest(), T{1})),
E(T::Lowest(), Negate(T{1}), error_msg(T::Lowest(), Negate(T{1}))), E(T::Lowest(), Negate(T{1}), error_msg(T::Lowest(), Negate(T{1}))),
}); });
} else {
ConcatInto( //
r, std::vector<Case>{
C(T::Highest(), T{1}, T::Lowest()),
C(T::Lowest(), Negate(T{1}), T::Highest()),
});
}
return r; return r;
} }
template <typename T> template <typename T>
std::vector<Case> OpAddFloatCases() { std::vector<Case> OpAddFloatCases() {
static_assert(IsFloatingPoint<T>); static_assert(IsFloatingPoint<T>);
auto r = std::vector<Case>{ auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "+", b);
};
return std::vector<Case>{
C(T{0}, T{0}, T{0}), C(T{0}, T{0}, T{0}),
C(T{1}, T{2}, T{3}), C(T{1}, T{2}, T{3}),
C(T::Lowest(), T{1}, T{T::Lowest() + 1}), C(T::Lowest(), T{1}, T{T::Lowest() + 1}),
C(T::Highest(), Negate(T{1}), T{T::Highest() - 1}), C(T::Highest(), Negate(T{1}), T{T::Highest() - 1}),
C(T::Lowest(), T::Highest(), T{0}), C(T::Lowest(), T::Highest(), T{0}),
};
ConcatIntoIf<!IsAbstract<T>>( //
r, std::vector<Case>{
C(T::Highest(), T::Highest(), T::Inf()),
C(T::Lowest(), Negate(T::Highest()), -T::Inf()),
});
auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "+", b);
};
ConcatIntoIf<IsAbstract<T>>( //
r, std::vector<Case>{
E(T::Highest(), T::Highest(), error_msg(T::Highest(), T::Highest())), E(T::Highest(), T::Highest(), error_msg(T::Highest(), T::Highest())),
E(T::Lowest(), Negate(T::Highest()), error_msg(T::Lowest(), Negate(T::Highest()))), E(T::Lowest(), Negate(T::Highest()), error_msg(T::Lowest(), Negate(T::Highest()))),
}); };
return r;
} }
INSTANTIATE_TEST_SUITE_P(Add, INSTANTIATE_TEST_SUITE_P(Add,
ResolverConstEvalBinaryOpTest, ResolverConstEvalBinaryOpTest,
@ -206,45 +201,40 @@ std::vector<Case> OpSubIntCases() {
C(T{T::Highest() - 1}, Negate(T{1}), T::Highest()), C(T{T::Highest() - 1}, Negate(T{1}), T::Highest()),
C(Negate(T{1}), T::Highest(), T::Lowest()), C(Negate(T{1}), T::Highest(), T::Lowest()),
}; };
ConcatIntoIf<!IsAbstract<T>>( // if constexpr (IsAbstract<T>) {
r, std::vector<Case>{
C(T::Lowest(), T{1}, T::Highest()),
C(T::Highest(), Negate(T{1}), T::Lowest()),
});
auto error_msg = [](auto a, auto b) { auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "-", b); return "12:34 error: " + OverflowErrorMessage(a, "-", b);
}; };
ConcatIntoIf<IsAbstract<T>>( // ConcatInto( //
r, std::vector<Case>{ r, std::vector<Case>{
E(T::Lowest(), T{1}, error_msg(T::Lowest(), T{1})), E(T::Lowest(), T{1}, error_msg(T::Lowest(), T{1})),
E(T::Highest(), Negate(T{1}), error_msg(T::Highest(), Negate(T{1}))), E(T::Highest(), Negate(T{1}), error_msg(T::Highest(), Negate(T{1}))),
}); });
} else {
ConcatInto( //
r, std::vector<Case>{
C(T::Lowest(), T{1}, T::Highest()),
C(T::Highest(), Negate(T{1}), T::Lowest()),
});
}
return r; return r;
} }
template <typename T> template <typename T>
std::vector<Case> OpSubFloatCases() { std::vector<Case> OpSubFloatCases() {
static_assert(IsFloatingPoint<T>); static_assert(IsFloatingPoint<T>);
auto r = std::vector<Case>{ auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "-", b);
};
return std::vector<Case>{
C(T{0}, T{0}, T{0}), C(T{0}, T{0}, T{0}),
C(T{3}, T{2}, T{1}), C(T{3}, T{2}, T{1}),
C(T::Highest(), T{1}, T{T::Highest() - 1}), C(T::Highest(), T{1}, T{T::Highest() - 1}),
C(T::Lowest(), Negate(T{1}), T{T::Lowest() + 1}), C(T::Lowest(), Negate(T{1}), T{T::Lowest() + 1}),
C(T{0}, T::Highest(), T::Lowest()), C(T{0}, T::Highest(), T::Lowest()),
};
ConcatIntoIf<!IsAbstract<T>>( //
r, std::vector<Case>{
C(T::Highest(), Negate(T::Highest()), T::Inf()),
C(T::Lowest(), T::Highest(), -T::Inf()),
});
auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "-", b);
};
ConcatIntoIf<IsAbstract<T>>( //
r, std::vector<Case>{
E(T::Highest(), Negate(T::Highest()), error_msg(T::Highest(), Negate(T::Highest()))), E(T::Highest(), Negate(T::Highest()), error_msg(T::Highest(), Negate(T::Highest()))),
E(T::Lowest(), T::Highest(), error_msg(T::Lowest(), T::Highest())), E(T::Lowest(), T::Highest(), error_msg(T::Lowest(), T::Highest())),
}); };
return r;
} }
INSTANTIATE_TEST_SUITE_P(Sub, INSTANTIATE_TEST_SUITE_P(Sub,
ResolverConstEvalBinaryOpTest, ResolverConstEvalBinaryOpTest,
@ -267,21 +257,25 @@ std::vector<Case> OpMulScalarCases() {
C(T::Highest(), T{1}, T::Highest()), C(T::Highest(), T{1}, T::Highest()),
C(T::Lowest(), T{1}, T::Lowest()), C(T::Lowest(), T{1}, T::Lowest()),
}; };
ConcatIntoIf<!IsAbstract<T>>( // if constexpr (IsAbstract<T> || IsFloatingPoint<T>) {
r, std::vector<Case>{
C(T::Highest(), T::Highest(), Mul(T::Highest(), T::Highest())),
C(T::Lowest(), T::Lowest(), Mul(T::Lowest(), T::Lowest())),
});
auto error_msg = [](auto a, auto b) { auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "*", b); return "12:34 error: " + OverflowErrorMessage(a, "*", b);
}; };
ConcatIntoIf<IsAbstract<T>>( // ConcatInto( //
r, std::vector<Case>{ r, std::vector<Case>{
// Fail if result is +/-inf
E(T::Highest(), T::Highest(), error_msg(T::Highest(), T::Highest())), E(T::Highest(), T::Highest(), error_msg(T::Highest(), T::Highest())),
E(T::Lowest(), T::Lowest(), error_msg(T::Lowest(), T::Lowest())), E(T::Lowest(), T::Lowest(), error_msg(T::Lowest(), T::Lowest())),
E(T::Highest(), T{2}, error_msg(T::Highest(), T{2})), E(T::Highest(), T{2}, error_msg(T::Highest(), T{2})),
E(T::Lowest(), Negate(T{2}), error_msg(T::Lowest(), Negate(T{2}))), E(T::Lowest(), Negate(T{2}), error_msg(T::Lowest(), Negate(T{2}))),
}); });
} else {
ConcatInto( //
r, std::vector<Case>{
C(T::Highest(), T::Highest(), Mul(T::Highest(), T::Highest())),
C(T::Lowest(), T::Lowest(), Mul(T::Lowest(), T::Lowest())),
});
}
return r; return r;
} }
@ -295,14 +289,24 @@ std::vector<Case> OpMulVecCases() {
// vec3 * vec3 = vec3 // vec3 * vec3 = vec3
C(Vec(T{1.25}, T{2.25}, T{3.25}), Vec(T{2.0}, T{2.0}, T{2.0}), Vec(T{2.5}, T{4.5}, T{6.5})), C(Vec(T{1.25}, T{2.25}, T{3.25}), Vec(T{2.0}, T{2.0}, T{2.0}), Vec(T{2.5}, T{4.5}, T{6.5})),
}; };
if constexpr (IsAbstract<T> || IsFloatingPoint<T>) {
auto error_msg = [](auto a, auto b) { auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "*", b); return "12:34 error: " + OverflowErrorMessage(a, "*", b);
}; };
ConcatIntoIf<IsAbstract<T>>( // ConcatInto( //
r, std::vector<Case>{ r,
std::vector<Case>{
// Fail if result is +/-inf
E(Val(T::Highest()), Vec(T{2}, T{1}), error_msg(T::Highest(), T{2})), E(Val(T::Highest()), Vec(T{2}, T{1}), error_msg(T::Highest(), T{2})),
E(Val(T::Lowest()), Vec(Negate(T{2}), T{1}), error_msg(T::Lowest(), Negate(T{2}))), E(Val(T::Lowest()), Vec(Negate(T{2}), T{1}), error_msg(T::Lowest(), Negate(T{2}))),
}); });
} else {
ConcatInto( //
r, std::vector<Case>{
C(Val(T::Highest()), Vec(T{2}, T{1}), Vec(T{-2}, T::Highest())),
C(Val(T::Lowest()), Vec(Negate(T{2}), T{1}), Vec(T{0}, T{T::Lowest()})),
});
}
return r; return r;
} }
@ -347,7 +351,7 @@ std::vector<Case> OpMulMatCases() {
auto error_msg = [](auto a, const char* op, auto b) { auto error_msg = [](auto a, const char* op, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, op, b); return "12:34 error: " + OverflowErrorMessage(a, op, b);
}; };
ConcatIntoIf<IsAbstract<T>>( // ConcatIntoIf<IsAbstract<T> || IsFloatingPoint<T>>( //
r, std::vector<Case>{ r, std::vector<Case>{
// vector-matrix multiply // vector-matrix multiply
@ -389,10 +393,10 @@ std::vector<Case> OpMulMatCases() {
// Overflow from second multiplication of dot product of lhs row 0 and rhs column 0 // Overflow from second multiplication of dot product of lhs row 0 and rhs column 0
// i.e. m1[0][0] * m2[0][0] + m1[0][1] * m[1][0] // i.e. m1[0][0] * m2[0][0] + m1[0][1] * m[1][0]
// ^ // ^
E(Mat({T{1.0}, T::Highest()}, // E(Mat({T{1.0}, T{1.0}}, //
{T::Highest(), T{1.0}}), //
Mat({T{1.0}, T{2.0}}, //
{T{1.0}, T{1.0}}), // {T{1.0}, T{1.0}}), //
Mat({T{1.0}, T{1.0}}, //
{T{2.0}, T{1.0}}), //
error_msg(T::Highest(), "*", T{2.0})), error_msg(T::Highest(), "*", T{2.0})),
// Overflow from addition of dot product of lhs row 0 and rhs column 0 // Overflow from addition of dot product of lhs row 0 and rhs column 0
@ -453,11 +457,23 @@ std::vector<Case> OpDivIntCases() {
// e1, when e1 is the most negative value in T, and e2 is -1. // e1, when e1 is the most negative value in T, and e2 is -1.
C(T::Smallest(), T{-1}, T::Smallest()), C(T::Smallest(), T{-1}, T::Smallest()),
}); });
auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "/", b);
};
ConcatIntoIf<IsAbstract<T>>( //
r, std::vector<Case>{
// Most negative value divided by -1
E(AInt::Lowest(), -1_a, error_msg(AInt::Lowest(), -1_a)),
});
return r; return r;
} }
template <typename T> template <typename T>
std::vector<Case> OpDivFloatCases() { std::vector<Case> OpDivFloatCases() {
auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "/", b);
};
std::vector<Case> r = { std::vector<Case> r = {
C(Val(T{0}), Val(T{1}), Val(T{0})), C(Val(T{0}), Val(T{1}), Val(T{0})),
C(Val(T{1}), Val(T{1}), Val(T{1})), C(Val(T{1}), Val(T{1}), Val(T{1})),
@ -469,32 +485,13 @@ std::vector<Case> OpDivFloatCases() {
C(Val(T::Highest()), Val(T::Highest()), Val(T{1})), C(Val(T::Highest()), Val(T::Highest()), Val(T{1})),
C(Val(T{0}), Val(T::Highest()), Val(T{0})), C(Val(T{0}), Val(T::Highest()), Val(T{0})),
C(Val(T{0}), Val(T::Lowest()), Val(-T{0})), C(Val(T{0}), Val(T::Lowest()), Val(-T{0})),
};
ConcatIntoIf<!IsAbstract<T>>( //
r, std::vector<Case>{
C(T{123}, T{0}, T::Inf()),
C(T{-123}, -T{0}, T::Inf()),
C(T{-123}, T{0}, -T::Inf()),
C(T{123}, -T{0}, -T::Inf()),
});
auto error_msg = [](auto a, auto b) {
return "12:34 error: " + OverflowErrorMessage(a, "/", b);
};
ConcatIntoIf<IsAbstract<T>>( //
r, std::vector<Case>{
// Divide by zero // Divide by zero
E(T{123}, T{0}, error_msg(T{123}, T{0})), E(T{123}, T{0}, error_msg(T{123}, T{0})),
E(Negate(T{123}), Negate(T{0}), error_msg(Negate(T{123}), Negate(T{0}))), E(Negate(T{123}), Negate(T{0}), error_msg(Negate(T{123}), Negate(T{0}))),
E(Negate(T{123}), T{0}, error_msg(Negate(T{123}), T{0})), E(Negate(T{123}), T{0}, error_msg(Negate(T{123}), T{0})),
E(T{123}, Negate(T{0}), error_msg(T{123}, Negate(T{0}))), E(T{123}, Negate(T{0}), error_msg(T{123}, Negate(T{0}))),
}); };
ConcatIntoIf<std::is_same_v<T, AInt>>( //
r, std::vector<Case>{
// Most negative value divided by -1
E(AInt::Lowest(), -1_a, error_msg(AInt::Lowest(), -1_a)),
});
return r; return r;
} }
INSTANTIATE_TEST_SUITE_P(Div, INSTANTIATE_TEST_SUITE_P(Div,

View File

@ -848,7 +848,7 @@ INSTANTIATE_TEST_SUITE_P( //
testing::ValuesIn(Concat(CountOneBitsCases<i32>(), // testing::ValuesIn(Concat(CountOneBitsCases<i32>(), //
CountOneBitsCases<u32>())))); CountOneBitsCases<u32>()))));
template <typename T, bool finite_only> template <typename T>
std::vector<Case> CrossCases() { std::vector<Case> CrossCases() {
constexpr auto vec_x = [](T v) { return Vec(T(v), T(0), T(0)); }; constexpr auto vec_x = [](T v) { return Vec(T(v), T(0), T(0)); };
constexpr auto vec_y = [](T v) { return Vec(T(0), T(v), T(0)); }; constexpr auto vec_y = [](T v) { return Vec(T(0), T(v), T(0)); };
@ -870,12 +870,6 @@ std::vector<Case> CrossCases() {
const auto lowest_x = vec_x(T::Lowest()); const auto lowest_x = vec_x(T::Lowest());
const auto lowest_y = vec_y(T::Lowest()); const auto lowest_y = vec_y(T::Lowest());
const auto lowest_z = vec_z(T::Lowest()); const auto lowest_z = vec_z(T::Lowest());
const auto inf_x = vec_x(T::Inf());
const auto inf_y = vec_y(T::Inf());
const auto inf_z = vec_z(T::Inf());
const auto neg_inf_x = vec_x(-T::Inf());
const auto neg_inf_y = vec_y(-T::Inf());
const auto neg_inf_z = vec_z(-T::Inf());
std::vector<Case> r = { std::vector<Case> r = {
C({zero, zero}, zero), C({zero, zero}, zero),
@ -924,28 +918,11 @@ std::vector<Case> CrossCases() {
Vec(T(-10.75), T(-6.75), T(11.75))), Vec(T(-10.75), T(-6.75), T(11.75))),
}; };
ConcatIntoIf<!finite_only>( //
r, std::vector<Case>{
C({highest_x, highest_y}, inf_z).PosOrNeg(), //
C({highest_y, highest_x}, inf_z).PosOrNeg(), //
C({highest_z, highest_x}, inf_y).PosOrNeg(), //
C({highest_x, highest_z}, inf_y).PosOrNeg(), //
C({highest_y, highest_z}, inf_x).PosOrNeg(), //
C({highest_z, highest_y}, inf_x).PosOrNeg(), //
C({lowest_x, lowest_y}, inf_z).PosOrNeg(), //
C({lowest_y, lowest_x}, inf_z).PosOrNeg(), //
C({lowest_z, lowest_x}, inf_y).PosOrNeg(), //
C({lowest_x, lowest_z}, inf_y).PosOrNeg(), //
C({lowest_y, lowest_z}, inf_x).PosOrNeg(), //
C({lowest_z, lowest_y}, inf_x).PosOrNeg(),
});
std::string pos_error_msg = std::string pos_error_msg =
"12:34 error: " + OverflowErrorMessage(T::Highest(), "*", T::Highest()); "12:34 error: " + OverflowErrorMessage(T::Highest(), "*", T::Highest());
std::string neg_error_msg = std::string neg_error_msg =
"12:34 error: " + OverflowErrorMessage(T::Lowest(), "*", T::Lowest()); "12:34 error: " + OverflowErrorMessage(T::Lowest(), "*", T::Lowest());
ConcatInto( //
ConcatIntoIf<finite_only>( //
r, std::vector<Case>{ r, std::vector<Case>{
E({highest_x, highest_y}, pos_error_msg), E({highest_x, highest_y}, pos_error_msg),
E({highest_y, highest_x}, pos_error_msg), E({highest_y, highest_x}, pos_error_msg),
@ -967,10 +944,10 @@ INSTANTIATE_TEST_SUITE_P( //
Cross, Cross,
ResolverConstEvalBuiltinTest, ResolverConstEvalBuiltinTest,
testing::Combine(testing::Values(sem::BuiltinType::kCross), testing::Combine(testing::Values(sem::BuiltinType::kCross),
testing::ValuesIn(Concat(CrossCases<AFloat, true>(), // testing::ValuesIn(Concat(CrossCases<AFloat>(), //
CrossCases<f32, false>(), CrossCases<f32>(),
CrossCases<f32, false>(), // CrossCases<f32>(), //
CrossCases<f16, false>())))); CrossCases<f16>()))));
template <typename T> template <typename T>
std::vector<Case> FirstLeadingBitCases() { std::vector<Case> FirstLeadingBitCases() {

View File

@ -352,9 +352,11 @@ TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
Structure("S", utils::Vector{Member("v", target_ty())}); Structure("S", utils::Vector{Member("v", target_ty())});
WrapInFunction(Construct(ty.type_name("S"), abstract_expr)); WrapInFunction(Construct(ty.type_name("S"), abstract_expr));
break; break;
case Method::kBinaryOp: case Method::kBinaryOp: {
WrapInFunction(Add(target_expr(), abstract_expr)); // Add 0 to ensure no overflow with max float values
break; auto binary_target_expr = data.target_expr(*this, 0);
WrapInFunction(Add(binary_target_expr, abstract_expr));
} break;
case Method::kSwitchCond: case Method::kSwitchCond:
WrapInFunction( WrapInFunction(
Switch(abstract_expr, // Switch(abstract_expr, //

View File

@ -146,7 +146,7 @@ OpDecorate %20 Binding 1
%128 = OpLoad %50 %10 %128 = OpLoad %50 %10
%129 = OpLoad %52 %20 %129 = OpLoad %52 %20
%130 = OpSampledImage %124 %129 %128 %130 = OpSampledImage %124 %129 %128
%131 = OpImageSampleProjImplicitLod %v4float %130 %126 %131 = OpImageSampleProjImplicitLod %v4float %130 %47
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -146,7 +146,7 @@ OpDecorate %20 Binding 1
%128 = OpLoad %50 %10 %128 = OpLoad %50 %10
%129 = OpLoad %52 %20 %129 = OpLoad %52 %20
%130 = OpSampledImage %124 %129 %128 %130 = OpSampledImage %124 %129 %128
%131 = OpImageSampleProjExplicitLod %v4float %130 %126 Lod %29 %131 = OpImageSampleProjExplicitLod %v4float %130 %47 Lod %29
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -146,7 +146,7 @@ OpDecorate %20 Binding 1
%128 = OpLoad %50 %10 %128 = OpLoad %50 %10
%129 = OpLoad %52 %20 %129 = OpLoad %52 %20
%130 = OpSampledImage %124 %129 %128 %130 = OpSampledImage %124 %129 %128
%131 = OpImageSampleProjDrefImplicitLod %float %130 %126 %float_0_200000003 %131 = OpImageSampleProjDrefImplicitLod %float %130 %47 %float_0_200000003
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -146,7 +146,7 @@ OpDecorate %20 Binding 1
%128 = OpLoad %50 %10 %128 = OpLoad %50 %10
%129 = OpLoad %52 %20 %129 = OpLoad %52 %20
%130 = OpSampledImage %124 %129 %128 %130 = OpSampledImage %124 %129 %128
%131 = OpImageSampleProjDrefExplicitLod %float %130 %126 %float_0_200000003 Lod %29 %131 = OpImageSampleProjDrefExplicitLod %float %130 %47 %float_0_200000003 Lod %29
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

View File

@ -63,7 +63,7 @@
%main = OpFunction %void None %21 %main = OpFunction %void None %21
%39 = OpLabel %39 = OpLabel
%undefined = OpVariable %_ptr_Function_float Function %undefined = OpVariable %_ptr_Function_float Function
%40 = OpFMod %float %float_5 %float_0 %40 = OpFMod %float %float_5 %float_5
OpStore %undefined %40 OpStore %undefined %40
%41 = OpAccessChain %_ptr_Uniform_int %_ %int_0 %int_0 %41 = OpAccessChain %_ptr_Uniform_int %_ %int_0 %int_0
%10 = OpLoad %int %41 %10 = OpLoad %int %41

View File

@ -30,7 +30,7 @@ fn main_1() {
var undefined : f32; var undefined : f32;
var x_51 : bool; var x_51 : bool;
var x_52_phi : bool; var x_52_phi : bool;
undefined = (5.0 - (0.0 * floor((5.0 / 0.0f)))); undefined = (5.0 - (0.0 * floor((5.0 / 5.0f))));
let x_10 : i32 = x_6.x_GLF_uniform_int_values[0].el; let x_10 : i32 = x_6.x_GLF_uniform_int_values[0].el;
let x_11 : i32 = x_6.x_GLF_uniform_int_values[0].el; let x_11 : i32 = x_6.x_GLF_uniform_int_values[0].el;
let x_12 : i32 = x_6.x_GLF_uniform_int_values[1].el; let x_12 : i32 = x_6.x_GLF_uniform_int_values[1].el;

View File

@ -499,6 +499,14 @@ crbug.com/tint/1755 [ win10 ] webgpu:shader,execution,expression,call,builtin,pa
crbug.com/tint/1755 [ win10 ] webgpu:shader,execution,expression,call,builtin,pack4x8snorm:pack:inputSource="const" [ Failure ] crbug.com/tint/1755 [ win10 ] webgpu:shader,execution,expression,call,builtin,pack4x8snorm:pack:inputSource="const" [ Failure ]
crbug.com/tint/1755 [ win10 ] webgpu:shader,execution,expression,call,builtin,pack4x8unorm:pack:inputSource="const" [ Failure ] crbug.com/tint/1755 [ win10 ] webgpu:shader,execution,expression,call,builtin,pack4x8unorm:pack:inputSource="const" [ Failure ]
################################################################################
# Const-eval functions that fail on inf/nan inputs
# KEEP
################################################################################
crbug.com/tint/1581 webgpu:shader,execution,expression,binary,f32_arithmetic:division:inputSource="const";* [ Failure ]
crbug.com/tint/1581 [ win ] webgpu:shader,execution,expression,call,builtin,cross:f32:inputSource="const" [ Failure ]
crbug.com/tint/1581 [ linux ] webgpu:shader,execution,expression,call,builtin,cross:f32:inputSource="const" [ Failure ]
################################################################################ ################################################################################
# untriaged failures # untriaged failures
# KEEP # KEEP