[spirv-reader] Test loop block order

Change-Id: If33d37d2813b1b1e584972d4da7aadbcb345d12f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/20066
Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
David Neto 2020-04-21 17:44:44 +00:00
parent b5d518b68b
commit 8e8c291db1
1 changed files with 462 additions and 3 deletions

View File

@ -35,6 +35,7 @@ std::string CommonTypes() {
%bool = OpTypeBool
%cond = OpUndef %bool
%cond2 = OpUndef %bool
%uint = OpTypeInt 32 0
%selector = OpUndef %uint
@ -502,7 +503,7 @@ TEST_F(SpvParserTest,
}
TEST_F(SpvParserTest,
ComputeBlockOrder_Nest_If_In_If) {
ComputeBlockOrder_Nest_If_Contains_If) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
@ -691,8 +692,466 @@ TEST_F(SpvParserTest,
<< assembly;
}
// TODO(dneto): test nesting
// TODO(dneto): test loops
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_SingleBlock_Simple) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
; The entry block can't be the target of a branch
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %20 None
OpBranchConditional %cond %20 %99
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_SingleBlock_Infinite) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
; The entry block can't be the target of a branch
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %20 None
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_SingleBlock_DupInfinite) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
; The entry block can't be the target of a branch
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %20 None
OpBranchConditional %cond %20 %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_HeaderHasBreakIf) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99 ; like While
%30 = OpLabel ; trivial body
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_HeaderHasBreakUnless) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %99 %30 ; has break-unless
%30 = OpLabel ; trivial body
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasBreak) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranch %99 ; break
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasBreakIf) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranchConditional %cond2 %99 %40 ; break-if
%40 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasBreakUnless) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranchConditional %cond2 %40 %99 ; break-unless
%40 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasContinueIf) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranchConditional %cond2 %50 %40 ; continue-if
%40 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasContinueUnless) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranchConditional %cond2 %40 %50 ; continue-unless
%40 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasSwitchContinueBreak) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpSwitch %selector %99 50 %50 ; default is break, 50 is continue
%40 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_Sequence) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranch %60
%60 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 60, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_ContainsIf) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranch %50
%50 = OpLabel
OpSelectionMerge %89 None
OpBranchConditional %cond2 %60 %70
%89 = OpLabel
OpBranch %20 ; backedge
%60 = OpLabel
OpBranch %89
%70 = OpLabel
OpBranch %89
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 60, 70, 89, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_HasBreakIf) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranchConditional %cond2 %99 %20
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_HasBreakUnless) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranch %50
%50 = OpLabel
OpBranchConditional %cond2 %20 %99
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_SwitchBreak) {
auto assembly = CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %50 None
OpBranchConditional %cond %30 %99
%30 = OpLabel
OpBranch %50
%50 = OpLabel
OpSwitch %selector %20 99 %99 ; yes, this is obtuse but valid
%99 = OpLabel
OpReturn
)";
auto* p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
fe.ComputeBlockOrderAndPositions();
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
}
} // namespace
} // namespace spirv