spirv-reader: fix position calculation of for phi var decl
Fixed: tint:495
Change-Id: I93f1b289eb33c2bda8b661f591a1c8dde775b1ab
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/46220
Commit-Queue: David Neto <dneto@google.com>
Commit-Queue: Alan Baker <alanbaker@google.com>
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: Alan Baker <alanbaker@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 5139f9f..16012fe 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -3961,7 +3961,7 @@
// of the predecessor block.
pred_block_info->phi_assignments.push_back({phi_id, value_id});
first_pos = std::min(first_pos, pred_block_info->pos);
- last_pos = std::min(last_pos, pred_block_info->pos);
+ last_pos = std::max(last_pos, pred_block_info->pos);
}
}
diff --git a/src/reader/spirv/function_var_test.cc b/src/reader/spirv/function_var_test.cc
index 790586c..1543518 100644
--- a/src/reader/spirv/function_var_test.cc
+++ b/src/reader/spirv/function_var_test.cc
@@ -1811,6 +1811,13 @@
}
}
Loop{
+ VariableDeclStatement{
+ Variable{
+ x_2_phi
+ function
+ __u32
+ }
+ }
If{
(
Identifier[not set]{x_101}
@@ -1819,13 +1826,6 @@
Break{}
}
}
- VariableDeclStatement{
- Variable{
- x_2_phi
- function
- __u32
- }
- }
If{
(
Identifier[not set]{x_102}
@@ -1865,7 +1865,7 @@
}
Return{}
)";
- EXPECT_EQ(expect, got);
+ EXPECT_EQ(expect, got) << got;
}
TEST_F(SpvParserTest, EmitStatement_Phi_FromHeaderAndThen) {
@@ -1933,6 +1933,13 @@
}
}
Loop{
+ VariableDeclStatement{
+ Variable{
+ x_2_phi
+ function
+ __u32
+ }
+ }
If{
(
Identifier[not set]{x_101}
@@ -1941,13 +1948,6 @@
Break{}
}
}
- VariableDeclStatement{
- Variable{
- x_2_phi
- function
- __u32
- }
- }
Assignment{
Identifier[not set]{x_2_phi}
ScalarConstructor[not set]{0}
@@ -1982,7 +1982,108 @@
}
Return{}
)";
- EXPECT_EQ(expect, got);
+ EXPECT_EQ(expect, got) << got;
+}
+
+TEST_F(SpvParserTest,
+ EmitStatement_Phi_InMerge_PredecessorsDominatdByNestedSwitchCase) {
+ // This is the essence of the bug report from crbug.com/tint/495
+ auto assembly = Preamble() + R"(
+ %cond = OpConstantTrue %bool
+ %pty = OpTypePointer Private %uint
+ %1 = OpVariable %pty Private
+ %boolpty = OpTypePointer Private %bool
+ %7 = OpVariable %boolpty Private
+ %8 = OpVariable %boolpty Private
+
+ %100 = OpFunction %void None %voidfn
+
+ %10 = OpLabel
+ OpSelectionMerge %99 None
+ OpSwitch %uint_1 %20 0 %20 1 %30
+
+ %20 = OpLabel ; case 0
+ OpBranch %30 ;; fall through
+
+ %30 = OpLabel ; case 1
+ OpSelectionMerge %50 None
+ OpBranchConditional %true %40 %45
+
+ %40 = OpLabel
+ OpBranch %50
+
+ %45 = OpLabel
+ OpBranch %99 ; break
+
+ %50 = OpLabel ; end the case
+ OpBranch %99
+
+ %99 = OpLabel
+ ; predecessors are all dominated by case construct head at %30
+ %phi = OpPhi %uint %uint_0 %45 %uint_1 %50
+ OpReturn
+
+ OpFunctionEnd
+ )";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+
+ auto got = ToString(p->builder(), fe.ast_body());
+ auto* expect = R"(VariableDeclStatement{
+ Variable{
+ x_35_phi
+ function
+ __u32
+ }
+}
+Switch{
+ ScalarConstructor[not set]{1}
+ {
+ Default{
+ Fallthrough{}
+ }
+ Case 0{
+ Fallthrough{}
+ }
+ Case 1{
+ If{
+ (
+ ScalarConstructor[not set]{true}
+ )
+ {
+ }
+ }
+ Else{
+ {
+ Assignment{
+ Identifier[not set]{x_35_phi}
+ ScalarConstructor[not set]{0}
+ }
+ Break{}
+ }
+ }
+ Assignment{
+ Identifier[not set]{x_35_phi}
+ ScalarConstructor[not set]{1}
+ }
+ }
+ }
+}
+VariableDeclStatement{
+ VariableConst{
+ x_35
+ none
+ __u32
+ {
+ Identifier[not set]{x_35_phi}
+ }
+ }
+}
+Return{}
+)";
+ EXPECT_EQ(expect, got) << got << assembly;
}
TEST_F(SpvParserTest, EmitStatement_UseInPhiCountsAsUse) {