Add continue construct analysis to struct cfg analysis (#2922)
* Add continue construct analysis to struct cfg analysis Add the ability to identify which blocks are in the continue construct for a loop, and to get functions that are called from those blocks, directly or indirectly. Part of https://github.com/KhronosGroup/SPIRV-Tools/issues/2912.
This commit is contained in:
Родитель
85c67b5e08
Коммит
9eb1c9a4c4
|
@ -60,8 +60,9 @@ class CFG {
|
|||
|
||||
// Compute structured block order into |order| for |func| starting at |root|.
|
||||
// This order has the property that dominators come before all blocks they
|
||||
// dominate and merge blocks come after all blocks that are in the control
|
||||
// constructs of their header.
|
||||
// dominate, merge blocks come after all blocks that are in the control
|
||||
// constructs of their header, and continue blocks come after all of the
|
||||
// blocks in the body of their loop.
|
||||
void ComputeStructuredOrder(Function* func, BasicBlock* root,
|
||||
std::list<BasicBlock*>* order);
|
||||
|
||||
|
|
|
@ -540,7 +540,7 @@ class IRContext {
|
|||
return GetFunction(inst->result_id());
|
||||
}
|
||||
|
||||
// Add to |todo| all ids of functions called in |func|.
|
||||
// Add to |todo| all ids of functions called directly from |func|.
|
||||
void AddCalls(const Function* func, std::queue<uint32_t>* todo);
|
||||
|
||||
// Applies |pfn| to every function in the call trees that are rooted at the
|
||||
|
|
|
@ -45,6 +45,7 @@ void StructuredCFGAnalysis::AddBlocksInFunction(Function* func) {
|
|||
struct TraversalInfo {
|
||||
ConstructInfo cinfo;
|
||||
uint32_t merge_node;
|
||||
uint32_t continue_node;
|
||||
};
|
||||
|
||||
// Set up a stack to keep track of currently active constructs.
|
||||
|
@ -53,7 +54,9 @@ void StructuredCFGAnalysis::AddBlocksInFunction(Function* func) {
|
|||
state[0].cinfo.containing_construct = 0;
|
||||
state[0].cinfo.containing_loop = 0;
|
||||
state[0].cinfo.containing_switch = 0;
|
||||
state[0].cinfo.in_continue = false;
|
||||
state[0].merge_node = 0;
|
||||
state[0].continue_node = 0;
|
||||
|
||||
for (BasicBlock* block : order) {
|
||||
if (context_->cfg()->IsPseudoEntryBlock(block) ||
|
||||
|
@ -65,6 +68,12 @@ void StructuredCFGAnalysis::AddBlocksInFunction(Function* func) {
|
|||
state.pop_back();
|
||||
}
|
||||
|
||||
// This works because the structured order is designed to keep the blocks in
|
||||
// the continue construct between the continue header and the merge node.
|
||||
if (block->id() == state.back().continue_node) {
|
||||
state.back().cinfo.in_continue = true;
|
||||
}
|
||||
|
||||
bb_to_construct_.emplace(std::make_pair(block->id(), state.back().cinfo));
|
||||
|
||||
if (Instruction* merge_inst = block->GetMergeInst()) {
|
||||
|
@ -76,8 +85,14 @@ void StructuredCFGAnalysis::AddBlocksInFunction(Function* func) {
|
|||
if (merge_inst->opcode() == SpvOpLoopMerge) {
|
||||
new_state.cinfo.containing_loop = block->id();
|
||||
new_state.cinfo.containing_switch = 0;
|
||||
new_state.cinfo.in_continue = false;
|
||||
new_state.continue_node =
|
||||
merge_inst->GetSingleWordInOperand(kContinueNodeIndex);
|
||||
} else {
|
||||
new_state.cinfo.containing_loop = state.back().cinfo.containing_loop;
|
||||
new_state.cinfo.in_continue = state.back().cinfo.in_continue;
|
||||
new_state.continue_node = state.back().continue_node;
|
||||
|
||||
if (merge_inst->NextNode()->opcode() == SpvOpSwitch) {
|
||||
new_state.cinfo.containing_switch = block->id();
|
||||
} else {
|
||||
|
@ -146,9 +161,59 @@ bool StructuredCFGAnalysis::IsContinueBlock(uint32_t bb_id) {
|
|||
return LoopContinueBlock(bb_id) == bb_id;
|
||||
}
|
||||
|
||||
bool StructuredCFGAnalysis::IsInContainingLoopsContinueConstruct(
|
||||
uint32_t bb_id) {
|
||||
auto it = bb_to_construct_.find(bb_id);
|
||||
if (it == bb_to_construct_.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->second.in_continue;
|
||||
}
|
||||
|
||||
bool StructuredCFGAnalysis::IsInContinueConstruct(uint32_t bb_id) {
|
||||
while (bb_id != 0) {
|
||||
if (IsInContainingLoopsContinueConstruct(bb_id)) {
|
||||
return true;
|
||||
}
|
||||
bb_id = ContainingLoop(bb_id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StructuredCFGAnalysis::IsMergeBlock(uint32_t bb_id) {
|
||||
return merge_blocks_.Get(bb_id);
|
||||
}
|
||||
|
||||
std::unordered_set<uint32_t>
|
||||
StructuredCFGAnalysis::FindFuncsCalledFromContinue() {
|
||||
std::unordered_set<uint32_t> called_from_continue;
|
||||
std::queue<uint32_t> funcs_to_process;
|
||||
|
||||
// First collect the functions that are called directly from a continue
|
||||
// construct.
|
||||
for (Function& func : *context_->module()) {
|
||||
for (auto& bb : func) {
|
||||
if (IsInContainingLoopsContinueConstruct(bb.id())) {
|
||||
for (const Instruction& inst : bb) {
|
||||
if (inst.opcode() == SpvOpFunctionCall) {
|
||||
funcs_to_process.push(inst.GetSingleWordInOperand(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now collect all of the functions that are indirectly called as well.
|
||||
while (!funcs_to_process.empty()) {
|
||||
uint32_t func_id = funcs_to_process.front();
|
||||
funcs_to_process.pop();
|
||||
Function* func = context_->GetFunction(func_id);
|
||||
if (called_from_continue.insert(func_id).second) {
|
||||
context_->AddCalls(func, &funcs_to_process);
|
||||
}
|
||||
}
|
||||
return called_from_continue;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define SOURCE_OPT_STRUCT_CFG_ANALYSIS_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "source/opt/function.h"
|
||||
#include "source/util/bit_vector.h"
|
||||
|
@ -88,21 +89,46 @@ class StructuredCFGAnalysis {
|
|||
// if no such block exists.
|
||||
uint32_t SwitchMergeBlock(uint32_t bb_id);
|
||||
|
||||
// Returns true if |bb_id| is the continue block for a loop.
|
||||
bool IsContinueBlock(uint32_t bb_id);
|
||||
|
||||
// Returns true if |bb_id| is in the continue construct for its inner most
|
||||
// containing loop.
|
||||
bool IsInContainingLoopsContinueConstruct(uint32_t bb_id);
|
||||
|
||||
// Returns true if |bb_id| is in the continue construct for any loop in its
|
||||
// function.
|
||||
bool IsInContinueConstruct(uint32_t bb_id);
|
||||
|
||||
// Return true if |bb_id| is the merge block for a construct.
|
||||
bool IsMergeBlock(uint32_t bb_id);
|
||||
|
||||
// Returns the set of function ids that are called directly or indirectly from
|
||||
// a continue construct.
|
||||
std::unordered_set<uint32_t> FindFuncsCalledFromContinue();
|
||||
|
||||
private:
|
||||
// Struct used to hold the information for a basic block.
|
||||
// |containing_construct| is the header for the innermost containing
|
||||
// construct, or 0 if no such construct exists. It could be a selection
|
||||
// construct or a loop construct. |containing_loop| is the innermost
|
||||
// containing loop construct, or 0 if the basic bloc is not in a loop. If the
|
||||
// basic block is in a selection construct that is contained in a loop
|
||||
// construct, then these two values will not be the same.
|
||||
// construct or a loop construct.
|
||||
//
|
||||
// |containing_loop| is the innermost containing loop construct, or 0 if the
|
||||
// basic bloc is not in a loop. If the basic block is in a selection
|
||||
// construct that is contained in a loop construct, then these two values will
|
||||
// not be the same.
|
||||
//
|
||||
// |containing_switch| is the innermost contain selection construct with an
|
||||
// |OpSwitch| for the branch, as long as there is not intervening loop. This
|
||||
// is used to identify the selection construct from which it can break.
|
||||
//
|
||||
// |in_continue| is true of the block is in the continue construct for its
|
||||
// innermost containing loop.
|
||||
struct ConstructInfo {
|
||||
uint32_t containing_construct;
|
||||
uint32_t containing_loop;
|
||||
uint32_t containing_switch;
|
||||
bool in_continue;
|
||||
};
|
||||
|
||||
// Populates |bb_to_construct_| with the innermost containing merge and loop
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче