[ir] Use the const eval results for expressions.
If an expression has a `sem::ValueExpression` attached we can use it to
directly obtain the result of the expression and stop emission. This Cl
updates the IR builder to pull the expression result if possible.
Several of the tests have been updated to go through a function in order
to stop const-eval from removing all the test content.
Bug: tint:1924
Change-Id: I6458cc297efc7789ac200069c18f75e8eb70c63b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/129680
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc
index d647105..90f7fb3 100644
--- a/src/tint/ir/builder_impl.cc
+++ b/src/tint/ir/builder_impl.cc
@@ -655,6 +655,15 @@
}
utils::Result<Value*> BuilderImpl::EmitExpression(const ast::Expression* expr) {
+ // If this is a value that has been const-eval'd return the result.
+ if (auto* sem = program_->Sem().Get(expr)->As<sem::ValueExpression>()) {
+ if (auto* v = sem->ConstantValue()) {
+ if (auto* cv = v->Clone(clone_ctx_)) {
+ return builder.Constant(cv);
+ }
+ }
+ }
+
return tint::Switch(
expr,
// [&](const ast::IndexAccessorExpression* a) {
@@ -701,8 +710,8 @@
// should never be used.
//
// TODO(dsinclair): Probably want to store the const variable somewhere and then in
- // identifier expression log an error if we ever see a const identifier. Add this when
- // identifiers and variables are supported.
+ // identifier expression log an error if we ever see a const identifier. Add this
+ // when identifiers and variables are supported.
},
[&](Default) {
add_error(var->source, "unknown variable: " + std::string(var->TypeInfo().name));
diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc
index 6d694eb..6efd69c 100644
--- a/src/tint/ir/builder_impl_test.cc
+++ b/src/tint/ir/builder_impl_test.cc
@@ -1553,7 +1553,8 @@
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) {
- auto* expr = Add(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Add(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1564,12 +1565,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 + 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) + 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) {
- auto* expr = Sub(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Sub(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1580,12 +1583,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 - 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) - 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) {
- auto* expr = Mul(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Mul(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1596,12 +1601,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 * 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) * 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) {
- auto* expr = Div(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Div(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1612,12 +1619,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 / 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) / 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) {
- auto* expr = Mod(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Mod(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1628,12 +1637,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 % 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) % 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) {
- auto* expr = And(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = And(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1644,12 +1655,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 & 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) & 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) {
- auto* expr = Or(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Or(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1660,12 +1673,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 | 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) | 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) {
- auto* expr = Xor(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Xor(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1676,12 +1691,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 ^ 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) ^ 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) {
- auto* expr = LogicalAnd(true, false);
+ Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
+ auto* expr = LogicalAnd(Call("my_func"), false);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1692,12 +1709,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = true && false
+ EXPECT_EQ(d.AsString(), R"(%1(bool) = call(my_func, )
+%2(bool) = %1(bool) && false
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) {
- auto* expr = LogicalOr(false, true);
+ Func("my_func", utils::Empty, ty.bool_(), utils::Vector{Return(true)});
+ auto* expr = LogicalOr(Call("my_func"), true);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1708,12 +1727,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = false || true
+ EXPECT_EQ(d.AsString(), R"(%1(bool) = call(my_func, )
+%2(bool) = %1(bool) || true
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) {
- auto* expr = Equal(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Equal(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1724,12 +1745,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = 3 == 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(bool) = %1(u32) == 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) {
- auto* expr = NotEqual(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = NotEqual(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1740,12 +1763,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = 3 != 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(bool) = %1(u32) != 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) {
- auto* expr = LessThan(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = LessThan(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1756,12 +1781,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = 3 < 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(bool) = %1(u32) < 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) {
- auto* expr = GreaterThan(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = GreaterThan(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1772,12 +1799,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = 3 > 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(bool) = %1(u32) > 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) {
- auto* expr = LessThanEqual(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = LessThanEqual(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1788,12 +1817,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = 3 <= 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(bool) = %1(u32) <= 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) {
- auto* expr = GreaterThanEqual(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = GreaterThanEqual(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1804,12 +1835,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(bool) = 3 >= 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(bool) = %1(u32) >= 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) {
- auto* expr = Shl(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Shl(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1820,12 +1853,14 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 << 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) << 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) {
- auto* expr = Shr(3_u, 4_u);
+ Func("my_func", utils::Empty, ty.u32(), utils::Vector{Return(0_u)});
+ auto* expr = Shr(Call("my_func"), 4_u);
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1836,13 +1871,16 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 >> 4
+ EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, )
+%2(u32) = %1(u32) >> 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
- auto* expr = LogicalAnd(LessThan(1_u, Add(Shr(3_u, 4_u), 9_u)),
- GreaterThan(2.5_f, Div(6.7_f, Mul(2.3_f, 5.5_f))));
+ Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
+
+ auto* expr = LogicalAnd(LessThan(Call("my_func"), 2_f),
+ GreaterThan(2.5_f, Div(Call("my_func"), Mul(2.3_f, Call("my_func")))));
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1853,18 +1891,39 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(u32) = 3 >> 4
-%2(u32) = %1(u32) + 9
-%3(bool) = 1 < %2(u32)
-%4(f32) = 2.29999995231628417969 * 5.5
-%5(f32) = 6.69999980926513671875 / %4(f32)
-%6(bool) = 2.5 > %5(f32)
-%7(bool) = %3(bool) && %6(bool)
+ EXPECT_EQ(d.AsString(), R"(%1(f32) = call(my_func, )
+%2(bool) = %1(f32) < 2.0
+%3(f32) = call(my_func, )
+%4(f32) = call(my_func, )
+%5(f32) = 2.29999995231628417969 * %4(f32)
+%6(f32) = %3(f32) / %5(f32)
+%7(bool) = 2.5 > %6(f32)
+%8(bool) = %2(bool) && %7(bool)
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound_WithConstEval) {
+ Func("my_func", utils::Vector{Param("p", ty.bool_())}, ty.bool_(), utils::Vector{Return(true)});
+ auto* expr = Call("my_func", LogicalAnd(LessThan(2.4_f, 2_f),
+ GreaterThan(2.5_f, Div(10_f, Mul(2.3_f, 9.4_f)))));
+ WrapInFunction(expr);
+
+ auto& b = CreateBuilder();
+ InjectFlowBlock();
+ auto r = b.EmitExpression(expr);
+ ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
+ ASSERT_TRUE(r);
+
+ Disassembler d(b.builder.ir);
+ d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
+ EXPECT_EQ(d.AsString(), R"(%1(bool) = call(my_func, false)
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) {
- auto* expr = Bitcast<f32>(3_u);
+ Func("my_func", utils::Empty, ty.f32(), utils::Vector{Return(0_f)});
+
+ auto* expr = Bitcast<f32>(Call("my_func"));
WrapInFunction(expr);
auto& b = CreateBuilder();
@@ -1875,7 +1934,8 @@
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(f32) = bitcast(3)
+ EXPECT_EQ(d.AsString(), R"(%1(f32) = call(my_func, )
+%2(f32) = bitcast(%1(f32))
)");
}
@@ -1904,14 +1964,14 @@
WrapInFunction(stmt);
auto& b = CreateBuilder();
+
InjectFlowBlock();
b.EmitStatement(stmt);
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
- EXPECT_EQ(d.AsString(), R"(%1(f32) = 2.0 * 3.0
-%2(void) = call(my_func, %1(f32))
+ EXPECT_EQ(d.AsString(), R"(%1(void) = call(my_func, 6.0)
)");
}