From 03ee23ea9efa2c4d053cb2c23152fc23553a3eaf Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Wed, 8 Mar 2023 23:22:27 +0000 Subject: [PATCH] [ir] Convert materialized nodes to constants This CL updates the IR builder to convert materialized call expressions directly into the resulting constant values. Bug: tint:1718 Change-Id: I184478996afdd11b00ca946775eab6801b777f3c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/122605 Commit-Queue: Dan Sinclair Kokoro: Kokoro Reviewed-by: Ben Clayton --- src/tint/ir/builder_impl.cc | 26 ++++++++++++++++++++------ src/tint/ir/builder_impl_test.cc | 24 ++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc index 9ecf1fb208..07a1fdbb4a 100644 --- a/src/tint/ir/builder_impl.cc +++ b/src/tint/ir/builder_impl.cc @@ -56,6 +56,7 @@ #include "src/tint/program.h" #include "src/tint/sem/builtin.h" #include "src/tint/sem/call.h" +#include "src/tint/sem/materialize.h" #include "src/tint/sem/module.h" #include "src/tint/sem/switch_statement.h" #include "src/tint/sem/value_constructor.h" @@ -751,6 +752,19 @@ utils::Result BuilderImpl::EmitCall(const ast::CallStatement* stmt) { } utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { + // If this is a materialized semantic node, just use the constant value. + if (auto* mat = program_->Sem().Get(expr)) { + if (mat->ConstantValue()) { + auto* cv = mat->ConstantValue()->Clone(clone_ctx_); + if (!cv) { + add_error(expr->source, "failed to get constant value for call " + + std::string(expr->TypeInfo().name)); + return utils::Failure; + } + return builder.Constant(cv); + } + } + utils::Vector args; args.Reserve(expr->args.Length()); @@ -758,7 +772,7 @@ utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { for (const auto* arg : expr->args) { auto value = EmitExpression(arg); if (!value) { - add_error(arg->source, "Failed to convert arguments"); + add_error(arg->source, "failed to convert arguments"); return utils::Failure; } args.Push(value.Get()); @@ -766,7 +780,7 @@ utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { auto* sem = program_->Sem().Get(expr); if (!sem) { - add_error(expr->source, "Failed to get semantic information for call " + + add_error(expr->source, "failed to get semantic information for call " + std::string(expr->TypeInfo().name)); return utils::Failure; } @@ -778,14 +792,14 @@ utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { // If this is a builtin function, emit the specific builtin value if (sem->Target()->As()) { // TODO(dsinclair): .. something ... - add_error(expr->source, "Missing builtin function support"); + add_error(expr->source, "missing builtin function support"); } else if (sem->Target()->As()) { instr = builder.Construct(ty, std::move(args)); } else if (auto* conv = sem->Target()->As()) { auto* from = conv->Source()->Clone(clone_ctx_.type_ctx); instr = builder.Convert(ty, from, std::move(args)); } else if (expr->target->identifier->Is()) { - TINT_UNIMPLEMENTED(IR, diagnostics_) << "Missing templated ident support"; + TINT_UNIMPLEMENTED(IR, diagnostics_) << "missing templated ident support"; return utils::Failure; } else { // Not a builtin and not a templated call, so this is a user function. @@ -802,7 +816,7 @@ utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { utils::Result BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) { auto* sem = program_->Sem().Get(lit); if (!sem) { - add_error(lit->source, "Failed to get semantic information for node " + + add_error(lit->source, "failed to get semantic information for node " + std::string(lit->TypeInfo().name)); return utils::Failure; } @@ -810,7 +824,7 @@ utils::Result BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit auto* cv = sem->ConstantValue()->Clone(clone_ctx_); if (!cv) { add_error(lit->source, - "Failed to get constant value for node " + std::string(lit->TypeInfo().name)); + "failed to get constant value for node " + std::string(lit->TypeInfo().name)); return utils::Failure; } return builder.Constant(cv); diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index be94e653e0..1705084a05 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -1876,9 +1876,12 @@ TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) { )"); } -TEST_F(IR_BuilderImplTest, EmitExpression_ConstructEmpty) { +// TODO(dsinclair): This needs assignment in order to output correctly. The empty constructor ends +// up materializing, so there is no expression to emit until there is a usage. When assigment is +// implemented this can be enabled (and the output updated). +TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_ConstructEmpty) { auto* expr = vec3(ty.f32()); - WrapInFunction(expr); + GlobalVar("i", builtin::AddressSpace::kPrivate, expr); auto& b = CreateBuilder(); InjectFlowBlock(); @@ -1923,5 +1926,22 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Convert) { )"); } +TEST_F(IR_BuilderImplTest, EmitExpression_MaterializedCall) { + auto* expr = Return(Call("trunc", 2.5_f)); + + Func("test_function", {}, ty.f32(), expr, utils::Empty); + + auto r = Build(); + ASSERT_TRUE(r) << Error(); + auto m = r.Move(); + + EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function + %bb1 = Block + Return (2.0) +FunctionEnd + +)"); +} + } // namespace } // namespace tint::ir