From dc8efd4095ce8bb0eb48c309bc887ed133955e66 Mon Sep 17 00:00:00 2001 From: David Neto Date: Mon, 8 Jun 2020 14:53:34 +0000 Subject: [PATCH] [spirv-reader] Add mergeless OpSwitch case This is a bit pathological. Bug: tint:3 Change-Id: I820d7d1bfd298a22be6c6014e7d4d00f1097759e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22740 Reviewed-by: dan sinclair --- src/reader/spirv/function_cfg_test.cc | 68 +++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/reader/spirv/function_cfg_test.cc b/src/reader/spirv/function_cfg_test.cc index 9cc83045cd..447c259e3b 100644 --- a/src/reader/spirv/function_cfg_test.cc +++ b/src/reader/spirv/function_cfg_test.cc @@ -8589,6 +8589,74 @@ Return{} )")) << ToString(fe.ast_body()); } +TEST_F(SpvParserTest, + DISABLED_Switch_NotAsSelectionHeader_NonDefaultBranchesAreContinue) { + // Adapted from SPIRV-Tools test MissingMergeOneUnseenTargetSwitchGood + auto* p = parser(test::Assemble(CommonTypes() + R"( + %100 = OpFunction %void None %voidfn + %entry = OpLabel + OpBranch %loop + %loop = OpLabel + OpLoopMerge %merge %cont None + OpBranchConditional %cond %merge %b1 + + ; Here an OpSwitch is used with only one "unseen-so-far" target + ; so it doesn't need an OpSelectionMerge. + ; The %cont target can be implemented via "continue". So we can + ; generate: + ; if ((selector != 1) && (selector != 3)) { continue; } + %b1 = OpLabel + OpSwitch %selector %b2 0 %b2 1 %cont 2 %b2 3 %cont + + %b2 = OpLabel ; the one unseen target + OpBranch %cont + %cont = OpLabel + OpBranchConditional %cond2 %merge %loop + %merge = OpLabel + OpReturn + OpFunctionEnd + )")); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(unhandled case)")) + << ToString(fe.ast_body()); +} + +TEST_F(SpvParserTest, + DISABLED_Switch_NotAsSelectionHeader_DefaultBranchIsContinue) { + // Adapted from SPIRV-Tools test MissingMergeOneUnseenTargetSwitchGood + auto* p = parser(test::Assemble(CommonTypes() + R"( + %100 = OpFunction %void None %voidfn + %entry = OpLabel + OpBranch %loop + %loop = OpLabel + OpLoopMerge %merge %cont None + OpBranchConditional %cond %merge %b1 + + ; Here an OpSwitch is used with only one "unseen-so-far" target + ; so it doesn't need an OpSelectionMerge. + ; The %cont target can be implemented via "continue". So we can + ; generate: + ; if (!(selector == 0 || selector == 2)) {continue;} + %b1 = OpLabel + OpSwitch %selector %cont 0 %b2 1 %cont 2 %b2 + + %b2 = OpLabel ; the one unseen target + OpBranch %cont + %cont = OpLabel + OpBranchConditional %cond2 %merge %loop + %merge = OpLabel + OpReturn + OpFunctionEnd + )")); + ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error(); + FunctionEmitter fe(p, *spirv_function(100)); + EXPECT_TRUE(fe.EmitBody()) << p->error(); + EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(unhandled case)")) + << ToString(fe.ast_body()); +} + } // namespace } // namespace spirv } // namespace reader