Implement const eval of abs

This CL adds const-eval for the `abs` builtin.

Bug: tint:1581
Change-Id: I6ee25c07620990f72a6962441aec62ae7665653e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/108340
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
dan sinclair
2022-11-03 14:47:18 +00:00
committed by Dawn LUCI CQ
parent 5ae03c266a
commit b3518d8b4d
191 changed files with 4752 additions and 371 deletions

View File

@@ -404,8 +404,8 @@ match storage
////////////////////////////////////////////////////////////////////////////////
// https://gpuweb.github.io/gpuweb/wgsl/#builtin-functions
fn abs<T: fiu32_f16>(T) -> T
fn abs<N: num, T: fiu32_f16>(vec<N, T>) -> vec<N, T>
@const fn abs<T: fia_fiu32_f16>(T) -> T
@const fn abs<N: num, T: fia_fiu32_f16>(vec<N, T>) -> vec<N, T>
fn acos<T: f32_f16>(T) -> T
fn acos<N: num, T: f32_f16>(vec<N, T>) -> vec<N, T>
fn acosh<T: f32_f16>(T) -> T

View File

@@ -61,12 +61,10 @@ inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
}
TEST_F(ResolverBuiltinTest, ModuleScopeUsage) {
GlobalConst("c", ty.f32(), Call(Source{{12, 34}}, "abs", 1._f));
GlobalConst("c", ty.f32(), Call(Source{{12, 34}}, "dpdy", 1._f));
EXPECT_FALSE(r()->Resolve());
// TODO(crbug.com/tint/1581): Once 'abs' is implemented as @const, this will no longer be an
// error.
EXPECT_EQ(
r()->error(),
R"(12:34 error: const initializer requires a const-expression, but expression is a runtime-expression)");

View File

@@ -1570,6 +1570,31 @@ ConstEval::Result ConstEval::OpShiftLeft(const sem::Type* ty,
return r;
}
ConstEval::Result ConstEval::abs(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source&) {
auto transform = [&](const sem::Constant* c0) {
auto create = [&](auto e) {
using NumberT = decltype(e);
NumberT result;
if constexpr (IsUnsignedIntegral<NumberT>) {
result = e;
} else if constexpr (IsSignedIntegral<NumberT>) {
if (e == NumberT::Lowest()) {
result = e;
} else {
result = NumberT{std::abs(e)};
}
} else {
result = NumberT{std::abs(e)};
}
return CreateElement(builder, c0->Type(), result);
};
return Dispatch_fia_fiu32_f16(create, c0);
};
return TransformElements(builder, ty, transform, args[0]);
}
ConstEval::Result ConstEval::all(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source&) {

View File

@@ -377,6 +377,15 @@ class ConstEval {
// Builtins
////////////////////////////////////////////////////////////////////////////
/// abs 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 abs(const sem::Type* ty,
utils::VectorRef<const sem::Constant*> args,
const Source& source);
/// all builtin
/// @param ty the expression type
/// @param args the input arguments

View File

@@ -146,6 +146,53 @@ INSTANTIATE_TEST_SUITE_P( //
C({1.0_a, 0_a}, kPiOver2<AFloat>),
})));
template <typename T, bool finite_only>
std::vector<Case> AbsCases() {
std::vector<Case> cases = {
C({T(0)}, T(0)),
C({T(2.0)}, T(2.0)),
C({T::Highest()}, T::Highest()),
// Vector tests
C({Vec(T(2.0), T::Highest())}, Vec(T(2.0), T::Highest())),
};
ConcatIntoIf<IsSignedIntegral<T>>(
cases,
std::vector<Case>{
C({Negate(T(0))}, T(0)),
C({Negate(T(2.0))}, T(2.0)),
// If e is signed and is the largest negative, the result is e
C({T::Lowest()}, T::Lowest()),
// 1 more then min i32
C({Negate(T(2147483647))}, T(2147483647)),
C({Vec(T(0), Negate(T(0)))}, Vec(T(0), T(0))),
C({Vec(Negate(T(2.0)), T(2.0), T::Highest())}, Vec(T(2.0), T(2.0), T::Highest())),
});
ConcatIntoIf<!finite_only>(cases, std::vector<Case>{
C({Negate(T::Inf())}, T::Inf()),
C({T::Inf()}, T::Inf()),
C({T::NaN()}, T::NaN()),
C({Vec(Negate(T::Inf()), T::Inf(), T::NaN())},
Vec(T::Inf(), T::Inf(), T::NaN())),
});
return cases;
}
INSTANTIATE_TEST_SUITE_P( //
Abs,
ResolverConstEvalBuiltinTest,
testing::Combine(testing::Values(sem::BuiltinType::kAbs),
testing::ValuesIn(Concat(AbsCases<AInt, false>(), //
AbsCases<i32, false>(),
AbsCases<u32, false>(),
AbsCases<AFloat, true>(),
AbsCases<f32, false>(),
AbsCases<f16, false>()))));
static std::vector<Case> AllCases() {
return {
C({Val(true)}, Val(true)),

View File

@@ -12945,24 +12945,24 @@ constexpr OverloadInfo kOverloads[] = {
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 0,
/* template types */ &kTemplateTypes[25],
/* template types */ &kTemplateTypes[28],
/* template numbers */ &kTemplateNumbers[10],
/* parameters */ &kParameters[1018],
/* return matcher indices */ &kMatcherIndices[1],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
/* const eval */ &ConstEval::abs,
},
{
/* [385] */
/* num parameters */ 1,
/* num template types */ 1,
/* num template numbers */ 1,
/* template types */ &kTemplateTypes[25],
/* template types */ &kTemplateTypes[28],
/* template numbers */ &kTemplateNumbers[6],
/* parameters */ &kParameters[853],
/* return matcher indices */ &kMatcherIndices[30],
/* flags */ OverloadFlags(OverloadFlag::kIsBuiltin, OverloadFlag::kSupportsVertexPipeline, OverloadFlag::kSupportsFragmentPipeline, OverloadFlag::kSupportsComputePipeline),
/* const eval */ nullptr,
/* const eval */ &ConstEval::abs,
},
{
/* [386] */
@@ -14013,8 +14013,8 @@ constexpr OverloadInfo kOverloads[] = {
constexpr IntrinsicInfo kBuiltins[] = {
{
/* [0] */
/* fn abs<T : fiu32_f16>(T) -> T */
/* fn abs<N : num, T : fiu32_f16>(vec<N, T>) -> vec<N, T> */
/* fn abs<T : fia_fiu32_f16>(T) -> T */
/* fn abs<N : num, T : fia_fiu32_f16>(vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[384],
},