mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
Add const-eval for min and max
This CL adds const-eval for `min` and `max`. Bug: tint:1581 Change-Id: Ica68ba312f21767c46d57d83570ddc72ee857231 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/110166 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
6924d6e903
commit
acce83d109
@@ -2119,6 +2119,30 @@ ConstEval::Result ConstEval::insertBits(const sem::Type* ty,
|
||||
return TransformElements(builder, ty, transform, args[0], args[1]);
|
||||
}
|
||||
|
||||
ConstEval::Result ConstEval::max(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source&) {
|
||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
|
||||
auto create = [&](auto e0, auto e1) {
|
||||
return CreateElement(builder, c0->Type(), decltype(e0)(std::max(e0, e1)));
|
||||
};
|
||||
return Dispatch_fia_fiu32_f16(create, c0, c1);
|
||||
};
|
||||
return TransformElements(builder, ty, transform, args[0], args[1]);
|
||||
}
|
||||
|
||||
ConstEval::Result ConstEval::min(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source&) {
|
||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
|
||||
auto create = [&](auto e0, auto e1) {
|
||||
return CreateElement(builder, c0->Type(), decltype(e0)(std::min(e0, e1)));
|
||||
};
|
||||
return Dispatch_fia_fiu32_f16(create, c0, c1);
|
||||
};
|
||||
return TransformElements(builder, ty, transform, args[0], args[1]);
|
||||
}
|
||||
|
||||
ConstEval::Result ConstEval::pack2x16float(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source) {
|
||||
|
||||
@@ -584,6 +584,24 @@ class ConstEval {
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source);
|
||||
|
||||
/// max builtin
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @param source the source location of the conversion
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
Result max(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source);
|
||||
|
||||
/// min builtin
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @param source the source location of the conversion
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
Result min(const sem::Type* ty, // NOLINT(build/include_what_you_use) -- confused by min
|
||||
utils::VectorRef<const sem::Constant*> args,
|
||||
const Source& source);
|
||||
|
||||
/// pack2x16float builtin
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
|
||||
@@ -1291,6 +1291,60 @@ INSTANTIATE_TEST_SUITE_P(ExtractBits,
|
||||
std::make_tuple(1, u32::Highest()), //
|
||||
std::make_tuple(u32::Highest(), u32::Highest())));
|
||||
|
||||
template <typename T>
|
||||
std::vector<Case> MaxCases() {
|
||||
return {
|
||||
C({T(0), T(0)}, T(0)),
|
||||
C({T(0), T::Highest()}, T::Highest()),
|
||||
C({T::Lowest(), T(0)}, T(0)),
|
||||
C({T::Highest(), T::Lowest()}, T::Highest()),
|
||||
C({T::Highest(), T::Highest()}, T::Highest()),
|
||||
C({T::Lowest(), T::Lowest()}, T::Lowest()),
|
||||
|
||||
// Vector tests
|
||||
C({Vec(T(0), T(0)), Vec(T(0), T(42))}, Vec(T(0), T(42))),
|
||||
C({Vec(T::Lowest(), T(0)), Vec(T(0), T::Lowest())}, Vec(T(0), T(0))),
|
||||
C({Vec(T::Lowest(), T::Highest()), Vec(T::Highest(), T::Lowest())},
|
||||
Vec(T::Highest(), T::Highest())),
|
||||
};
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P( //
|
||||
Max,
|
||||
ResolverConstEvalBuiltinTest,
|
||||
testing::Combine(testing::Values(sem::BuiltinType::kMax),
|
||||
testing::ValuesIn(Concat(MaxCases<AInt>(), //
|
||||
MaxCases<i32>(),
|
||||
MaxCases<u32>(),
|
||||
MaxCases<AFloat>(),
|
||||
MaxCases<f32>(),
|
||||
MaxCases<f16>()))));
|
||||
|
||||
template <typename T>
|
||||
std::vector<Case> MinCases() {
|
||||
return {C({T(0), T(0)}, T(0)), //
|
||||
C({T(0), T(42)}, T(0)), //
|
||||
C({T::Lowest(), T(0)}, T::Lowest()), //
|
||||
C({T(0), T::Highest()}, T(0)), //
|
||||
C({T::Highest(), T::Lowest()}, T::Lowest()),
|
||||
C({T::Highest(), T::Highest()}, T::Highest()),
|
||||
C({T::Lowest(), T::Lowest()}, T::Lowest()),
|
||||
|
||||
// Vector tests
|
||||
C({Vec(T(0), T(0)), Vec(T(0), T(42))}, Vec(T(0), T(0))),
|
||||
C({Vec(T::Lowest(), T(0), T(1)), Vec(T(0), T(42), T::Highest())},
|
||||
Vec(T::Lowest(), T(0), T(1)))};
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P( //
|
||||
Min,
|
||||
ResolverConstEvalBuiltinTest,
|
||||
testing::Combine(testing::Values(sem::BuiltinType::kMin),
|
||||
testing::ValuesIn(Concat(MinCases<AInt>(), //
|
||||
MinCases<i32>(),
|
||||
MinCases<u32>(),
|
||||
MinCases<AFloat>(),
|
||||
MinCases<f32>(),
|
||||
MinCases<f16>()))));
|
||||
|
||||
std::vector<Case> Pack4x8snormCases() {
|
||||
return {
|
||||
C({Vec(f32(0), f32(0), f32(0), f32(0))}, Val(u32(0x0000'0000))),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -472,8 +472,13 @@ constexpr Method kSwitchMethods[] = {
|
||||
constexpr Method kNoMaterializeMethods[] = {
|
||||
Method::kPhonyAssign, //
|
||||
Method::kBinaryOp,
|
||||
// TODO(crbug.com/tint/1504): Enable once "min" supports const evaluation
|
||||
// Method::kBuiltinArg,
|
||||
};
|
||||
|
||||
/// Methods that do not materialize
|
||||
constexpr Method kNoMaterializeScalarVectorMethods[] = {
|
||||
Method::kPhonyAssign, //
|
||||
Method::kBinaryOp,
|
||||
Method::kBuiltinArg,
|
||||
};
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
MaterializeScalar,
|
||||
@@ -697,6 +702,17 @@ INSTANTIATE_TEST_SUITE_P(NoMaterialize,
|
||||
Types<AFloatM, AFloatM>(1.0_a, 1.0_a), //
|
||||
})));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(NoMaterializeScalarVector,
|
||||
MaterializeAbstractNumericToConcreteType,
|
||||
testing::Combine(testing::Values(Expectation::kNoMaterialize),
|
||||
testing::ValuesIn(kNoMaterializeScalarVectorMethods),
|
||||
testing::ValuesIn(std::vector<Data>{
|
||||
Types<AInt, AInt>(1_a, 1_a), //
|
||||
Types<AIntV, AIntV>(1_a, 1_a), //
|
||||
Types<AFloat, AFloat>(1.0_a, 1.0_a), //
|
||||
Types<AFloatV, AFloatV>(1.0_a, 1.0_a), //
|
||||
})));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(InvalidConversion,
|
||||
MaterializeAbstractNumericToConcreteType,
|
||||
testing::Combine(testing::Values(Expectation::kInvalidConversion),
|
||||
@@ -771,9 +787,6 @@ enum class Method {
|
||||
// let a = abstract_expr;
|
||||
kLet,
|
||||
|
||||
// min(abstract_expr, abstract_expr)
|
||||
kBuiltinArg,
|
||||
|
||||
// bitcast<f32>(abstract_expr)
|
||||
kBitcastF32Arg,
|
||||
|
||||
@@ -810,8 +823,6 @@ static std::ostream& operator<<(std::ostream& o, Method m) {
|
||||
return o << "var";
|
||||
case Method::kLet:
|
||||
return o << "let";
|
||||
case Method::kBuiltinArg:
|
||||
return o << "builtin-arg";
|
||||
case Method::kBitcastF32Arg:
|
||||
return o << "bitcast-f32-arg";
|
||||
case Method::kBitcastVec3F32Arg:
|
||||
@@ -890,10 +901,6 @@ TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
|
||||
WrapInFunction(Decl(Let("a", abstract_expr())));
|
||||
break;
|
||||
}
|
||||
case Method::kBuiltinArg: {
|
||||
WrapInFunction(CallStmt(Call("min", abstract_expr(), abstract_expr())));
|
||||
break;
|
||||
}
|
||||
case Method::kBitcastF32Arg: {
|
||||
WrapInFunction(Bitcast<f32>(abstract_expr()));
|
||||
break;
|
||||
@@ -949,17 +956,8 @@ TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
|
||||
}
|
||||
case Expectation::kInvalidConversion: {
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
std::string expect;
|
||||
switch (method) {
|
||||
case Method::kBuiltinArg:
|
||||
expect = "error: no matching call to min(" + data.abstract_type_name + ", " +
|
||||
data.abstract_type_name + ")";
|
||||
break;
|
||||
default:
|
||||
expect = "error: cannot convert value of type '" + data.abstract_type_name +
|
||||
"' to type '" + data.expected_type_name + "'";
|
||||
break;
|
||||
}
|
||||
std::string expect = "error: cannot convert value of type '" + data.abstract_type_name +
|
||||
"' to type '" + data.expected_type_name + "'";
|
||||
EXPECT_THAT(r()->error(), testing::StartsWith(expect));
|
||||
break;
|
||||
}
|
||||
@@ -977,16 +975,17 @@ TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
|
||||
constexpr Method kScalarMethods[] = {
|
||||
Method::kLet,
|
||||
Method::kVar,
|
||||
Method::kBuiltinArg,
|
||||
Method::kBitcastF32Arg,
|
||||
Method::kTintMaterializeBuiltin,
|
||||
};
|
||||
|
||||
/// Methods that support vector materialization
|
||||
constexpr Method kVectorMethods[] = {
|
||||
Method::kLet, Method::kVar,
|
||||
Method::kBuiltinArg, Method::kBitcastVec3F32Arg,
|
||||
Method::kRuntimeIndex, Method::kTintMaterializeBuiltin,
|
||||
Method::kLet,
|
||||
Method::kVar,
|
||||
Method::kBitcastVec3F32Arg,
|
||||
Method::kRuntimeIndex,
|
||||
Method::kTintMaterializeBuiltin,
|
||||
};
|
||||
|
||||
/// Methods that support matrix materialization
|
||||
|
||||
Reference in New Issue
Block a user