|
|
@@ -26,6 +26,7 @@ namespace opt {
|
|
|
namespace {
|
|
|
|
|
|
using StructCFGAnalysisTest = PassTest<::testing::Test>;
|
|
|
+using ::testing::UnorderedElementsAre;
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, BBInSelection) {
|
|
|
const std::string text = R"(
|
|
|
@@ -62,6 +63,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// BB2 is in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -70,6 +75,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The merge node is not in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -78,6 +87,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, BBInLoop) {
|
|
|
@@ -119,6 +132,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// BB2 is in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -127,6 +144,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The merge node is not in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -135,6 +156,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The continue block is in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -143,6 +168,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(4));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, SelectionInLoop) {
|
|
|
@@ -189,6 +218,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// Selection header is in the loop only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -197,6 +230,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The loop merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -205,6 +242,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The continue block is in the loop only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -213,14 +254,22 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
- // BB5 is in the selection fist and the loop.
|
|
|
+ // BB5 is in the selection and the loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
EXPECT_EQ(analysis.ContainingLoop(5), 1);
|
|
|
EXPECT_EQ(analysis.MergeBlock(5), 6);
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
|
|
|
// The selection merge is in the loop only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(6), 1);
|
|
|
@@ -229,6 +278,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(6), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(6), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(6), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(6));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(6));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, LoopInSelection) {
|
|
|
@@ -275,6 +328,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// Loop header is in the selection only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -283,6 +340,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The selection merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -291,6 +352,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The loop merge is in the selection only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -299,6 +364,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
// The loop continue target is in the loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
@@ -307,6 +376,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 4);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
|
|
|
// BB6 is in the loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(6), 2);
|
|
|
@@ -315,6 +388,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(6), 4);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(6), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(6), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(6));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, SelectionInSelection) {
|
|
|
@@ -359,6 +436,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// The inner header is in the outer selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -367,6 +448,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The outer merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -375,6 +460,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The inner merge is in the outer selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -383,6 +472,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
// BB5 is in the inner selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
@@ -391,6 +484,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, LoopInLoop) {
|
|
|
@@ -439,6 +536,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// The inner loop header is in the outer loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -447,6 +548,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The outer merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -455,6 +560,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The inner merge is in the outer loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -463,6 +572,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
// The inner continue target is in the inner loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
@@ -471,6 +584,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 4);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
|
|
|
// BB6 is in the loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(6), 2);
|
|
|
@@ -479,6 +596,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(6), 4);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(6), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(6), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(6));
|
|
|
|
|
|
// The outer continue target is in the outer loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(7), 1);
|
|
|
@@ -487,6 +608,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(7), 3);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(7), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(7), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(7));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(7));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(7));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(7));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, KernelTest) {
|
|
|
@@ -523,6 +648,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(i), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(i), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(i), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(i));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(i));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(i));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(i));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -581,6 +710,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// BB2 is in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -589,6 +722,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 1);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 3);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The merge node is not in the construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -597,6 +734,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, LoopInSwitch) {
|
|
|
@@ -643,6 +784,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// Loop header is in the selection only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -651,6 +796,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 1);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 3);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The selection merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -659,6 +808,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The loop merge is in the selection only.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -667,6 +820,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 1);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 3);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
// The loop continue target is in the loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
@@ -675,6 +832,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 4);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
|
|
|
// BB6 is in the loop.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(6), 2);
|
|
|
@@ -683,6 +844,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(6), 4);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(6), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(6), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(6));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, SelectionInSwitch) {
|
|
|
@@ -727,6 +892,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// The inner header is in the outer selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -735,6 +904,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 1);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 3);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The outer merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -743,6 +916,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The inner merge is in the outer selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -751,6 +928,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 1);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 3);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
// BB5 is in the inner selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
@@ -759,6 +940,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 1);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 3);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
}
|
|
|
|
|
|
TEST_F(StructCFGAnalysisTest, SwitchInSelection) {
|
|
|
@@ -803,6 +988,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
|
|
|
// The inner header is in the outer selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
@@ -811,6 +1000,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(2), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
|
|
|
// The outer merge node is not in either construct.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
@@ -819,6 +1012,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
|
|
|
// The inner merge is in the outer selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
@@ -827,6 +1024,10 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(4), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
|
|
|
// BB5 is in the inner selection.
|
|
|
EXPECT_EQ(analysis.ContainingConstruct(5), 2);
|
|
|
@@ -835,8 +1036,339 @@ OpFunctionEnd
|
|
|
EXPECT_EQ(analysis.LoopMergeBlock(5), 0);
|
|
|
EXPECT_EQ(analysis.ContainingSwitch(5), 2);
|
|
|
EXPECT_EQ(analysis.SwitchMergeBlock(5), 4);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
}
|
|
|
|
|
|
+TEST_F(StructCFGAnalysisTest, SelectionInContinue) {
|
|
|
+ const std::string text = R"(
|
|
|
+OpCapability Shader
|
|
|
+OpMemoryModel Logical GLSL450
|
|
|
+OpEntryPoint Fragment %main "main"
|
|
|
+%void = OpTypeVoid
|
|
|
+%bool = OpTypeBool
|
|
|
+%bool_undef = OpUndef %bool
|
|
|
+%uint = OpTypeInt 32 0
|
|
|
+%uint_undef = OpUndef %uint
|
|
|
+%void_func = OpTypeFunction %void
|
|
|
+%main = OpFunction %void None %void_func
|
|
|
+%entry_lab = OpLabel
|
|
|
+OpBranch %1
|
|
|
+%1 = OpLabel
|
|
|
+OpLoopMerge %3 %4 None
|
|
|
+OpBranchConditional %undef_bool %2 %3
|
|
|
+%2 = OpLabel
|
|
|
+OpBranch %3
|
|
|
+%4 = OpLabel
|
|
|
+OpSelectionMerge %6 None
|
|
|
+OpBranchConditional %undef_bool %5 %6
|
|
|
+%5 = OpLabel
|
|
|
+OpBranch %6
|
|
|
+%6 = OpLabel
|
|
|
+OpBranch %1
|
|
|
+%3 = OpLabel
|
|
|
+OpReturn
|
|
|
+OpFunctionEnd
|
|
|
+)";
|
|
|
+
|
|
|
+ std::unique_ptr<IRContext> context =
|
|
|
+ BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
|
|
|
+ SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
|
|
+
|
|
|
+ StructuredCFGAnalysis analysis(context.get());
|
|
|
+
|
|
|
+ // The loop header is not in either construct.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(1), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(1), 0);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(1), 0);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
+
|
|
|
+ // Selection header is in the loop only.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(2), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(2), 3);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(2), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
+
|
|
|
+ // The loop merge node is not in either construct.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(3), 0);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(3), 0);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
+
|
|
|
+ // The continue block is in the loop only.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(4), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(4), 3);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(4), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(4));
|
|
|
+
|
|
|
+ // BB5 is in the selection and the continue for the loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(5), 4);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(5), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(5), 6);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(5), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
+
|
|
|
+ // BB5 is in the continue for the loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(6), 1);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(6), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(6), 3);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(6), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(6), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(6), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(6));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(6));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(6));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(6));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(StructCFGAnalysisTest, LoopInContinue) {
|
|
|
+ const std::string text = R"(
|
|
|
+OpCapability Shader
|
|
|
+OpMemoryModel Logical GLSL450
|
|
|
+OpEntryPoint Fragment %main "main"
|
|
|
+%void = OpTypeVoid
|
|
|
+%bool = OpTypeBool
|
|
|
+%bool_undef = OpUndef %bool
|
|
|
+%uint = OpTypeInt 32 0
|
|
|
+%uint_undef = OpUndef %uint
|
|
|
+%void_func = OpTypeFunction %void
|
|
|
+%main = OpFunction %void None %void_func
|
|
|
+%entry_lab = OpLabel
|
|
|
+OpBranch %1
|
|
|
+%1 = OpLabel
|
|
|
+OpLoopMerge %3 %7 None
|
|
|
+OpBranchConditional %undef_bool %2 %3
|
|
|
+%2 = OpLabel
|
|
|
+OpBranchConditional %undef_bool %3 %7
|
|
|
+%7 = OpLabel
|
|
|
+OpLoopMerge %4 %5 None
|
|
|
+OpBranchConditional %undef_bool %4 %6
|
|
|
+%5 = OpLabel
|
|
|
+OpBranch %7
|
|
|
+%6 = OpLabel
|
|
|
+OpBranch %4
|
|
|
+%4 = OpLabel
|
|
|
+OpBranch %1
|
|
|
+%3 = OpLabel
|
|
|
+OpReturn
|
|
|
+OpFunctionEnd
|
|
|
+)";
|
|
|
+
|
|
|
+ std::unique_ptr<IRContext> context =
|
|
|
+ BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
|
|
|
+ SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
|
|
+
|
|
|
+ StructuredCFGAnalysis analysis(context.get());
|
|
|
+
|
|
|
+ // The outer loop header is not in either construct.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(1), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(1), 0);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(1), 0);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(1), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(1), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(1), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(1));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(1));
|
|
|
+
|
|
|
+ // BB2 is a regular block in the inner loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(2), 1);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(2), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(2), 3);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(2), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(2), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(2), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(2));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(2));
|
|
|
+
|
|
|
+ // The outer merge node is not in either construct.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(3), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(3), 0);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(3), 0);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(3), 0);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(3), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(3), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3));
|
|
|
+ EXPECT_FALSE(analysis.IsInContinueConstruct(3));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(3));
|
|
|
+
|
|
|
+ // The inner merge is in the continue of the outer loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(4), 1);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(4), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(4), 3);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(4), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(4), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(4), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(4));
|
|
|
+ EXPECT_TRUE(analysis.IsMergeBlock(4));
|
|
|
+
|
|
|
+ // The inner continue target is in the inner loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(5), 7);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(5), 7);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(5), 4);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(5), 4);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(5), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(5), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(5));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(5));
|
|
|
+
|
|
|
+ // BB6 is a regular block in the inner loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(6), 7);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(6), 7);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(6), 4);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(6), 4);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(6), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(6), 0);
|
|
|
+ EXPECT_FALSE(analysis.IsContinueBlock(6));
|
|
|
+ EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(6));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(6));
|
|
|
+
|
|
|
+ // The outer continue target is in the outer loop.
|
|
|
+ EXPECT_EQ(analysis.ContainingConstruct(7), 1);
|
|
|
+ EXPECT_EQ(analysis.ContainingLoop(7), 1);
|
|
|
+ EXPECT_EQ(analysis.MergeBlock(7), 3);
|
|
|
+ EXPECT_EQ(analysis.LoopMergeBlock(7), 3);
|
|
|
+ EXPECT_EQ(analysis.ContainingSwitch(7), 0);
|
|
|
+ EXPECT_EQ(analysis.SwitchMergeBlock(7), 0);
|
|
|
+ EXPECT_TRUE(analysis.IsContinueBlock(7));
|
|
|
+ EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(7));
|
|
|
+ EXPECT_TRUE(analysis.IsInContinueConstruct(7));
|
|
|
+ EXPECT_FALSE(analysis.IsMergeBlock(7));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(StructCFGAnalysisTest, FuncCallInContinueDirect) {
|
|
|
+ const std::string text = R"(
|
|
|
+ OpCapability Shader
|
|
|
+ OpMemoryModel Logical GLSL450
|
|
|
+ OpEntryPoint Fragment %1 "main"
|
|
|
+ %void = OpTypeVoid
|
|
|
+ %bool = OpTypeBool
|
|
|
+ %4 = OpUndef %bool
|
|
|
+ %uint = OpTypeInt 32 0
|
|
|
+ %6 = OpUndef %uint
|
|
|
+ %7 = OpTypeFunction %void
|
|
|
+ %1 = OpFunction %void None %7
|
|
|
+ %8 = OpLabel
|
|
|
+ OpBranch %9
|
|
|
+ %9 = OpLabel
|
|
|
+ OpLoopMerge %10 %11 None
|
|
|
+ OpBranchConditional %12 %10 %11
|
|
|
+ %11 = OpLabel
|
|
|
+ %13 = OpFunctionCall %void %14
|
|
|
+ OpBranch %9
|
|
|
+ %10 = OpLabel
|
|
|
+ %15 = OpFunctionCall %void %16
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+ %14 = OpFunction %void None %7
|
|
|
+ %17 = OpLabel
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+ %16 = OpFunction %void None %7
|
|
|
+ %18 = OpLabel
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+)";
|
|
|
+
|
|
|
+ std::unique_ptr<IRContext> context =
|
|
|
+ BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
|
|
|
+ SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
|
|
+
|
|
|
+ StructuredCFGAnalysis analysis(context.get());
|
|
|
+
|
|
|
+ auto c = analysis.FindFuncsCalledFromContinue();
|
|
|
+ EXPECT_THAT(c, UnorderedElementsAre(14u));
|
|
|
+}
|
|
|
+
|
|
|
+TEST_F(StructCFGAnalysisTest, FuncCallInContinueIndirect) {
|
|
|
+ const std::string text = R"(
|
|
|
+ OpCapability Shader
|
|
|
+ OpMemoryModel Logical GLSL450
|
|
|
+ OpEntryPoint Fragment %1 "main"
|
|
|
+ %void = OpTypeVoid
|
|
|
+ %bool = OpTypeBool
|
|
|
+ %4 = OpUndef %bool
|
|
|
+ %uint = OpTypeInt 32 0
|
|
|
+ %6 = OpUndef %uint
|
|
|
+ %7 = OpTypeFunction %void
|
|
|
+ %1 = OpFunction %void None %7
|
|
|
+ %8 = OpLabel
|
|
|
+ OpBranch %9
|
|
|
+ %9 = OpLabel
|
|
|
+ OpLoopMerge %10 %11 None
|
|
|
+ OpBranchConditional %12 %10 %11
|
|
|
+ %11 = OpLabel
|
|
|
+ %13 = OpFunctionCall %void %14
|
|
|
+ OpBranch %9
|
|
|
+ %10 = OpLabel
|
|
|
+ %15 = OpFunctionCall %void %16
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+ %14 = OpFunction %void None %7
|
|
|
+ %17 = OpLabel
|
|
|
+ %19 = OpFunctionCall %void %16
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+ %16 = OpFunction %void None %7
|
|
|
+ %18 = OpLabel
|
|
|
+ %20 = OpFunctionCall %void %21
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+ %21 = OpFunction %void None %7
|
|
|
+ %22 = OpLabel
|
|
|
+ OpReturn
|
|
|
+ OpFunctionEnd
|
|
|
+)";
|
|
|
+
|
|
|
+ std::unique_ptr<IRContext> context =
|
|
|
+ BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
|
|
|
+ SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
|
|
+
|
|
|
+ StructuredCFGAnalysis analysis(context.get());
|
|
|
+
|
|
|
+ auto c = analysis.FindFuncsCalledFromContinue();
|
|
|
+ EXPECT_THAT(c, UnorderedElementsAre(14u, 16u, 21u));
|
|
|
+}
|
|
|
} // namespace
|
|
|
} // namespace opt
|
|
|
} // namespace spvtools
|