Remove unreferenced variables in SingleEntryPoint Transform
For overridable constants without explicit ID, replace the
decoration with explicit ID to avoid ID changes impacted by stripped
away variables.
Bug: tint:1155, dawn:1137
Change-Id: I7d76c08952cfa870403ee2653411b2b6ee2af7b6
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/69500
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Shrek Shao <shrekshao@google.com>
diff --git a/src/transform/single_entry_point.cc b/src/transform/single_entry_point.cc
index e03c962..da9c273 100644
--- a/src/transform/single_entry_point.cc
+++ b/src/transform/single_entry_point.cc
@@ -74,7 +74,22 @@
// TODO(jrprice): Strip unused types.
ctx.dst->AST().AddTypeDecl(ctx.Clone(ty));
} else if (auto* var = decl->As<ast::Variable>()) {
- if (var->is_const || referenced_vars.count(var)) {
+ if (referenced_vars.count(var)) {
+ if (var->is_const) {
+ if (auto* deco = ast::GetDecoration<ast::OverrideDecoration>(
+ var->decorations)) {
+ // It is an overridable constant
+ if (!deco->has_value) {
+ // If the decoration doesn't have numeric ID specified explicitly
+ // Make their ids explicitly assigned in the decoration so that
+ // they won't be affected by other stripped away constants
+ auto* global = sem.Get(var)->As<sem::GlobalVariable>();
+ const auto* new_deco =
+ ctx.dst->Override(deco->source, global->ConstantId());
+ ctx.Replace(deco, new_deco);
+ }
+ }
+ }
ctx.dst->AST().AddGlobalVariable(ctx.Clone(var));
}
} else if (auto* func = decl->As<ast::Function>()) {
diff --git a/src/transform/single_entry_point_test.cc b/src/transform/single_entry_point_test.cc
index 677f411..cdab094 100644
--- a/src/transform/single_entry_point_test.cc
+++ b/src/transform/single_entry_point_test.cc
@@ -219,14 +219,8 @@
)";
auto* expect = R"(
-let a : f32 = 1.0;
-
-let b : f32 = 1.0;
-
let c : f32 = 1.0;
-let d : f32 = 1.0;
-
[[stage(compute), workgroup_size(1)]]
fn comp_main1() {
let local_c : f32 = c;
@@ -242,6 +236,120 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(SingleEntryPointTest, OverridableConstants) {
+ auto* src = R"(
+[[override(1001)]] let c1 : u32 = 1u;
+[[override]] let c2 : u32 = 1u;
+[[override(0)]] let c3 : u32 = 1u;
+[[override(9999)]] let c4 : u32 = 1u;
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main1() {
+ let local_d = c1;
+}
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main2() {
+ let local_d = c2;
+}
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main3() {
+ let local_d = c3;
+}
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main4() {
+ let local_d = c4;
+}
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main5() {
+ let local_d = 1u;
+}
+)";
+
+ {
+ SingleEntryPoint::Config cfg("comp_main1");
+ auto* expect = R"(
+[[override(1001)]] let c1 : u32 = 1u;
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main1() {
+ let local_d = c1;
+}
+)";
+ DataMap data;
+ data.Add<SingleEntryPoint::Config>(cfg);
+ auto got = Run<SingleEntryPoint>(src, data);
+ EXPECT_EQ(expect, str(got));
+ }
+
+ {
+ SingleEntryPoint::Config cfg("comp_main2");
+ // The decorator is replaced with the one with explicit id
+ // And should not be affected by other constants stripped away
+ auto* expect = R"(
+[[override(1)]] let c2 : u32 = 1u;
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main2() {
+ let local_d = c2;
+}
+)";
+ DataMap data;
+ data.Add<SingleEntryPoint::Config>(cfg);
+ auto got = Run<SingleEntryPoint>(src, data);
+ EXPECT_EQ(expect, str(got));
+ }
+
+ {
+ SingleEntryPoint::Config cfg("comp_main3");
+ auto* expect = R"(
+[[override(0)]] let c3 : u32 = 1u;
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main3() {
+ let local_d = c3;
+}
+)";
+ DataMap data;
+ data.Add<SingleEntryPoint::Config>(cfg);
+ auto got = Run<SingleEntryPoint>(src, data);
+ EXPECT_EQ(expect, str(got));
+ }
+
+ {
+ SingleEntryPoint::Config cfg("comp_main4");
+ auto* expect = R"(
+[[override(9999)]] let c4 : u32 = 1u;
+
+[[stage(compute), workgroup_size(1)]]
+fn comp_main4() {
+ let local_d = c4;
+}
+)";
+ DataMap data;
+ data.Add<SingleEntryPoint::Config>(cfg);
+ auto got = Run<SingleEntryPoint>(src, data);
+ EXPECT_EQ(expect, str(got));
+ }
+
+ {
+ SingleEntryPoint::Config cfg("comp_main5");
+ auto* expect = R"(
+[[stage(compute), workgroup_size(1)]]
+fn comp_main5() {
+ let local_d = 1u;
+}
+)";
+ DataMap data;
+ data.Add<SingleEntryPoint::Config>(cfg);
+ auto got = Run<SingleEntryPoint>(src, data);
+ EXPECT_EQ(expect, str(got));
+ }
+}
+
TEST_F(SingleEntryPointTest, CalledFunctions) {
auto* src = R"(
fn inner1() {