[tint][ir][ToProgram] Assign builtin calls to phonies

If builtin returns a value, but it's not used.

Change-Id: I3450fd2cdfd5a98c19acb7d40b0c22f0acfff654
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/140984
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/ir/to_program.cc b/src/tint/ir/to_program.cc
index 8c679b2..d35863b 100644
--- a/src/tint/ir/to_program.cc
+++ b/src/tint/ir/to_program.cc
@@ -561,10 +561,16 @@
             },
             [&](ir::BuiltinCall* c) {
                 auto* expr = b.Call(c->Func(), std::move(args));
-                if (!call->HasResults() || call->Result()->Usages().IsEmpty()) {
+                if (!call->HasResults() || call->Result()->Type()->Is<type::Void>()) {
                     Append(b.CallStmt(expr));
                     return;
                 }
+                if (call->Result()->Usages().IsEmpty()) {
+                    // TODO(crbug.com/1718): Assignment to phony is only required if the builtin is
+                    // annotated with @must_use. We don't yet have this information.
+                    Append(b.Assign(b.Phony(), expr));
+                    return;
+                }
                 Bind(c->Result(), expr, PtrKind::kPtr);
             },
             [&](ir::Construct* c) {
diff --git a/src/tint/ir/to_program_roundtrip_test.cc b/src/tint/ir/to_program_roundtrip_test.cc
index 8750416..e737032 100644
--- a/src/tint/ir/to_program_roundtrip_test.cc
+++ b/src/tint/ir/to_program_roundtrip_test.cc
@@ -186,6 +186,14 @@
 )");
 }
 
+TEST_F(IRToProgramRoundtripTest, BuiltinCall_PhonyAssignment) {
+    Test(R"(
+fn f(a : i32, b : i32) {
+  _ = max(a, b);
+}
+)");
+}
+
 TEST_F(IRToProgramRoundtripTest, BuiltinCall_PtrArg) {
     Test(R"(
 var<workgroup> v : bool;