1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include "source/opt/struct_cfg_analysis.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include <string> 18fd4e5da5Sopenharmony_ci 19fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 20fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 21fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 22fd4e5da5Sopenharmony_ci 23fd4e5da5Sopenharmony_cinamespace spvtools { 24fd4e5da5Sopenharmony_cinamespace opt { 25fd4e5da5Sopenharmony_cinamespace { 26fd4e5da5Sopenharmony_ci 27fd4e5da5Sopenharmony_ciusing StructCFGAnalysisTest = PassTest<::testing::Test>; 28fd4e5da5Sopenharmony_ciusing ::testing::UnorderedElementsAre; 29fd4e5da5Sopenharmony_ci 30fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, BBInSelection) { 31fd4e5da5Sopenharmony_ci const std::string text = R"( 32fd4e5da5Sopenharmony_ciOpCapability Shader 33fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 34fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 35fd4e5da5Sopenharmony_ci%void = OpTypeVoid 36fd4e5da5Sopenharmony_ci%bool = OpTypeBool 37fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 38fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 39fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 40fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 41fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 42fd4e5da5Sopenharmony_ci%1 = OpLabel 43fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 44fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 45fd4e5da5Sopenharmony_ci%2 = OpLabel 46fd4e5da5Sopenharmony_ciOpBranch %3 47fd4e5da5Sopenharmony_ci%3 = OpLabel 48fd4e5da5Sopenharmony_ciOpReturn 49fd4e5da5Sopenharmony_ciOpFunctionEnd 50fd4e5da5Sopenharmony_ci)"; 51fd4e5da5Sopenharmony_ci 52fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 53fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 54fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 55fd4e5da5Sopenharmony_ci 56fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 57fd4e5da5Sopenharmony_ci 58fd4e5da5Sopenharmony_ci // The header is not in the construct. 59fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 60fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 61fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 62fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 63fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 64fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 65fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 66fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 67fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 68fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 69fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 70fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 71fd4e5da5Sopenharmony_ci 72fd4e5da5Sopenharmony_ci // BB2 is in the construct. 73fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 74fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 75fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 76fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 77fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 78fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 79fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 80fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 81fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 82fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 83fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 84fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 85fd4e5da5Sopenharmony_ci 86fd4e5da5Sopenharmony_ci // The merge node is not in the construct. 87fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 88fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 89fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 90fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 91fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 92fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 93fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 94fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 95fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 96fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 97fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 98fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 99fd4e5da5Sopenharmony_ci} 100fd4e5da5Sopenharmony_ci 101fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, BBInLoop) { 102fd4e5da5Sopenharmony_ci const std::string text = R"( 103fd4e5da5Sopenharmony_ciOpCapability Shader 104fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 105fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 106fd4e5da5Sopenharmony_ci%void = OpTypeVoid 107fd4e5da5Sopenharmony_ci%bool = OpTypeBool 108fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 109fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 110fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 111fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 112fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 113fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 114fd4e5da5Sopenharmony_ciOpBranch %1 115fd4e5da5Sopenharmony_ci%1 = OpLabel 116fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None 117fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 118fd4e5da5Sopenharmony_ci%2 = OpLabel 119fd4e5da5Sopenharmony_ciOpBranch %3 120fd4e5da5Sopenharmony_ci%4 = OpLabel 121fd4e5da5Sopenharmony_ciOpBranch %1 122fd4e5da5Sopenharmony_ci%3 = OpLabel 123fd4e5da5Sopenharmony_ciOpReturn 124fd4e5da5Sopenharmony_ciOpFunctionEnd 125fd4e5da5Sopenharmony_ci)"; 126fd4e5da5Sopenharmony_ci 127fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 128fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 129fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 130fd4e5da5Sopenharmony_ci 131fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 132fd4e5da5Sopenharmony_ci 133fd4e5da5Sopenharmony_ci // The header is not in the construct. 134fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 135fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 136fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 137fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 138fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 139fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 140fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 141fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 142fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 143fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 144fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 145fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 146fd4e5da5Sopenharmony_ci 147fd4e5da5Sopenharmony_ci // BB2 is in the construct. 148fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 149fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 1); 150fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 151fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 152fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 3); 153fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 1); 154fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 155fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 156fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 157fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 158fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 159fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 160fd4e5da5Sopenharmony_ci 161fd4e5da5Sopenharmony_ci // The merge node is not in the construct. 162fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 163fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 164fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 165fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 166fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 167fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 168fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 169fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 170fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 171fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 172fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 173fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 174fd4e5da5Sopenharmony_ci 175fd4e5da5Sopenharmony_ci // The continue block is in the construct. 176fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 177fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 1); 178fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 179fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 180fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 3); 181fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 1); 182fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 183fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 184fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(4)); 185fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); 186fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(4)); 187fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(4)); 188fd4e5da5Sopenharmony_ci} 189fd4e5da5Sopenharmony_ci 190fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, SelectionInLoop) { 191fd4e5da5Sopenharmony_ci const std::string text = R"( 192fd4e5da5Sopenharmony_ciOpCapability Shader 193fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 194fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 195fd4e5da5Sopenharmony_ci%void = OpTypeVoid 196fd4e5da5Sopenharmony_ci%bool = OpTypeBool 197fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 198fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 199fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 200fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 201fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 202fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 203fd4e5da5Sopenharmony_ciOpBranch %1 204fd4e5da5Sopenharmony_ci%1 = OpLabel 205fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None 206fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 207fd4e5da5Sopenharmony_ci%2 = OpLabel 208fd4e5da5Sopenharmony_ciOpSelectionMerge %6 None 209fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %5 %6 210fd4e5da5Sopenharmony_ci%5 = OpLabel 211fd4e5da5Sopenharmony_ciOpBranch %6 212fd4e5da5Sopenharmony_ci%6 = OpLabel 213fd4e5da5Sopenharmony_ciOpBranch %3 214fd4e5da5Sopenharmony_ci%4 = OpLabel 215fd4e5da5Sopenharmony_ciOpBranch %1 216fd4e5da5Sopenharmony_ci%3 = OpLabel 217fd4e5da5Sopenharmony_ciOpReturn 218fd4e5da5Sopenharmony_ciOpFunctionEnd 219fd4e5da5Sopenharmony_ci)"; 220fd4e5da5Sopenharmony_ci 221fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 222fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 223fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 224fd4e5da5Sopenharmony_ci 225fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 226fd4e5da5Sopenharmony_ci 227fd4e5da5Sopenharmony_ci // The loop header is not in either construct. 228fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 229fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 230fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 231fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 232fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 233fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 234fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 235fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 236fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 237fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 238fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 239fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 240fd4e5da5Sopenharmony_ci 241fd4e5da5Sopenharmony_ci // Selection header is in the loop only. 242fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 243fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 1); 244fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 245fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 246fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 3); 247fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 1); 248fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 249fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 250fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 251fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 252fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 253fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 254fd4e5da5Sopenharmony_ci 255fd4e5da5Sopenharmony_ci // The loop merge node is not in either construct. 256fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 257fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 258fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 259fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 260fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 261fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 262fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 263fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 264fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 265fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 266fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 267fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 268fd4e5da5Sopenharmony_ci 269fd4e5da5Sopenharmony_ci // The continue block is in the loop only. 270fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 271fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 1); 272fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 273fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 274fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 3); 275fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 1); 276fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 277fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 278fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(4)); 279fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); 280fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(4)); 281fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(4)); 282fd4e5da5Sopenharmony_ci 283fd4e5da5Sopenharmony_ci // BB5 is in the selection and the loop. 284fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 285fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 1); 286fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 6); 287fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 288fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 3); 289fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 1); 290fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 291fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 292fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(5)); 293fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); 294fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(5)); 295fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 296fd4e5da5Sopenharmony_ci 297fd4e5da5Sopenharmony_ci // The selection merge is in the loop only. 298fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(6), 1); 299fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(6), 1); 300fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(6), 3); 301fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(6), 1); 302fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(6), 3); 303fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(6), 1); 304fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(6), 0); 305fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); 306fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(6)); 307fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); 308fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(6)); 309fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(6)); 310fd4e5da5Sopenharmony_ci} 311fd4e5da5Sopenharmony_ci 312fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, LoopInSelection) { 313fd4e5da5Sopenharmony_ci const std::string text = R"( 314fd4e5da5Sopenharmony_ciOpCapability Shader 315fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 316fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 317fd4e5da5Sopenharmony_ci%void = OpTypeVoid 318fd4e5da5Sopenharmony_ci%bool = OpTypeBool 319fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 320fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 321fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 322fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 323fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 324fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 325fd4e5da5Sopenharmony_ciOpBranch %1 326fd4e5da5Sopenharmony_ci%1 = OpLabel 327fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 328fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 329fd4e5da5Sopenharmony_ci%2 = OpLabel 330fd4e5da5Sopenharmony_ciOpLoopMerge %4 %5 None 331fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %4 %6 332fd4e5da5Sopenharmony_ci%5 = OpLabel 333fd4e5da5Sopenharmony_ciOpBranch %2 334fd4e5da5Sopenharmony_ci%6 = OpLabel 335fd4e5da5Sopenharmony_ciOpBranch %4 336fd4e5da5Sopenharmony_ci%4 = OpLabel 337fd4e5da5Sopenharmony_ciOpBranch %3 338fd4e5da5Sopenharmony_ci%3 = OpLabel 339fd4e5da5Sopenharmony_ciOpReturn 340fd4e5da5Sopenharmony_ciOpFunctionEnd 341fd4e5da5Sopenharmony_ci)"; 342fd4e5da5Sopenharmony_ci 343fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 344fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 345fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 346fd4e5da5Sopenharmony_ci 347fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 348fd4e5da5Sopenharmony_ci 349fd4e5da5Sopenharmony_ci // The selection header is not in either construct. 350fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 351fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 352fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 353fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 354fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 355fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 356fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 357fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 358fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 359fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 360fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 361fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 362fd4e5da5Sopenharmony_ci 363fd4e5da5Sopenharmony_ci // Loop header is in the selection only. 364fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 365fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 366fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 367fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 368fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 369fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 370fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 371fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 372fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 373fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 374fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 375fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 376fd4e5da5Sopenharmony_ci 377fd4e5da5Sopenharmony_ci // The selection merge node is not in either construct. 378fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 379fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 380fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 381fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 382fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 383fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 384fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 385fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 386fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 387fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 388fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 389fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 390fd4e5da5Sopenharmony_ci 391fd4e5da5Sopenharmony_ci // The loop merge is in the selection only. 392fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 393fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 0); 394fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 395fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 396fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 0); 397fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 0); 398fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 399fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 400fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 401fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); 402fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(4)); 403fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 404fd4e5da5Sopenharmony_ci 405fd4e5da5Sopenharmony_ci // The loop continue target is in the loop. 406fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 407fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 2); 408fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 409fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 410fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 4); 411fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 1); 412fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 413fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 414fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(5)); 415fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); 416fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(5)); 417fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 418fd4e5da5Sopenharmony_ci 419fd4e5da5Sopenharmony_ci // BB6 is in the loop. 420fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(6), 2); 421fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(6), 2); 422fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(6), 4); 423fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(6), 2); 424fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(6), 4); 425fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(6), 1); 426fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(6), 0); 427fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); 428fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(6)); 429fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); 430fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(6)); 431fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(6)); 432fd4e5da5Sopenharmony_ci} 433fd4e5da5Sopenharmony_ci 434fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, SelectionInSelection) { 435fd4e5da5Sopenharmony_ci const std::string text = R"( 436fd4e5da5Sopenharmony_ciOpCapability Shader 437fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 438fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 439fd4e5da5Sopenharmony_ci%void = OpTypeVoid 440fd4e5da5Sopenharmony_ci%bool = OpTypeBool 441fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 442fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 443fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 444fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 445fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 446fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 447fd4e5da5Sopenharmony_ciOpBranch %1 448fd4e5da5Sopenharmony_ci%1 = OpLabel 449fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 450fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 451fd4e5da5Sopenharmony_ci%2 = OpLabel 452fd4e5da5Sopenharmony_ciOpSelectionMerge %4 None 453fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %4 %5 454fd4e5da5Sopenharmony_ci%5 = OpLabel 455fd4e5da5Sopenharmony_ciOpBranch %4 456fd4e5da5Sopenharmony_ci%4 = OpLabel 457fd4e5da5Sopenharmony_ciOpBranch %3 458fd4e5da5Sopenharmony_ci%3 = OpLabel 459fd4e5da5Sopenharmony_ciOpReturn 460fd4e5da5Sopenharmony_ciOpFunctionEnd 461fd4e5da5Sopenharmony_ci)"; 462fd4e5da5Sopenharmony_ci 463fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 464fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 465fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 466fd4e5da5Sopenharmony_ci 467fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 468fd4e5da5Sopenharmony_ci 469fd4e5da5Sopenharmony_ci // The outer selection header is not in either construct. 470fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 471fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 472fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 473fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 474fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 475fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 476fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 477fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 478fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 479fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 480fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 481fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 482fd4e5da5Sopenharmony_ci 483fd4e5da5Sopenharmony_ci // The inner header is in the outer selection. 484fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 485fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 486fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 487fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 488fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 489fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 490fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 491fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 492fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 493fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 494fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 495fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 496fd4e5da5Sopenharmony_ci 497fd4e5da5Sopenharmony_ci // The outer merge node is not in either construct. 498fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 499fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 500fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 501fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 502fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 503fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 504fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 505fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 506fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 507fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 508fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 509fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 510fd4e5da5Sopenharmony_ci 511fd4e5da5Sopenharmony_ci // The inner merge is in the outer selection. 512fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 513fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 0); 514fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 515fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 516fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 0); 517fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 0); 518fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 519fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 520fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 521fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); 522fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(4)); 523fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 524fd4e5da5Sopenharmony_ci 525fd4e5da5Sopenharmony_ci // BB5 is in the inner selection. 526fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 527fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 0); 528fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 529fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 530fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 0); 531fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 0); 532fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 533fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 534fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(5)); 535fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); 536fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(5)); 537fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 538fd4e5da5Sopenharmony_ci} 539fd4e5da5Sopenharmony_ci 540fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, LoopInLoop) { 541fd4e5da5Sopenharmony_ci const std::string text = R"( 542fd4e5da5Sopenharmony_ciOpCapability Shader 543fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 544fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 545fd4e5da5Sopenharmony_ci%void = OpTypeVoid 546fd4e5da5Sopenharmony_ci%bool = OpTypeBool 547fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 548fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 549fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 550fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 551fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 552fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 553fd4e5da5Sopenharmony_ciOpBranch %1 554fd4e5da5Sopenharmony_ci%1 = OpLabel 555fd4e5da5Sopenharmony_ciOpLoopMerge %3 %7 None 556fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 557fd4e5da5Sopenharmony_ci%2 = OpLabel 558fd4e5da5Sopenharmony_ciOpLoopMerge %4 %5 None 559fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %4 %6 560fd4e5da5Sopenharmony_ci%5 = OpLabel 561fd4e5da5Sopenharmony_ciOpBranch %2 562fd4e5da5Sopenharmony_ci%6 = OpLabel 563fd4e5da5Sopenharmony_ciOpBranch %4 564fd4e5da5Sopenharmony_ci%4 = OpLabel 565fd4e5da5Sopenharmony_ciOpBranch %3 566fd4e5da5Sopenharmony_ci%7 = OpLabel 567fd4e5da5Sopenharmony_ciOpBranch %1 568fd4e5da5Sopenharmony_ci%3 = OpLabel 569fd4e5da5Sopenharmony_ciOpReturn 570fd4e5da5Sopenharmony_ciOpFunctionEnd 571fd4e5da5Sopenharmony_ci)"; 572fd4e5da5Sopenharmony_ci 573fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 574fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 575fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 576fd4e5da5Sopenharmony_ci 577fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 578fd4e5da5Sopenharmony_ci 579fd4e5da5Sopenharmony_ci // The outer loop header is not in either construct. 580fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 581fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 582fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 583fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 584fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 585fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 586fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 587fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 588fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 589fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 590fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 591fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 592fd4e5da5Sopenharmony_ci 593fd4e5da5Sopenharmony_ci // The inner loop header is in the outer loop. 594fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 595fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 1); 596fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 597fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 598fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 3); 599fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 1); 600fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 601fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 602fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 603fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 604fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 605fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 606fd4e5da5Sopenharmony_ci 607fd4e5da5Sopenharmony_ci // The outer merge node is not in either construct. 608fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 609fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 610fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 611fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 612fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 613fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 614fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 615fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 616fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 617fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 618fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 619fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 620fd4e5da5Sopenharmony_ci 621fd4e5da5Sopenharmony_ci // The inner merge is in the outer loop. 622fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 623fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 1); 624fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 625fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 626fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 3); 627fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 1); 628fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 629fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 630fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 631fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); 632fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(4)); 633fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 634fd4e5da5Sopenharmony_ci 635fd4e5da5Sopenharmony_ci // The inner continue target is in the inner loop. 636fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 637fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 2); 638fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 639fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 640fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 4); 641fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 2); 642fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 643fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 644fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(5)); 645fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); 646fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(5)); 647fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 648fd4e5da5Sopenharmony_ci 649fd4e5da5Sopenharmony_ci // BB6 is in the loop. 650fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(6), 2); 651fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(6), 2); 652fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(6), 4); 653fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(6), 2); 654fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(6), 4); 655fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(6), 2); 656fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(6), 0); 657fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); 658fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(6)); 659fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); 660fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(6)); 661fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(6)); 662fd4e5da5Sopenharmony_ci 663fd4e5da5Sopenharmony_ci // The outer continue target is in the outer loop. 664fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(7), 1); 665fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(7), 1); 666fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(7), 3); 667fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(7), 1); 668fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(7), 3); 669fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(7), 1); 670fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(7), 0); 671fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(7), 0); 672fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(7)); 673fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(7)); 674fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(7)); 675fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(7)); 676fd4e5da5Sopenharmony_ci} 677fd4e5da5Sopenharmony_ci 678fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, KernelTest) { 679fd4e5da5Sopenharmony_ci const std::string text = R"( 680fd4e5da5Sopenharmony_ciOpCapability Kernel 681fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 682fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 683fd4e5da5Sopenharmony_ci%void = OpTypeVoid 684fd4e5da5Sopenharmony_ci%bool = OpTypeBool 685fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 686fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 687fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 688fd4e5da5Sopenharmony_ci%1 = OpLabel 689fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 690fd4e5da5Sopenharmony_ci%2 = OpLabel 691fd4e5da5Sopenharmony_ciOpBranch %3 692fd4e5da5Sopenharmony_ci%3 = OpLabel 693fd4e5da5Sopenharmony_ciOpReturn 694fd4e5da5Sopenharmony_ciOpFunctionEnd 695fd4e5da5Sopenharmony_ci)"; 696fd4e5da5Sopenharmony_ci 697fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 698fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 699fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 700fd4e5da5Sopenharmony_ci 701fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 702fd4e5da5Sopenharmony_ci 703fd4e5da5Sopenharmony_ci // No structured control flow, so none of the basic block are in any 704fd4e5da5Sopenharmony_ci // construct. 705fd4e5da5Sopenharmony_ci for (uint32_t i = 1; i <= 3; i++) { 706fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(i), 0); 707fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(i), 0); 708fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(i), 0); 709fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(i), 0); 710fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(i), 0); 711fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(i), 0); 712fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(i), 0); 713fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(i), 0); 714fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(i)); 715fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(i)); 716fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(i)); 717fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(i)); 718fd4e5da5Sopenharmony_ci } 719fd4e5da5Sopenharmony_ci} 720fd4e5da5Sopenharmony_ci 721fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, EmptyFunctionTest) { 722fd4e5da5Sopenharmony_ci const std::string text = R"( 723fd4e5da5Sopenharmony_ciOpCapability Shader 724fd4e5da5Sopenharmony_ciOpCapability Linkage 725fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 726fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "x" Import 727fd4e5da5Sopenharmony_ci%void = OpTypeVoid 728fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void 729fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn 730fd4e5da5Sopenharmony_ciOpFunctionEnd 731fd4e5da5Sopenharmony_ci)"; 732fd4e5da5Sopenharmony_ci 733fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 734fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 735fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 736fd4e5da5Sopenharmony_ci 737fd4e5da5Sopenharmony_ci // #2451: This segfaulted on empty functions. 738fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 739fd4e5da5Sopenharmony_ci} 740fd4e5da5Sopenharmony_ci 741fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, BBInSwitch) { 742fd4e5da5Sopenharmony_ci const std::string text = R"( 743fd4e5da5Sopenharmony_ciOpCapability Shader 744fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 745fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 746fd4e5da5Sopenharmony_ci%void = OpTypeVoid 747fd4e5da5Sopenharmony_ci%bool = OpTypeBool 748fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 749fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 750fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 751fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 752fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 753fd4e5da5Sopenharmony_ci%1 = OpLabel 754fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 755fd4e5da5Sopenharmony_ciOpSwitch %uint_undef %2 0 %3 756fd4e5da5Sopenharmony_ci%2 = OpLabel 757fd4e5da5Sopenharmony_ciOpBranch %3 758fd4e5da5Sopenharmony_ci%3 = OpLabel 759fd4e5da5Sopenharmony_ciOpReturn 760fd4e5da5Sopenharmony_ciOpFunctionEnd 761fd4e5da5Sopenharmony_ci)"; 762fd4e5da5Sopenharmony_ci 763fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 764fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 765fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 766fd4e5da5Sopenharmony_ci 767fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 768fd4e5da5Sopenharmony_ci 769fd4e5da5Sopenharmony_ci // The header is not in the construct. 770fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 771fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 772fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 773fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 774fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 775fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 776fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 777fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 778fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 779fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 780fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 781fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 782fd4e5da5Sopenharmony_ci 783fd4e5da5Sopenharmony_ci // BB2 is in the construct. 784fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 785fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 786fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 787fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 788fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 789fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 790fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 1); 791fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 3); 792fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 793fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 794fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 795fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 796fd4e5da5Sopenharmony_ci 797fd4e5da5Sopenharmony_ci // The merge node is not in the construct. 798fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 799fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 800fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 801fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 802fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 803fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 804fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 805fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 806fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 807fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 808fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 809fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 810fd4e5da5Sopenharmony_ci} 811fd4e5da5Sopenharmony_ci 812fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, LoopInSwitch) { 813fd4e5da5Sopenharmony_ci const std::string text = R"( 814fd4e5da5Sopenharmony_ciOpCapability Shader 815fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 816fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 817fd4e5da5Sopenharmony_ci%void = OpTypeVoid 818fd4e5da5Sopenharmony_ci%bool = OpTypeBool 819fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 820fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 821fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 822fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 823fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 824fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 825fd4e5da5Sopenharmony_ciOpBranch %1 826fd4e5da5Sopenharmony_ci%1 = OpLabel 827fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 828fd4e5da5Sopenharmony_ciOpSwitch %uint_undef %2 1 %3 829fd4e5da5Sopenharmony_ci%2 = OpLabel 830fd4e5da5Sopenharmony_ciOpLoopMerge %4 %5 None 831fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %4 %6 832fd4e5da5Sopenharmony_ci%5 = OpLabel 833fd4e5da5Sopenharmony_ciOpBranch %2 834fd4e5da5Sopenharmony_ci%6 = OpLabel 835fd4e5da5Sopenharmony_ciOpBranch %4 836fd4e5da5Sopenharmony_ci%4 = OpLabel 837fd4e5da5Sopenharmony_ciOpBranch %3 838fd4e5da5Sopenharmony_ci%3 = OpLabel 839fd4e5da5Sopenharmony_ciOpReturn 840fd4e5da5Sopenharmony_ciOpFunctionEnd 841fd4e5da5Sopenharmony_ci)"; 842fd4e5da5Sopenharmony_ci 843fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 844fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 845fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 846fd4e5da5Sopenharmony_ci 847fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 848fd4e5da5Sopenharmony_ci 849fd4e5da5Sopenharmony_ci // The selection header is not in either construct. 850fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 851fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 852fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 853fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 854fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 855fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 856fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 857fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 858fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 859fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 860fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 861fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 862fd4e5da5Sopenharmony_ci 863fd4e5da5Sopenharmony_ci // Loop header is in the selection only. 864fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 865fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 866fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 867fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 868fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 869fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 870fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 1); 871fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 3); 872fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 873fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 874fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 875fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 876fd4e5da5Sopenharmony_ci 877fd4e5da5Sopenharmony_ci // The selection merge node is not in either construct. 878fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 879fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 880fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 881fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 882fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 883fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 884fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 885fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 886fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 887fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 888fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 889fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 890fd4e5da5Sopenharmony_ci 891fd4e5da5Sopenharmony_ci // The loop merge is in the selection only. 892fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 893fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 0); 894fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 895fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 896fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 0); 897fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 0); 898fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 1); 899fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 3); 900fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 901fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); 902fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(4)); 903fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 904fd4e5da5Sopenharmony_ci 905fd4e5da5Sopenharmony_ci // The loop continue target is in the loop. 906fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 907fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 2); 908fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 909fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 910fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 4); 911fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 1); 912fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 913fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 914fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(5)); 915fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); 916fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(5)); 917fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 918fd4e5da5Sopenharmony_ci 919fd4e5da5Sopenharmony_ci // BB6 is in the loop. 920fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(6), 2); 921fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(6), 2); 922fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(6), 4); 923fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(6), 2); 924fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(6), 4); 925fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(6), 1); 926fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(6), 0); 927fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); 928fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(6)); 929fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); 930fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(6)); 931fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(6)); 932fd4e5da5Sopenharmony_ci} 933fd4e5da5Sopenharmony_ci 934fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, SelectionInSwitch) { 935fd4e5da5Sopenharmony_ci const std::string text = R"( 936fd4e5da5Sopenharmony_ciOpCapability Shader 937fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 938fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 939fd4e5da5Sopenharmony_ci%void = OpTypeVoid 940fd4e5da5Sopenharmony_ci%bool = OpTypeBool 941fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 942fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 943fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 944fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 945fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 946fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 947fd4e5da5Sopenharmony_ciOpBranch %1 948fd4e5da5Sopenharmony_ci%1 = OpLabel 949fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 950fd4e5da5Sopenharmony_ciOpSwitch %uint_undef %2 10 %3 951fd4e5da5Sopenharmony_ci%2 = OpLabel 952fd4e5da5Sopenharmony_ciOpSelectionMerge %4 None 953fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %4 %5 954fd4e5da5Sopenharmony_ci%5 = OpLabel 955fd4e5da5Sopenharmony_ciOpBranch %4 956fd4e5da5Sopenharmony_ci%4 = OpLabel 957fd4e5da5Sopenharmony_ciOpBranch %3 958fd4e5da5Sopenharmony_ci%3 = OpLabel 959fd4e5da5Sopenharmony_ciOpReturn 960fd4e5da5Sopenharmony_ciOpFunctionEnd 961fd4e5da5Sopenharmony_ci)"; 962fd4e5da5Sopenharmony_ci 963fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 964fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 965fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 966fd4e5da5Sopenharmony_ci 967fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 968fd4e5da5Sopenharmony_ci 969fd4e5da5Sopenharmony_ci // The outer selection header is not in either construct. 970fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 971fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 972fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 973fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 974fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 975fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 976fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 977fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 978fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 979fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 980fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 981fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 982fd4e5da5Sopenharmony_ci 983fd4e5da5Sopenharmony_ci // The inner header is in the outer selection. 984fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 985fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 986fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 987fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 988fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 989fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 990fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 1); 991fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 3); 992fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 993fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 994fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 995fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 996fd4e5da5Sopenharmony_ci 997fd4e5da5Sopenharmony_ci // The outer merge node is not in either construct. 998fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 999fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 1000fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 1001fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 1002fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 1003fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 1004fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 1005fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 1006fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 1007fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 1008fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 1009fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 1010fd4e5da5Sopenharmony_ci 1011fd4e5da5Sopenharmony_ci // The inner merge is in the outer selection. 1012fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 1013fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 0); 1014fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 1015fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 1016fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 0); 1017fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 0); 1018fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 1); 1019fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 3); 1020fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 1021fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); 1022fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(4)); 1023fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 1024fd4e5da5Sopenharmony_ci 1025fd4e5da5Sopenharmony_ci // BB5 is in the inner selection. 1026fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 1027fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 0); 1028fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 1029fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 1030fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 0); 1031fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 0); 1032fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 1); 1033fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 3); 1034fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(5)); 1035fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); 1036fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(5)); 1037fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 1038fd4e5da5Sopenharmony_ci} 1039fd4e5da5Sopenharmony_ci 1040fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, SwitchInSelection) { 1041fd4e5da5Sopenharmony_ci const std::string text = R"( 1042fd4e5da5Sopenharmony_ciOpCapability Shader 1043fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 1044fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 1045fd4e5da5Sopenharmony_ci%void = OpTypeVoid 1046fd4e5da5Sopenharmony_ci%bool = OpTypeBool 1047fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 1048fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 1049fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 1050fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 1051fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 1052fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 1053fd4e5da5Sopenharmony_ciOpBranch %1 1054fd4e5da5Sopenharmony_ci%1 = OpLabel 1055fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None 1056fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 1057fd4e5da5Sopenharmony_ci%2 = OpLabel 1058fd4e5da5Sopenharmony_ciOpSelectionMerge %4 None 1059fd4e5da5Sopenharmony_ciOpSwitch %uint_undef %4 7 %5 1060fd4e5da5Sopenharmony_ci%5 = OpLabel 1061fd4e5da5Sopenharmony_ciOpBranch %4 1062fd4e5da5Sopenharmony_ci%4 = OpLabel 1063fd4e5da5Sopenharmony_ciOpBranch %3 1064fd4e5da5Sopenharmony_ci%3 = OpLabel 1065fd4e5da5Sopenharmony_ciOpReturn 1066fd4e5da5Sopenharmony_ciOpFunctionEnd 1067fd4e5da5Sopenharmony_ci)"; 1068fd4e5da5Sopenharmony_ci 1069fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1070fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1071fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1072fd4e5da5Sopenharmony_ci 1073fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 1074fd4e5da5Sopenharmony_ci 1075fd4e5da5Sopenharmony_ci // The outer selection header is not in either construct. 1076fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 1077fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 1078fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 1079fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 1080fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 1081fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 1082fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 1083fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 1084fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 1085fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 1086fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 1087fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 1088fd4e5da5Sopenharmony_ci 1089fd4e5da5Sopenharmony_ci // The inner header is in the outer selection. 1090fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 1091fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 0); 1092fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 1093fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 1094fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 0); 1095fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 0); 1096fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 1097fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 1098fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 1099fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 1100fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 1101fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 1102fd4e5da5Sopenharmony_ci 1103fd4e5da5Sopenharmony_ci // The outer merge node is not in either construct. 1104fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 1105fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 1106fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 1107fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 1108fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 1109fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 1110fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 1111fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 1112fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 1113fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 1114fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 1115fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 1116fd4e5da5Sopenharmony_ci 1117fd4e5da5Sopenharmony_ci // The inner merge is in the outer selection. 1118fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 1119fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 0); 1120fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 1121fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 1122fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 0); 1123fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 0); 1124fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 1125fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 1126fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 1127fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(4)); 1128fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(4)); 1129fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 1130fd4e5da5Sopenharmony_ci 1131fd4e5da5Sopenharmony_ci // BB5 is in the inner selection. 1132fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 2); 1133fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 0); 1134fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 1135fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 1136fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 0); 1137fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 0); 1138fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 2); 1139fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 4); 1140fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(5)); 1141fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(5)); 1142fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(5)); 1143fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 1144fd4e5da5Sopenharmony_ci} 1145fd4e5da5Sopenharmony_ci 1146fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, SelectionInContinue) { 1147fd4e5da5Sopenharmony_ci const std::string text = R"( 1148fd4e5da5Sopenharmony_ciOpCapability Shader 1149fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 1150fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 1151fd4e5da5Sopenharmony_ci%void = OpTypeVoid 1152fd4e5da5Sopenharmony_ci%bool = OpTypeBool 1153fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 1154fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 1155fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 1156fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 1157fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 1158fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 1159fd4e5da5Sopenharmony_ciOpBranch %1 1160fd4e5da5Sopenharmony_ci%1 = OpLabel 1161fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None 1162fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 1163fd4e5da5Sopenharmony_ci%2 = OpLabel 1164fd4e5da5Sopenharmony_ciOpBranch %3 1165fd4e5da5Sopenharmony_ci%4 = OpLabel 1166fd4e5da5Sopenharmony_ciOpSelectionMerge %6 None 1167fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %5 %6 1168fd4e5da5Sopenharmony_ci%5 = OpLabel 1169fd4e5da5Sopenharmony_ciOpBranch %6 1170fd4e5da5Sopenharmony_ci%6 = OpLabel 1171fd4e5da5Sopenharmony_ciOpBranch %1 1172fd4e5da5Sopenharmony_ci%3 = OpLabel 1173fd4e5da5Sopenharmony_ciOpReturn 1174fd4e5da5Sopenharmony_ciOpFunctionEnd 1175fd4e5da5Sopenharmony_ci)"; 1176fd4e5da5Sopenharmony_ci 1177fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1178fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1179fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1180fd4e5da5Sopenharmony_ci 1181fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 1182fd4e5da5Sopenharmony_ci 1183fd4e5da5Sopenharmony_ci // The loop header is not in either construct. 1184fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 1185fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 1186fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 1187fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 1188fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 1189fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 1190fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 1191fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 1192fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 1193fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 1194fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 1195fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 1196fd4e5da5Sopenharmony_ci 1197fd4e5da5Sopenharmony_ci // Selection header is in the loop only. 1198fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 1199fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 1); 1200fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 1201fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 1202fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 3); 1203fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 1); 1204fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 1205fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 1206fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 1207fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 1208fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 1209fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 1210fd4e5da5Sopenharmony_ci 1211fd4e5da5Sopenharmony_ci // The loop merge node is not in either construct. 1212fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 1213fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 1214fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 1215fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 1216fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 1217fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 1218fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 1219fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 1220fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 1221fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 1222fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 1223fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 1224fd4e5da5Sopenharmony_ci 1225fd4e5da5Sopenharmony_ci // The continue block is in the loop only. 1226fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 1227fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 1); 1228fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 1229fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 1230fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 3); 1231fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 1); 1232fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 1233fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 1234fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(4)); 1235fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); 1236fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(4)); 1237fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(4)); 1238fd4e5da5Sopenharmony_ci 1239fd4e5da5Sopenharmony_ci // BB5 is in the selection and the continue for the loop. 1240fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 4); 1241fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 1); 1242fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 6); 1243fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 1244fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 3); 1245fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 1); 1246fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 1247fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 1248fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(5)); 1249fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); 1250fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(5)); 1251fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 1252fd4e5da5Sopenharmony_ci 1253fd4e5da5Sopenharmony_ci // BB5 is in the continue for the loop. 1254fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(6), 1); 1255fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(6), 1); 1256fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(6), 3); 1257fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(6), 1); 1258fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(6), 3); 1259fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(6), 1); 1260fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(6), 0); 1261fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); 1262fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(6)); 1263fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(6)); 1264fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(6)); 1265fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(6)); 1266fd4e5da5Sopenharmony_ci} 1267fd4e5da5Sopenharmony_ci 1268fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, LoopInContinue) { 1269fd4e5da5Sopenharmony_ci const std::string text = R"( 1270fd4e5da5Sopenharmony_ciOpCapability Shader 1271fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 1272fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 1273fd4e5da5Sopenharmony_ci%void = OpTypeVoid 1274fd4e5da5Sopenharmony_ci%bool = OpTypeBool 1275fd4e5da5Sopenharmony_ci%bool_undef = OpUndef %bool 1276fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 1277fd4e5da5Sopenharmony_ci%uint_undef = OpUndef %uint 1278fd4e5da5Sopenharmony_ci%void_func = OpTypeFunction %void 1279fd4e5da5Sopenharmony_ci%main = OpFunction %void None %void_func 1280fd4e5da5Sopenharmony_ci%entry_lab = OpLabel 1281fd4e5da5Sopenharmony_ciOpBranch %1 1282fd4e5da5Sopenharmony_ci%1 = OpLabel 1283fd4e5da5Sopenharmony_ciOpLoopMerge %3 %7 None 1284fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %2 %3 1285fd4e5da5Sopenharmony_ci%2 = OpLabel 1286fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %3 %7 1287fd4e5da5Sopenharmony_ci%7 = OpLabel 1288fd4e5da5Sopenharmony_ciOpLoopMerge %4 %5 None 1289fd4e5da5Sopenharmony_ciOpBranchConditional %undef_bool %4 %6 1290fd4e5da5Sopenharmony_ci%5 = OpLabel 1291fd4e5da5Sopenharmony_ciOpBranch %7 1292fd4e5da5Sopenharmony_ci%6 = OpLabel 1293fd4e5da5Sopenharmony_ciOpBranch %4 1294fd4e5da5Sopenharmony_ci%4 = OpLabel 1295fd4e5da5Sopenharmony_ciOpBranch %1 1296fd4e5da5Sopenharmony_ci%3 = OpLabel 1297fd4e5da5Sopenharmony_ciOpReturn 1298fd4e5da5Sopenharmony_ciOpFunctionEnd 1299fd4e5da5Sopenharmony_ci)"; 1300fd4e5da5Sopenharmony_ci 1301fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1302fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1303fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1304fd4e5da5Sopenharmony_ci 1305fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 1306fd4e5da5Sopenharmony_ci 1307fd4e5da5Sopenharmony_ci // The outer loop header is not in either construct. 1308fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(1), 0); 1309fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(1), 0); 1310fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(1), 0); 1311fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(1), 0); 1312fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(1), 0); 1313fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(1), 0); 1314fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(1), 0); 1315fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(1), 0); 1316fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(1)); 1317fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(1)); 1318fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(1)); 1319fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(1)); 1320fd4e5da5Sopenharmony_ci 1321fd4e5da5Sopenharmony_ci // BB2 is a regular block in the inner loop. 1322fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(2), 1); 1323fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(2), 1); 1324fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(2), 3); 1325fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(2), 1); 1326fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(2), 3); 1327fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(2), 1); 1328fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(2), 0); 1329fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(2), 0); 1330fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(2)); 1331fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(2)); 1332fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(2)); 1333fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(2)); 1334fd4e5da5Sopenharmony_ci 1335fd4e5da5Sopenharmony_ci // The outer merge node is not in either construct. 1336fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(3), 0); 1337fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(3), 0); 1338fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(3), 0); 1339fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(3), 0); 1340fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(3), 0); 1341fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(3), 0); 1342fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(3), 0); 1343fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(3), 0); 1344fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(3)); 1345fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(3)); 1346fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContinueConstruct(3)); 1347fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(3)); 1348fd4e5da5Sopenharmony_ci 1349fd4e5da5Sopenharmony_ci // The inner merge is in the continue of the outer loop. 1350fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(4), 1); 1351fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(4), 1); 1352fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(4), 3); 1353fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(4), 1); 1354fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(4), 3); 1355fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(4), 1); 1356fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(4), 0); 1357fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(4), 0); 1358fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(4)); 1359fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(4)); 1360fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(4)); 1361fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsMergeBlock(4)); 1362fd4e5da5Sopenharmony_ci 1363fd4e5da5Sopenharmony_ci // The inner continue target is in the inner loop. 1364fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(5), 7); 1365fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(5), 7); 1366fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(5), 4); 1367fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(5), 2); 1368fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(5), 4); 1369fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(5), 2); 1370fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(5), 0); 1371fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(5), 0); 1372fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(5)); 1373fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(5)); 1374fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(5)); 1375fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(5)); 1376fd4e5da5Sopenharmony_ci 1377fd4e5da5Sopenharmony_ci // BB6 is a regular block in the inner loop. 1378fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(6), 7); 1379fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(6), 7); 1380fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(6), 4); 1381fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(6), 2); 1382fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(6), 4); 1383fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(6), 2); 1384fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(6), 0); 1385fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(6), 0); 1386fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsContinueBlock(6)); 1387fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsInContainingLoopsContinueConstruct(6)); 1388fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(6)); 1389fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(6)); 1390fd4e5da5Sopenharmony_ci 1391fd4e5da5Sopenharmony_ci // The outer continue target is in the outer loop. 1392fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingConstruct(7), 1); 1393fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingLoop(7), 1); 1394fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.MergeBlock(7), 3); 1395fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.NestingDepth(7), 1); 1396fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopMergeBlock(7), 3); 1397fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.LoopNestingDepth(7), 1); 1398fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.ContainingSwitch(7), 0); 1399fd4e5da5Sopenharmony_ci EXPECT_EQ(analysis.SwitchMergeBlock(7), 0); 1400fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsContinueBlock(7)); 1401fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContainingLoopsContinueConstruct(7)); 1402fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(7)); 1403fd4e5da5Sopenharmony_ci EXPECT_FALSE(analysis.IsMergeBlock(7)); 1404fd4e5da5Sopenharmony_ci} 1405fd4e5da5Sopenharmony_ci 1406fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, FuncCallInContinueDirect) { 1407fd4e5da5Sopenharmony_ci const std::string text = R"( 1408fd4e5da5Sopenharmony_ci OpCapability Shader 1409fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1410fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %1 "main" 1411fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1412fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1413fd4e5da5Sopenharmony_ci %4 = OpUndef %bool 1414fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1415fd4e5da5Sopenharmony_ci %6 = OpUndef %uint 1416fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %void 1417fd4e5da5Sopenharmony_ci %1 = OpFunction %void None %7 1418fd4e5da5Sopenharmony_ci %8 = OpLabel 1419fd4e5da5Sopenharmony_ci OpBranch %9 1420fd4e5da5Sopenharmony_ci %9 = OpLabel 1421fd4e5da5Sopenharmony_ci OpLoopMerge %10 %11 None 1422fd4e5da5Sopenharmony_ci OpBranchConditional %12 %10 %11 1423fd4e5da5Sopenharmony_ci %11 = OpLabel 1424fd4e5da5Sopenharmony_ci %13 = OpFunctionCall %void %14 1425fd4e5da5Sopenharmony_ci OpBranch %9 1426fd4e5da5Sopenharmony_ci %10 = OpLabel 1427fd4e5da5Sopenharmony_ci %15 = OpFunctionCall %void %16 1428fd4e5da5Sopenharmony_ci OpReturn 1429fd4e5da5Sopenharmony_ci OpFunctionEnd 1430fd4e5da5Sopenharmony_ci %14 = OpFunction %void None %7 1431fd4e5da5Sopenharmony_ci %17 = OpLabel 1432fd4e5da5Sopenharmony_ci OpReturn 1433fd4e5da5Sopenharmony_ci OpFunctionEnd 1434fd4e5da5Sopenharmony_ci %16 = OpFunction %void None %7 1435fd4e5da5Sopenharmony_ci %18 = OpLabel 1436fd4e5da5Sopenharmony_ci OpReturn 1437fd4e5da5Sopenharmony_ci OpFunctionEnd 1438fd4e5da5Sopenharmony_ci)"; 1439fd4e5da5Sopenharmony_ci 1440fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1441fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1442fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1443fd4e5da5Sopenharmony_ci 1444fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 1445fd4e5da5Sopenharmony_ci 1446fd4e5da5Sopenharmony_ci auto c = analysis.FindFuncsCalledFromContinue(); 1447fd4e5da5Sopenharmony_ci EXPECT_THAT(c, UnorderedElementsAre(14u)); 1448fd4e5da5Sopenharmony_ci} 1449fd4e5da5Sopenharmony_ci 1450fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, FuncCallInContinueIndirect) { 1451fd4e5da5Sopenharmony_ci const std::string text = R"( 1452fd4e5da5Sopenharmony_ci OpCapability Shader 1453fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1454fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %1 "main" 1455fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1456fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1457fd4e5da5Sopenharmony_ci %4 = OpUndef %bool 1458fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1459fd4e5da5Sopenharmony_ci %6 = OpUndef %uint 1460fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %void 1461fd4e5da5Sopenharmony_ci %1 = OpFunction %void None %7 1462fd4e5da5Sopenharmony_ci %8 = OpLabel 1463fd4e5da5Sopenharmony_ci OpBranch %9 1464fd4e5da5Sopenharmony_ci %9 = OpLabel 1465fd4e5da5Sopenharmony_ci OpLoopMerge %10 %11 None 1466fd4e5da5Sopenharmony_ci OpBranchConditional %12 %10 %11 1467fd4e5da5Sopenharmony_ci %11 = OpLabel 1468fd4e5da5Sopenharmony_ci %13 = OpFunctionCall %void %14 1469fd4e5da5Sopenharmony_ci OpBranch %9 1470fd4e5da5Sopenharmony_ci %10 = OpLabel 1471fd4e5da5Sopenharmony_ci %15 = OpFunctionCall %void %16 1472fd4e5da5Sopenharmony_ci OpReturn 1473fd4e5da5Sopenharmony_ci OpFunctionEnd 1474fd4e5da5Sopenharmony_ci %14 = OpFunction %void None %7 1475fd4e5da5Sopenharmony_ci %17 = OpLabel 1476fd4e5da5Sopenharmony_ci %19 = OpFunctionCall %void %16 1477fd4e5da5Sopenharmony_ci OpReturn 1478fd4e5da5Sopenharmony_ci OpFunctionEnd 1479fd4e5da5Sopenharmony_ci %16 = OpFunction %void None %7 1480fd4e5da5Sopenharmony_ci %18 = OpLabel 1481fd4e5da5Sopenharmony_ci %20 = OpFunctionCall %void %21 1482fd4e5da5Sopenharmony_ci OpReturn 1483fd4e5da5Sopenharmony_ci OpFunctionEnd 1484fd4e5da5Sopenharmony_ci %21 = OpFunction %void None %7 1485fd4e5da5Sopenharmony_ci %22 = OpLabel 1486fd4e5da5Sopenharmony_ci OpReturn 1487fd4e5da5Sopenharmony_ci OpFunctionEnd 1488fd4e5da5Sopenharmony_ci)"; 1489fd4e5da5Sopenharmony_ci 1490fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1491fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1492fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1493fd4e5da5Sopenharmony_ci 1494fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 1495fd4e5da5Sopenharmony_ci 1496fd4e5da5Sopenharmony_ci auto c = analysis.FindFuncsCalledFromContinue(); 1497fd4e5da5Sopenharmony_ci EXPECT_THAT(c, UnorderedElementsAre(14u, 16u, 21u)); 1498fd4e5da5Sopenharmony_ci} 1499fd4e5da5Sopenharmony_ci 1500fd4e5da5Sopenharmony_ciTEST_F(StructCFGAnalysisTest, SingleBlockLoop) { 1501fd4e5da5Sopenharmony_ci const std::string text = R"( 1502fd4e5da5Sopenharmony_ci OpCapability Shader 1503fd4e5da5Sopenharmony_ci OpCapability Linkage 1504fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1505fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1506fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1507fd4e5da5Sopenharmony_ci %undef = OpUndef %bool 1508fd4e5da5Sopenharmony_ci %void_fn = OpTypeFunction %void 1509fd4e5da5Sopenharmony_ci %main = OpFunction %void None %void_fn 1510fd4e5da5Sopenharmony_ci %2 = OpLabel 1511fd4e5da5Sopenharmony_ci OpBranch %3 1512fd4e5da5Sopenharmony_ci %3 = OpLabel 1513fd4e5da5Sopenharmony_ci OpLoopMerge %4 %3 None 1514fd4e5da5Sopenharmony_ci OpBranchConditional %undef %3 %4 1515fd4e5da5Sopenharmony_ci %4 = OpLabel 1516fd4e5da5Sopenharmony_ci OpReturn 1517fd4e5da5Sopenharmony_ci OpFunctionEnd 1518fd4e5da5Sopenharmony_ci)"; 1519fd4e5da5Sopenharmony_ci 1520fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 1521fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 1522fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1523fd4e5da5Sopenharmony_ci 1524fd4e5da5Sopenharmony_ci StructuredCFGAnalysis analysis(context.get()); 1525fd4e5da5Sopenharmony_ci 1526fd4e5da5Sopenharmony_ci EXPECT_TRUE(analysis.IsInContinueConstruct(3)); 1527fd4e5da5Sopenharmony_ci} 1528fd4e5da5Sopenharmony_ci} // namespace 1529fd4e5da5Sopenharmony_ci} // namespace opt 1530fd4e5da5Sopenharmony_ci} // namespace spvtools 1531