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>
diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc
index 13cb213..b52f4aa 100644
--- a/src/tint/resolver/const_eval.cc
+++ b/src/tint/resolver/const_eval.cc
@@ -1330,13 +1330,10 @@
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(
diff --git a/src/tint/resolver/const_eval.h b/src/tint/resolver/const_eval.h
index d75f5de..dbb1c2e 100644
--- a/src/tint/resolver/const_eval.h
+++ b/src/tint/resolver/const_eval.h
@@ -80,10 +80,11 @@
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
diff --git a/src/tint/resolver/const_eval_binary_op_test.cc b/src/tint/resolver/const_eval_binary_op_test.cc
index e7e306a..7ea998a 100644
--- a/src/tint/resolver/const_eval_binary_op_test.cc
+++ b/src/tint/resolver/const_eval_binary_op_test.cc
@@ -1775,8 +1775,7 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
+)");
}
////////////////////////////////////////////////
diff --git a/src/tint/resolver/const_eval_bitcast_test.cc b/src/tint/resolver/const_eval_bitcast_test.cc
index 34fc25e..50d4693 100644
--- a/src/tint/resolver/const_eval_bitcast_test.cc
+++ b/src/tint/resolver/const_eval_bitcast_test.cc
@@ -67,7 +67,7 @@
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 @@
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"));
}
}
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 4291009..cec6e5a 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1960,24 +1960,24 @@
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;
}