tint: implement short-circuiting of const eval bitcast

Bug: tint:1581
Change-Id: I6058dee593bf97f9dee202a80ced7b2551da0ba9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/115220
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Antonio Maiorano 2022-12-21 21:15:03 +00:00
parent bf9c34642a
commit bc44620d68
5 changed files with 42 additions and 39 deletions

View File

@ -1330,13 +1330,10 @@ ConstEval::Result ConstEval::Swizzle(const type::Type* ty,
return builder.create<constant::Composite>(ty, std::move(values));
}
ConstEval::Result ConstEval::Bitcast(const type::Type* ty, const sem::Expression* expr) {
auto* value = expr->ConstantValue();
if (!value) {
return nullptr;
}
ConstEval::Result ConstEval::Bitcast(const type::Type* ty,
const constant::Value* value,
const Source& source) {
auto* el_ty = type::Type::DeepestElementOf(ty);
auto& source = expr->Declaration()->source;
auto transform = [&](const constant::Value* c0) {
auto create = [&](auto e) {
return Switch(

View File

@ -80,10 +80,11 @@ class ConstEval {
Result ArrayOrStructInit(const type::Type* ty, utils::VectorRef<const sem::Expression*> args);
/// @param ty the target type
/// @param expr the input expression
/// @param value the value being converted
/// @param source the source location
/// @return the bit-cast of the given expression to the given type, or null if the value cannot
/// be calculated
Result Bitcast(const type::Type* ty, const sem::Expression* expr);
Result Bitcast(const type::Type* ty, const constant::Value* value, const Source& source);
/// @param obj the object being indexed
/// @param idx the index expression

View File

@ -1775,8 +1775,7 @@ TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Index) {
// Short-Circuit Bitcast
////////////////////////////////////////////////
// @TODO(crbug.com/tint/1581): Enable once const eval of bitcast is implemented
TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_And_Invalid_Bitcast) {
TEST_F(ResolverConstEvalTest, ShortCircuit_And_Invalid_Bitcast) {
// const one = 1;
// const a = 0x7F800000;
// const result = (one == 0) && (bitcast<f32>(a) == 0.0);
@ -1791,8 +1790,7 @@ TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_And_Invalid_Bitcast) {
ValidateAnd(Sem(), binary);
}
// @TODO(crbug.com/tint/1581): Enable once const eval of bitcast is implemented
TEST_F(ResolverConstEvalTest, DISABLED_NonShortCircuit_And_Invalid_Bitcast) {
TEST_F(ResolverConstEvalTest, NonShortCircuit_And_Invalid_Bitcast) {
// const one = 1;
// const a = 0x7F800000;
// const result = (one == 1) && (bitcast<f32>(a) == 0.0);
@ -1804,11 +1802,10 @@ TEST_F(ResolverConstEvalTest, DISABLED_NonShortCircuit_And_Invalid_Bitcast) {
GlobalConst("result", binary);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: value not representable as f32 message here");
EXPECT_EQ(r()->error(), "12:34 error: value inf cannot be represented as 'f32'");
}
// @TODO(crbug.com/tint/1581): Enable once const eval of bitcast is implemented
TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_And_Error_Bitcast) {
TEST_F(ResolverConstEvalTest, ShortCircuit_And_Error_Bitcast) {
// const one = 1;
// const a = 0x7F800000;
// const result = (one == 0) && (bitcast<f32>(a) == 0i);
@ -1820,11 +1817,15 @@ TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_And_Error_Bitcast) {
GlobalConst("result", binary);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload message here)");
EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for operator == (f32, i32)
2 candidate operators:
operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
)");
}
// @TODO(crbug.com/tint/1581): Enable once const eval of bitcast is implemented
TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_Or_Invalid_Bitcast) {
TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Invalid_Bitcast) {
// const one = 1;
// const a = 0x7F800000;
// const result = (one == 1) || (bitcast<f32>(a) == 0.0);
@ -1839,8 +1840,7 @@ TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_Or_Invalid_Bitcast) {
ValidateOr(Sem(), binary);
}
// @TODO(crbug.com/tint/1581): Enable once const eval of bitcast is implemented
TEST_F(ResolverConstEvalTest, DISABLED_NonShortCircuit_Or_Invalid_Bitcast) {
TEST_F(ResolverConstEvalTest, NonShortCircuit_Or_Invalid_Bitcast) {
// const one = 1;
// const a = 0x7F800000;
// const result = (one == 0) || (bitcast<f32>(a) == 0.0);
@ -1852,11 +1852,10 @@ TEST_F(ResolverConstEvalTest, DISABLED_NonShortCircuit_Or_Invalid_Bitcast) {
GlobalConst("result", binary);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: value not representable as f32 message here");
EXPECT_EQ(r()->error(), "12:34 error: value inf cannot be represented as 'f32'");
}
// @TODO(crbug.com/tint/1581): Enable once const eval of bitcast is implemented
TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_Or_Error_Bitcast) {
TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Bitcast) {
// const one = 1;
// const a = 0x7F800000;
// const result = (one == 1) || (bitcast<f32>(a) == 0i);
@ -1868,7 +1867,12 @@ TEST_F(ResolverConstEvalTest, DISABLED_ShortCircuit_Or_Error_Bitcast) {
GlobalConst("result", binary);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload message here)");
EXPECT_EQ(r()->error(), R"(12:34 error: no matching overload for operator == (f32, i32)
2 candidate operators:
operator == (T, T) -> bool where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
operator == (vecN<T>, vecN<T>) -> vecN<bool> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
)");
}
////////////////////////////////////////////////

View File

@ -67,7 +67,7 @@ TEST_P(ResolverConstEvalBitcastTest, Test) {
auto* target_ty = target_create_ptrs.ast(*this);
ASSERT_NE(target_ty, nullptr);
auto* input_val = input.Expr(*this);
const ast::Expression* expr = Bitcast(target_ty, input_val);
const ast::Expression* expr = Bitcast(Source{{12, 34}}, target_ty, input_val);
WrapInFunction(expr);
@ -87,6 +87,7 @@ TEST_P(ResolverConstEvalBitcastTest, Test) {
EXPECT_EQ(expected_values, got_values);
} else {
ASSERT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), testing::StartsWith("12:34 error:"));
EXPECT_THAT(r()->error(), testing::HasSubstr("cannot be represented as"));
}
}

View File

@ -1960,24 +1960,24 @@ sem::Expression* Resolver::Bitcast(const ast::BitcastExpression* expr) {
if (!validator_.Bitcast(expr, ty)) {
return nullptr;
}
//
const constant::Value* val = nullptr;
sem::EvaluationStage stage = sem::EvaluationStage::kRuntime;
// TODO(crbug.com/tint/1582): short circuit 'expr' once const eval of Bitcast is implemented.
if (auto r = const_eval_.Bitcast(ty, inner)) {
val = r.Get();
if (val) {
stage = sem::EvaluationStage::kConstant;
}
} else {
return nullptr;
auto stage = inner->Stage();
if (stage == sem::EvaluationStage::kConstant && skip_const_eval_.Contains(expr)) {
stage = sem::EvaluationStage::kNotEvaluated;
}
const constant::Value* value = nullptr;
if (stage == sem::EvaluationStage::kConstant) {
if (auto r = const_eval_.Bitcast(ty, inner->ConstantValue(), expr->source)) {
value = r.Get();
} else {
return nullptr;
}
}
auto* sem = builder_->create<sem::Expression>(expr, ty, stage, current_statement_,
std::move(val), inner->HasSideEffects());
std::move(value), inner->HasSideEffects());
sem->Behaviors() = inner->Behaviors();
return sem;
}