1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc. 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 <string> 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 18fd4e5da5Sopenharmony_ci#include "source/opt/ccp_pass.h" 19fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 20fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_cinamespace spvtools { 23fd4e5da5Sopenharmony_cinamespace opt { 24fd4e5da5Sopenharmony_cinamespace { 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_ciusing CCPTest = PassTest<::testing::Test>; 27fd4e5da5Sopenharmony_ci 28fd4e5da5Sopenharmony_ciTEST_F(CCPTest, PropagateThroughPhis) { 29fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 30fd4e5da5Sopenharmony_ci OpCapability Shader 31fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 32fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 33fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %x %outparm 34fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 35fd4e5da5Sopenharmony_ci OpSource GLSL 450 36fd4e5da5Sopenharmony_ci OpName %main "main" 37fd4e5da5Sopenharmony_ci OpName %x "x" 38fd4e5da5Sopenharmony_ci OpName %outparm "outparm" 39fd4e5da5Sopenharmony_ci OpDecorate %x Flat 40fd4e5da5Sopenharmony_ci OpDecorate %x Location 0 41fd4e5da5Sopenharmony_ci OpDecorate %outparm Location 0 42fd4e5da5Sopenharmony_ci %void = OpTypeVoid 43fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 44fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 45fd4e5da5Sopenharmony_ci %bool = OpTypeBool 46fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 47fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 48fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 49fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 50fd4e5da5Sopenharmony_ci%_ptr_Input_int = OpTypePointer Input %int 51fd4e5da5Sopenharmony_ci %x = OpVariable %_ptr_Input_int Input 52fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 53fd4e5da5Sopenharmony_ci %outparm = OpVariable %_ptr_Output_int Output 54fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 55fd4e5da5Sopenharmony_ci %4 = OpLabel 56fd4e5da5Sopenharmony_ci %5 = OpLoad %int %x 57fd4e5da5Sopenharmony_ci %9 = OpIAdd %int %int_1 %int_3 58fd4e5da5Sopenharmony_ci %6 = OpSGreaterThan %bool %5 %int_3 59fd4e5da5Sopenharmony_ci OpSelectionMerge %25 None 60fd4e5da5Sopenharmony_ci OpBranchConditional %6 %22 %23 61fd4e5da5Sopenharmony_ci %22 = OpLabel 62fd4e5da5Sopenharmony_ci 63fd4e5da5Sopenharmony_ci; CHECK: OpCopyObject %int %int_4 64fd4e5da5Sopenharmony_ci %7 = OpCopyObject %int %9 65fd4e5da5Sopenharmony_ci 66fd4e5da5Sopenharmony_ci OpBranch %25 67fd4e5da5Sopenharmony_ci %23 = OpLabel 68fd4e5da5Sopenharmony_ci %8 = OpCopyObject %int %int_4 69fd4e5da5Sopenharmony_ci OpBranch %25 70fd4e5da5Sopenharmony_ci %25 = OpLabel 71fd4e5da5Sopenharmony_ci 72fd4e5da5Sopenharmony_ci; %int_4 should have propagated to both OpPhi operands. 73fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_4 {{%\d+}} %int_4 {{%\d+}} 74fd4e5da5Sopenharmony_ci %35 = OpPhi %int %7 %22 %8 %23 75fd4e5da5Sopenharmony_ci 76fd4e5da5Sopenharmony_ci; This function always returns 4. DCE should get rid of everything else. 77fd4e5da5Sopenharmony_ci; CHECK OpStore %outparm %int_4 78fd4e5da5Sopenharmony_ci OpStore %outparm %35 79fd4e5da5Sopenharmony_ci OpReturn 80fd4e5da5Sopenharmony_ci OpFunctionEnd 81fd4e5da5Sopenharmony_ci )"; 82fd4e5da5Sopenharmony_ci 83fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 84fd4e5da5Sopenharmony_ci} 85fd4e5da5Sopenharmony_ci 86fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifyConditionals) { 87fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 88fd4e5da5Sopenharmony_ci OpCapability Shader 89fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 90fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 91fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %outparm 92fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 93fd4e5da5Sopenharmony_ci OpSource GLSL 450 94fd4e5da5Sopenharmony_ci OpName %main "main" 95fd4e5da5Sopenharmony_ci OpName %outparm "outparm" 96fd4e5da5Sopenharmony_ci OpDecorate %outparm Location 0 97fd4e5da5Sopenharmony_ci %void = OpTypeVoid 98fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 99fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 100fd4e5da5Sopenharmony_ci %bool = OpTypeBool 101fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 102fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 103fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 104fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 105fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 106fd4e5da5Sopenharmony_ci %outparm = OpVariable %_ptr_Output_int Output 107fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 108fd4e5da5Sopenharmony_ci %4 = OpLabel 109fd4e5da5Sopenharmony_ci %9 = OpIAdd %int %int_4 %int_3 110fd4e5da5Sopenharmony_ci %6 = OpSGreaterThan %bool %9 %int_3 111fd4e5da5Sopenharmony_ci OpSelectionMerge %25 None 112fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional %true [[bb_taken:%\d+]] [[bb_not_taken:%\d+]] 113fd4e5da5Sopenharmony_ci OpBranchConditional %6 %22 %23 114fd4e5da5Sopenharmony_ci; CHECK: [[bb_taken]] = OpLabel 115fd4e5da5Sopenharmony_ci %22 = OpLabel 116fd4e5da5Sopenharmony_ci; CHECK: OpCopyObject %int %int_7 117fd4e5da5Sopenharmony_ci %7 = OpCopyObject %int %9 118fd4e5da5Sopenharmony_ci OpBranch %25 119fd4e5da5Sopenharmony_ci; CHECK: [[bb_not_taken]] = OpLabel 120fd4e5da5Sopenharmony_ci %23 = OpLabel 121fd4e5da5Sopenharmony_ci; CHECK: [[id_not_evaluated:%\d+]] = OpCopyObject %int %int_4 122fd4e5da5Sopenharmony_ci %8 = OpCopyObject %int %int_4 123fd4e5da5Sopenharmony_ci OpBranch %25 124fd4e5da5Sopenharmony_ci %25 = OpLabel 125fd4e5da5Sopenharmony_ci 126fd4e5da5Sopenharmony_ci; %int_7 should have propagated to the first OpPhi operand. But the else branch 127fd4e5da5Sopenharmony_ci; is not executable (conditional is always true), so no values should be 128fd4e5da5Sopenharmony_ci; propagated there and the value of the OpPhi should always be %int_7. 129fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_7 [[bb_taken]] [[id_not_evaluated]] [[bb_not_taken]] 130fd4e5da5Sopenharmony_ci %35 = OpPhi %int %7 %22 %8 %23 131fd4e5da5Sopenharmony_ci 132fd4e5da5Sopenharmony_ci; Only the true path of the conditional is ever executed. The output of this 133fd4e5da5Sopenharmony_ci; function is always %int_7. 134fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm %int_7 135fd4e5da5Sopenharmony_ci OpStore %outparm %35 136fd4e5da5Sopenharmony_ci OpReturn 137fd4e5da5Sopenharmony_ci OpFunctionEnd 138fd4e5da5Sopenharmony_ci )"; 139fd4e5da5Sopenharmony_ci 140fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 141fd4e5da5Sopenharmony_ci} 142fd4e5da5Sopenharmony_ci 143fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifySwitches) { 144fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 145fd4e5da5Sopenharmony_ci OpCapability Shader 146fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 147fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 148fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %outparm 149fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 150fd4e5da5Sopenharmony_ci OpSource GLSL 450 151fd4e5da5Sopenharmony_ci OpName %main "main" 152fd4e5da5Sopenharmony_ci OpName %outparm "outparm" 153fd4e5da5Sopenharmony_ci OpDecorate %outparm Location 0 154fd4e5da5Sopenharmony_ci %void = OpTypeVoid 155fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %void 156fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 157fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 158fd4e5da5Sopenharmony_ci %int_23 = OpConstant %int 23 159fd4e5da5Sopenharmony_ci %int_42 = OpConstant %int 42 160fd4e5da5Sopenharmony_ci %int_14 = OpConstant %int 14 161fd4e5da5Sopenharmony_ci %int_15 = OpConstant %int 15 162fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 163fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 164fd4e5da5Sopenharmony_ci %outparm = OpVariable %_ptr_Output_int Output 165fd4e5da5Sopenharmony_ci %main = OpFunction %void None %6 166fd4e5da5Sopenharmony_ci %15 = OpLabel 167fd4e5da5Sopenharmony_ci OpSelectionMerge %17 None 168fd4e5da5Sopenharmony_ci OpSwitch %int_23 %17 10 %18 13 %19 23 %20 169fd4e5da5Sopenharmony_ci %18 = OpLabel 170fd4e5da5Sopenharmony_ci OpBranch %17 171fd4e5da5Sopenharmony_ci %19 = OpLabel 172fd4e5da5Sopenharmony_ci OpBranch %17 173fd4e5da5Sopenharmony_ci %20 = OpLabel 174fd4e5da5Sopenharmony_ci OpBranch %17 175fd4e5da5Sopenharmony_ci %17 = OpLabel 176fd4e5da5Sopenharmony_ci %24 = OpPhi %int %int_23 %15 %int_42 %18 %int_14 %19 %int_15 %20 177fd4e5da5Sopenharmony_ci 178fd4e5da5Sopenharmony_ci; The switch will always jump to label %20, which carries the value %int_15. 179fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_15 %int_4 180fd4e5da5Sopenharmony_ci %22 = OpIAdd %int %24 %int_4 181fd4e5da5Sopenharmony_ci 182fd4e5da5Sopenharmony_ci; Consequently, the return value will always be %int_19. 183fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm %int_19 184fd4e5da5Sopenharmony_ci OpStore %outparm %22 185fd4e5da5Sopenharmony_ci OpReturn 186fd4e5da5Sopenharmony_ci OpFunctionEnd 187fd4e5da5Sopenharmony_ci )"; 188fd4e5da5Sopenharmony_ci 189fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 190fd4e5da5Sopenharmony_ci} 191fd4e5da5Sopenharmony_ci 192fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifySwitchesDefaultBranch) { 193fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 194fd4e5da5Sopenharmony_ci OpCapability Shader 195fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 196fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 197fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %outparm 198fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 199fd4e5da5Sopenharmony_ci OpSource GLSL 450 200fd4e5da5Sopenharmony_ci OpName %main "main" 201fd4e5da5Sopenharmony_ci OpName %outparm "outparm" 202fd4e5da5Sopenharmony_ci OpDecorate %outparm Location 0 203fd4e5da5Sopenharmony_ci %void = OpTypeVoid 204fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %void 205fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 206fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 207fd4e5da5Sopenharmony_ci %int_42 = OpConstant %int 42 208fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 209fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 210fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 211fd4e5da5Sopenharmony_ci %outparm = OpVariable %_ptr_Output_int Output 212fd4e5da5Sopenharmony_ci %main = OpFunction %void None %6 213fd4e5da5Sopenharmony_ci %13 = OpLabel 214fd4e5da5Sopenharmony_ci %15 = OpIAdd %int %int_42 %int_4 215fd4e5da5Sopenharmony_ci OpSelectionMerge %16 None 216fd4e5da5Sopenharmony_ci 217fd4e5da5Sopenharmony_ci; CHECK: OpSwitch %int_46 {{%\d+}} 10 {{%\d+}} 218fd4e5da5Sopenharmony_ci OpSwitch %15 %17 10 %18 219fd4e5da5Sopenharmony_ci %18 = OpLabel 220fd4e5da5Sopenharmony_ci OpBranch %16 221fd4e5da5Sopenharmony_ci %17 = OpLabel 222fd4e5da5Sopenharmony_ci OpBranch %16 223fd4e5da5Sopenharmony_ci %16 = OpLabel 224fd4e5da5Sopenharmony_ci %22 = OpPhi %int %int_42 %18 %int_1 %17 225fd4e5da5Sopenharmony_ci 226fd4e5da5Sopenharmony_ci; The switch will always jump to the default label %17. This carries the value 227fd4e5da5Sopenharmony_ci; %int_1. 228fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_1 %int_4 229fd4e5da5Sopenharmony_ci %20 = OpIAdd %int %22 %int_4 230fd4e5da5Sopenharmony_ci 231fd4e5da5Sopenharmony_ci; Resulting in a return value of %int_5. 232fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm %int_5 233fd4e5da5Sopenharmony_ci OpStore %outparm %20 234fd4e5da5Sopenharmony_ci OpReturn 235fd4e5da5Sopenharmony_ci OpFunctionEnd 236fd4e5da5Sopenharmony_ci )"; 237fd4e5da5Sopenharmony_ci 238fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 239fd4e5da5Sopenharmony_ci} 240fd4e5da5Sopenharmony_ci 241fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SimplifyIntVector) { 242fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 243fd4e5da5Sopenharmony_ci OpCapability Shader 244fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 245fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 246fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %OutColor 247fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 248fd4e5da5Sopenharmony_ci OpSource GLSL 450 249fd4e5da5Sopenharmony_ci OpName %main "main" 250fd4e5da5Sopenharmony_ci OpName %v "v" 251fd4e5da5Sopenharmony_ci OpName %OutColor "OutColor" 252fd4e5da5Sopenharmony_ci OpDecorate %OutColor Location 0 253fd4e5da5Sopenharmony_ci %void = OpTypeVoid 254fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 255fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 256fd4e5da5Sopenharmony_ci %v4int = OpTypeVector %int 4 257fd4e5da5Sopenharmony_ci%_ptr_Function_v4int = OpTypePointer Function %v4int 258fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 259fd4e5da5Sopenharmony_ci %int_2 = OpConstant %int 2 260fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 261fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 262fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %v4int %int_1 %int_2 %int_3 %int_4 263fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 264fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 265fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 266fd4e5da5Sopenharmony_ci%_ptr_Output_v4int = OpTypePointer Output %v4int 267fd4e5da5Sopenharmony_ci %OutColor = OpVariable %_ptr_Output_v4int Output 268fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 269fd4e5da5Sopenharmony_ci %5 = OpLabel 270fd4e5da5Sopenharmony_ci %v = OpVariable %_ptr_Function_v4int Function 271fd4e5da5Sopenharmony_ci OpStore %v %14 272fd4e5da5Sopenharmony_ci %18 = OpAccessChain %_ptr_Function_int %v %uint_0 273fd4e5da5Sopenharmony_ci %19 = OpLoad %int %18 274fd4e5da5Sopenharmony_ci 275fd4e5da5Sopenharmony_ci; The constant folder does not see through access chains. To get this, the 276fd4e5da5Sopenharmony_ci; vector would have to be scalarized. 277fd4e5da5Sopenharmony_ci; CHECK: [[result_id:%\d+]] = OpIAdd %int {{%\d+}} %int_1 278fd4e5da5Sopenharmony_ci %20 = OpIAdd %int %19 %int_1 279fd4e5da5Sopenharmony_ci %21 = OpAccessChain %_ptr_Function_int %v %uint_0 280fd4e5da5Sopenharmony_ci 281fd4e5da5Sopenharmony_ci; CHECK: OpStore {{%\d+}} [[result_id]] 282fd4e5da5Sopenharmony_ci OpStore %21 %20 283fd4e5da5Sopenharmony_ci %24 = OpLoad %v4int %v 284fd4e5da5Sopenharmony_ci OpStore %OutColor %24 285fd4e5da5Sopenharmony_ci OpReturn 286fd4e5da5Sopenharmony_ci OpFunctionEnd 287fd4e5da5Sopenharmony_ci )"; 288fd4e5da5Sopenharmony_ci 289fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 290fd4e5da5Sopenharmony_ci} 291fd4e5da5Sopenharmony_ci 292fd4e5da5Sopenharmony_ciTEST_F(CCPTest, BadSimplifyFloatVector) { 293fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 294fd4e5da5Sopenharmony_ci OpCapability Shader 295fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 296fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 297fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %OutColor 298fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 299fd4e5da5Sopenharmony_ci OpSource GLSL 450 300fd4e5da5Sopenharmony_ci OpName %main "main" 301fd4e5da5Sopenharmony_ci OpName %v "v" 302fd4e5da5Sopenharmony_ci OpName %OutColor "OutColor" 303fd4e5da5Sopenharmony_ci OpDecorate %OutColor Location 0 304fd4e5da5Sopenharmony_ci %void = OpTypeVoid 305fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 306fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 307fd4e5da5Sopenharmony_ci %v4float = OpTypeVector %float 4 308fd4e5da5Sopenharmony_ci%_ptr_Function_v4float = OpTypePointer Function %v4float 309fd4e5da5Sopenharmony_ci %float_1 = OpConstant %float 1 310fd4e5da5Sopenharmony_ci %float_2 = OpConstant %float 2 311fd4e5da5Sopenharmony_ci %float_3 = OpConstant %float 3 312fd4e5da5Sopenharmony_ci %float_4 = OpConstant %float 4 313fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4 314fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 315fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 316fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float 317fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float 318fd4e5da5Sopenharmony_ci %OutColor = OpVariable %_ptr_Output_v4float Output 319fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 320fd4e5da5Sopenharmony_ci %5 = OpLabel 321fd4e5da5Sopenharmony_ci %v = OpVariable %_ptr_Function_v4float Function 322fd4e5da5Sopenharmony_ci OpStore %v %14 323fd4e5da5Sopenharmony_ci %18 = OpAccessChain %_ptr_Function_float %v %uint_0 324fd4e5da5Sopenharmony_ci %19 = OpLoad %float %18 325fd4e5da5Sopenharmony_ci 326fd4e5da5Sopenharmony_ci; NOTE: This test should start failing once floating point folding is 327fd4e5da5Sopenharmony_ci; implemented (https://github.com/KhronosGroup/SPIRV-Tools/issues/943). 328fd4e5da5Sopenharmony_ci; This should be checking that we are adding %float_1 + %float_1. 329fd4e5da5Sopenharmony_ci; CHECK: [[result_id:%\d+]] = OpFAdd %float {{%\d+}} %float_1 330fd4e5da5Sopenharmony_ci %20 = OpFAdd %float %19 %float_1 331fd4e5da5Sopenharmony_ci %21 = OpAccessChain %_ptr_Function_float %v %uint_0 332fd4e5da5Sopenharmony_ci 333fd4e5da5Sopenharmony_ci; This should be checkint that we are storing %float_2 instead of result_it. 334fd4e5da5Sopenharmony_ci; CHECK: OpStore {{%\d+}} [[result_id]] 335fd4e5da5Sopenharmony_ci OpStore %21 %20 336fd4e5da5Sopenharmony_ci %24 = OpLoad %v4float %v 337fd4e5da5Sopenharmony_ci OpStore %OutColor %24 338fd4e5da5Sopenharmony_ci OpReturn 339fd4e5da5Sopenharmony_ci OpFunctionEnd 340fd4e5da5Sopenharmony_ci )"; 341fd4e5da5Sopenharmony_ci 342fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 343fd4e5da5Sopenharmony_ci} 344fd4e5da5Sopenharmony_ci 345fd4e5da5Sopenharmony_ciTEST_F(CCPTest, NoLoadStorePropagation) { 346fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 347fd4e5da5Sopenharmony_ci OpCapability Shader 348fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 349fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 350fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %outparm 351fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 352fd4e5da5Sopenharmony_ci OpSource GLSL 450 353fd4e5da5Sopenharmony_ci OpName %main "main" 354fd4e5da5Sopenharmony_ci OpName %x "x" 355fd4e5da5Sopenharmony_ci OpName %outparm "outparm" 356fd4e5da5Sopenharmony_ci OpDecorate %outparm Location 0 357fd4e5da5Sopenharmony_ci %void = OpTypeVoid 358fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 359fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 360fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 361fd4e5da5Sopenharmony_ci %int_23 = OpConstant %int 23 362fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 363fd4e5da5Sopenharmony_ci %outparm = OpVariable %_ptr_Output_int Output 364fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 365fd4e5da5Sopenharmony_ci %5 = OpLabel 366fd4e5da5Sopenharmony_ci %x = OpVariable %_ptr_Function_int Function 367fd4e5da5Sopenharmony_ci OpStore %x %int_23 368fd4e5da5Sopenharmony_ci 369fd4e5da5Sopenharmony_ci; int_23 should not propagate into this load. 370fd4e5da5Sopenharmony_ci; CHECK: [[load_id:%\d+]] = OpLoad %int %x 371fd4e5da5Sopenharmony_ci %12 = OpLoad %int %x 372fd4e5da5Sopenharmony_ci 373fd4e5da5Sopenharmony_ci; Nor into this copy operation. 374fd4e5da5Sopenharmony_ci; CHECK: [[copy_id:%\d+]] = OpCopyObject %int [[load_id]] 375fd4e5da5Sopenharmony_ci %13 = OpCopyObject %int %12 376fd4e5da5Sopenharmony_ci 377fd4e5da5Sopenharmony_ci; Likewise here. 378fd4e5da5Sopenharmony_ci; CHECK: OpStore %outparm [[copy_id]] 379fd4e5da5Sopenharmony_ci OpStore %outparm %13 380fd4e5da5Sopenharmony_ci OpReturn 381fd4e5da5Sopenharmony_ci OpFunctionEnd 382fd4e5da5Sopenharmony_ci )"; 383fd4e5da5Sopenharmony_ci 384fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 385fd4e5da5Sopenharmony_ci} 386fd4e5da5Sopenharmony_ci 387fd4e5da5Sopenharmony_ciTEST_F(CCPTest, HandleAbortInstructions) { 388fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 389fd4e5da5Sopenharmony_ci OpCapability Shader 390fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 391fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 392fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 393fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 394fd4e5da5Sopenharmony_ci OpSource HLSL 500 395fd4e5da5Sopenharmony_ci OpName %main "main" 396fd4e5da5Sopenharmony_ci %void = OpTypeVoid 397fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 398fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 399fd4e5da5Sopenharmony_ci %bool = OpTypeBool 400fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool 401fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 402fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 403fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 404fd4e5da5Sopenharmony_ci %4 = OpLabel 405fd4e5da5Sopenharmony_ci %9 = OpIAdd %int %int_3 %int_1 406fd4e5da5Sopenharmony_ci %6 = OpSGreaterThan %bool %9 %int_3 407fd4e5da5Sopenharmony_ci OpSelectionMerge %23 None 408fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional %true {{%\d+}} {{%\d+}} 409fd4e5da5Sopenharmony_ci OpBranchConditional %6 %22 %23 410fd4e5da5Sopenharmony_ci %22 = OpLabel 411fd4e5da5Sopenharmony_ci OpKill 412fd4e5da5Sopenharmony_ci %23 = OpLabel 413fd4e5da5Sopenharmony_ci OpReturn 414fd4e5da5Sopenharmony_ci OpFunctionEnd 415fd4e5da5Sopenharmony_ci )"; 416fd4e5da5Sopenharmony_ci 417fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 418fd4e5da5Sopenharmony_ci} 419fd4e5da5Sopenharmony_ci 420fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SSAWebCycles) { 421fd4e5da5Sopenharmony_ci // Test reduced from https://github.com/KhronosGroup/SPIRV-Tools/issues/1159 422fd4e5da5Sopenharmony_ci // When there is a cycle in the SSA def-use web, the propagator was getting 423fd4e5da5Sopenharmony_ci // into an infinite loop. SSA edges for Phi instructions should not be 424fd4e5da5Sopenharmony_ci // added to the edges to simulate. 425fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 426fd4e5da5Sopenharmony_ci OpCapability Shader 427fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 428fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 429fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 430fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 431fd4e5da5Sopenharmony_ci OpSource GLSL 450 432fd4e5da5Sopenharmony_ci OpName %main "main" 433fd4e5da5Sopenharmony_ci %void = OpTypeVoid 434fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 435fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 436fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 437fd4e5da5Sopenharmony_ci %int_0 = OpConstant %int 0 438fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 439fd4e5da5Sopenharmony_ci %bool = OpTypeBool 440fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 441fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 442fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 443fd4e5da5Sopenharmony_ci %5 = OpLabel 444fd4e5da5Sopenharmony_ci OpBranch %11 445fd4e5da5Sopenharmony_ci %11 = OpLabel 446fd4e5da5Sopenharmony_ci %29 = OpPhi %int %int_0 %5 %22 %14 447fd4e5da5Sopenharmony_ci %30 = OpPhi %int %int_0 %5 %25 %14 448fd4e5da5Sopenharmony_ci OpLoopMerge %13 %14 None 449fd4e5da5Sopenharmony_ci OpBranch %15 450fd4e5da5Sopenharmony_ci %15 = OpLabel 451fd4e5da5Sopenharmony_ci %19 = OpSLessThan %bool %30 %int_4 452fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional %true {{%\d+}} {{%\d+}} 453fd4e5da5Sopenharmony_ci OpBranchConditional %19 %12 %13 454fd4e5da5Sopenharmony_ci %12 = OpLabel 455fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_0 %int_0 456fd4e5da5Sopenharmony_ci %22 = OpIAdd %int %29 %30 457fd4e5da5Sopenharmony_ci OpBranch %14 458fd4e5da5Sopenharmony_ci %14 = OpLabel 459fd4e5da5Sopenharmony_ci; CHECK: OpPhi %int %int_0 {{%\d+}} 460fd4e5da5Sopenharmony_ci %25 = OpPhi %int %30 %12 461fd4e5da5Sopenharmony_ci OpBranch %11 462fd4e5da5Sopenharmony_ci %13 = OpLabel 463fd4e5da5Sopenharmony_ci OpReturn 464fd4e5da5Sopenharmony_ci OpFunctionEnd 465fd4e5da5Sopenharmony_ci )"; 466fd4e5da5Sopenharmony_ci 467fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 468fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 469fd4e5da5Sopenharmony_ci} 470fd4e5da5Sopenharmony_ci 471fd4e5da5Sopenharmony_ciTEST_F(CCPTest, LoopInductionVariables) { 472fd4e5da5Sopenharmony_ci // Test reduced from https://github.com/KhronosGroup/SPIRV-Tools/issues/1143 473fd4e5da5Sopenharmony_ci // We are failing to properly consider the induction variable for this loop 474fd4e5da5Sopenharmony_ci // as Varying. 475fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 476fd4e5da5Sopenharmony_ci OpCapability Shader 477fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 478fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 479fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 480fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 481fd4e5da5Sopenharmony_ci OpSource GLSL 430 482fd4e5da5Sopenharmony_ci OpName %main "main" 483fd4e5da5Sopenharmony_ci %void = OpTypeVoid 484fd4e5da5Sopenharmony_ci %5 = OpTypeFunction %void 485fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 486fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 487fd4e5da5Sopenharmony_ci %int_0 = OpConstant %int 0 488fd4e5da5Sopenharmony_ci %int_10 = OpConstant %int 10 489fd4e5da5Sopenharmony_ci %bool = OpTypeBool 490fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 491fd4e5da5Sopenharmony_ci %main = OpFunction %void None %5 492fd4e5da5Sopenharmony_ci %12 = OpLabel 493fd4e5da5Sopenharmony_ci OpBranch %13 494fd4e5da5Sopenharmony_ci %13 = OpLabel 495fd4e5da5Sopenharmony_ci 496fd4e5da5Sopenharmony_ci; This Phi should not have all constant arguments: 497fd4e5da5Sopenharmony_ci; CHECK: [[phi_id:%\d+]] = OpPhi %int %int_0 {{%\d+}} {{%\d+}} {{%\d+}} 498fd4e5da5Sopenharmony_ci %22 = OpPhi %int %int_0 %12 %21 %15 499fd4e5da5Sopenharmony_ci OpLoopMerge %14 %15 None 500fd4e5da5Sopenharmony_ci OpBranch %16 501fd4e5da5Sopenharmony_ci %16 = OpLabel 502fd4e5da5Sopenharmony_ci 503fd4e5da5Sopenharmony_ci; The Phi should never be considered to have the value %int_0. 504fd4e5da5Sopenharmony_ci; CHECK: [[branch_selector:%\d+]] = OpSLessThan %bool [[phi_id]] %int_10 505fd4e5da5Sopenharmony_ci %18 = OpSLessThan %bool %22 %int_10 506fd4e5da5Sopenharmony_ci 507fd4e5da5Sopenharmony_ci; This conditional was wrongly converted into an always-true jump due to the 508fd4e5da5Sopenharmony_ci; bad meet evaluation of %22. 509fd4e5da5Sopenharmony_ci; CHECK: OpBranchConditional [[branch_selector]] {{%\d+}} {{%\d+}} 510fd4e5da5Sopenharmony_ci OpBranchConditional %18 %19 %14 511fd4e5da5Sopenharmony_ci %19 = OpLabel 512fd4e5da5Sopenharmony_ci OpBranch %15 513fd4e5da5Sopenharmony_ci %15 = OpLabel 514fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int [[phi_id]] %int_1 515fd4e5da5Sopenharmony_ci %21 = OpIAdd %int %22 %int_1 516fd4e5da5Sopenharmony_ci OpBranch %13 517fd4e5da5Sopenharmony_ci %14 = OpLabel 518fd4e5da5Sopenharmony_ci OpReturn 519fd4e5da5Sopenharmony_ci OpFunctionEnd 520fd4e5da5Sopenharmony_ci )"; 521fd4e5da5Sopenharmony_ci 522fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(spv_asm, true); 523fd4e5da5Sopenharmony_ci} 524fd4e5da5Sopenharmony_ci 525fd4e5da5Sopenharmony_ciTEST_F(CCPTest, HandleCompositeWithUndef) { 526fd4e5da5Sopenharmony_ci // Check to make sure that CCP does not crash when given a "constant" struct 527fd4e5da5Sopenharmony_ci // with an undef. If at a later time CCP is enhanced to optimize this case, 528fd4e5da5Sopenharmony_ci // it is not wrong. 529fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 530fd4e5da5Sopenharmony_ci OpCapability Shader 531fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 532fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 533fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 534fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 535fd4e5da5Sopenharmony_ci OpSource HLSL 500 536fd4e5da5Sopenharmony_ci OpName %main "main" 537fd4e5da5Sopenharmony_ci %void = OpTypeVoid 538fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %void 539fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 540fd4e5da5Sopenharmony_ci %bool = OpTypeBool 541fd4e5da5Sopenharmony_ci %_struct_7 = OpTypeStruct %int %int 542fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 543fd4e5da5Sopenharmony_ci %9 = OpUndef %int 544fd4e5da5Sopenharmony_ci %10 = OpConstantComposite %_struct_7 %int_1 %9 545fd4e5da5Sopenharmony_ci %main = OpFunction %void None %4 546fd4e5da5Sopenharmony_ci %11 = OpLabel 547fd4e5da5Sopenharmony_ci %12 = OpCompositeExtract %int %10 0 548fd4e5da5Sopenharmony_ci %13 = OpCopyObject %int %12 549fd4e5da5Sopenharmony_ci OpReturn 550fd4e5da5Sopenharmony_ci OpFunctionEnd 551fd4e5da5Sopenharmony_ci )"; 552fd4e5da5Sopenharmony_ci 553fd4e5da5Sopenharmony_ci auto res = SinglePassRunToBinary<CCPPass>(spv_asm, true); 554fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange); 555fd4e5da5Sopenharmony_ci} 556fd4e5da5Sopenharmony_ci 557fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SkipSpecConstantInstrucitons) { 558fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 559fd4e5da5Sopenharmony_ci OpCapability Shader 560fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 561fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 562fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" 563fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 564fd4e5da5Sopenharmony_ci OpSource HLSL 500 565fd4e5da5Sopenharmony_ci OpName %main "main" 566fd4e5da5Sopenharmony_ci %void = OpTypeVoid 567fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %void 568fd4e5da5Sopenharmony_ci %bool = OpTypeBool 569fd4e5da5Sopenharmony_ci %10 = OpSpecConstantFalse %bool 570fd4e5da5Sopenharmony_ci %main = OpFunction %void None %4 571fd4e5da5Sopenharmony_ci %11 = OpLabel 572fd4e5da5Sopenharmony_ci OpBranchConditional %10 %L1 %L2 573fd4e5da5Sopenharmony_ci %L1 = OpLabel 574fd4e5da5Sopenharmony_ci OpReturn 575fd4e5da5Sopenharmony_ci %L2 = OpLabel 576fd4e5da5Sopenharmony_ci OpReturn 577fd4e5da5Sopenharmony_ci OpFunctionEnd 578fd4e5da5Sopenharmony_ci )"; 579fd4e5da5Sopenharmony_ci 580fd4e5da5Sopenharmony_ci auto res = SinglePassRunToBinary<CCPPass>(spv_asm, true); 581fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(res), Pass::Status::SuccessWithoutChange); 582fd4e5da5Sopenharmony_ci} 583fd4e5da5Sopenharmony_ci 584fd4e5da5Sopenharmony_ciTEST_F(CCPTest, FoldConstantCompositeInstrucitonsWithSpecConst) { 585fd4e5da5Sopenharmony_ci const std::string spv_asm = R"( 586fd4e5da5Sopenharmony_ci OpCapability Shader 587fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 588fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %1 "main" 589fd4e5da5Sopenharmony_ci OpExecutionMode %1 OriginUpperLeft 590fd4e5da5Sopenharmony_ci %void = OpTypeVoid 591fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %void 592fd4e5da5Sopenharmony_ci %bool = OpTypeBool 593fd4e5da5Sopenharmony_ci %v3bool = OpTypeVector %bool 3 594fd4e5da5Sopenharmony_ci %_struct_8 = OpTypeStruct %v3bool 595fd4e5da5Sopenharmony_ci %true = OpConstantTrue %bool 596fd4e5da5Sopenharmony_ci; CHECK: [[spec_const:%\w+]] = OpSpecConstantComposite %v3bool 597fd4e5da5Sopenharmony_ci %11 = OpSpecConstantComposite %v3bool %true %true %true 598fd4e5da5Sopenharmony_ci %12 = OpConstantComposite %_struct_8 %11 599fd4e5da5Sopenharmony_ci; CHECK: OpFunction 600fd4e5da5Sopenharmony_ci %1 = OpFunction %void None %4 601fd4e5da5Sopenharmony_ci %29 = OpLabel 602fd4e5da5Sopenharmony_ci %31 = OpCompositeExtract %v3bool %12 0 603fd4e5da5Sopenharmony_ci; CHECK: OpCompositeExtract %bool [[spec_const]] 0 604fd4e5da5Sopenharmony_ci %32 = OpCompositeExtract %bool %31 0 605fd4e5da5Sopenharmony_ci OpReturn 606fd4e5da5Sopenharmony_ci OpFunctionEnd 607fd4e5da5Sopenharmony_ci )"; 608fd4e5da5Sopenharmony_ci 609fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndMatch<CCPPass>(spv_asm, true); 610fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 611fd4e5da5Sopenharmony_ci} 612fd4e5da5Sopenharmony_ci 613fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UpdateSubsequentPhisToVarying) { 614fd4e5da5Sopenharmony_ci const std::string text = R"( 615fd4e5da5Sopenharmony_ciOpCapability Shader 616fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 617fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" %in 618fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft 619fd4e5da5Sopenharmony_ci%void = OpTypeVoid 620fd4e5da5Sopenharmony_ci%bool = OpTypeBool 621fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 622fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool 623fd4e5da5Sopenharmony_ci%int0 = OpConstant %int 0 624fd4e5da5Sopenharmony_ci%int1 = OpConstant %int 1 625fd4e5da5Sopenharmony_ci%int6 = OpConstant %int 6 626fd4e5da5Sopenharmony_ci%int_ptr_Input = OpTypePointer Input %int 627fd4e5da5Sopenharmony_ci%in = OpVariable %int_ptr_Input Input 628fd4e5da5Sopenharmony_ci%undef = OpUndef %int 629fd4e5da5Sopenharmony_ci 630fd4e5da5Sopenharmony_ci; Although no constants are propagated in this function, the propagator 631fd4e5da5Sopenharmony_ci; generates a new %true value while visiting conditional statements. 632fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool 633fd4e5da5Sopenharmony_ci 634fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 635fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 636fd4e5da5Sopenharmony_ci%1 = OpLabel 637fd4e5da5Sopenharmony_ciOpBranch %2 638fd4e5da5Sopenharmony_ci%2 = OpLabel 639fd4e5da5Sopenharmony_ci%outer_phi = OpPhi %int %int0 %1 %outer_add %15 640fd4e5da5Sopenharmony_ci%cond1 = OpSLessThanEqual %bool %outer_phi %int6 641fd4e5da5Sopenharmony_ciOpLoopMerge %3 %15 None 642fd4e5da5Sopenharmony_ciOpBranchConditional %cond1 %4 %3 643fd4e5da5Sopenharmony_ci%4 = OpLabel 644fd4e5da5Sopenharmony_ci%ld = OpLoad %int %in 645fd4e5da5Sopenharmony_ci%cond2 = OpSGreaterThanEqual %bool %int1 %ld 646fd4e5da5Sopenharmony_ciOpSelectionMerge %10 None 647fd4e5da5Sopenharmony_ciOpBranchConditional %cond2 %8 %9 648fd4e5da5Sopenharmony_ci%8 = OpLabel 649fd4e5da5Sopenharmony_ciOpBranch %10 650fd4e5da5Sopenharmony_ci%9 = OpLabel 651fd4e5da5Sopenharmony_ciOpBranch %10 652fd4e5da5Sopenharmony_ci%10 = OpLabel 653fd4e5da5Sopenharmony_ci%extra_phi = OpPhi %int %outer_phi %8 %outer_phi %9 654fd4e5da5Sopenharmony_ciOpBranch %11 655fd4e5da5Sopenharmony_ci%11 = OpLabel 656fd4e5da5Sopenharmony_ci%inner_phi = OpPhi %int %int0 %10 %inner_add %13 657fd4e5da5Sopenharmony_ci%cond3 = OpSLessThanEqual %bool %inner_phi %int6 658fd4e5da5Sopenharmony_ciOpLoopMerge %14 %13 None 659fd4e5da5Sopenharmony_ciOpBranchConditional %cond3 %12 %14 660fd4e5da5Sopenharmony_ci%12 = OpLabel 661fd4e5da5Sopenharmony_ciOpBranch %13 662fd4e5da5Sopenharmony_ci%13 = OpLabel 663fd4e5da5Sopenharmony_ci%inner_add = OpIAdd %int %inner_phi %int1 664fd4e5da5Sopenharmony_ciOpBranch %11 665fd4e5da5Sopenharmony_ci%14 = OpLabel 666fd4e5da5Sopenharmony_ciOpBranch %15 667fd4e5da5Sopenharmony_ci%15 = OpLabel 668fd4e5da5Sopenharmony_ci%outer_add = OpIAdd %int %extra_phi %int1 669fd4e5da5Sopenharmony_ciOpBranch %2 670fd4e5da5Sopenharmony_ci%3 = OpLabel 671fd4e5da5Sopenharmony_ciOpReturn 672fd4e5da5Sopenharmony_ciOpFunctionEnd 673fd4e5da5Sopenharmony_ci)"; 674fd4e5da5Sopenharmony_ci 675fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndMatch<CCPPass>(text, true); 676fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 677fd4e5da5Sopenharmony_ci} 678fd4e5da5Sopenharmony_ci 679fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UndefInPhi) { 680fd4e5da5Sopenharmony_ci const std::string text = R"( 681fd4e5da5Sopenharmony_ci; CHECK: [[uint1:%\w+]] = OpConstant {{%\w+}} 1 682fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi 683fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[phi]] [[uint1]] 684fd4e5da5Sopenharmony_ci OpCapability Kernel 685fd4e5da5Sopenharmony_ci OpCapability Linkage 686fd4e5da5Sopenharmony_ci OpMemoryModel Logical OpenCL 687fd4e5da5Sopenharmony_ci OpDecorate %1 LinkageAttributes "func" Export 688fd4e5da5Sopenharmony_ci %void = OpTypeVoid 689fd4e5da5Sopenharmony_ci %bool = OpTypeBool 690fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 691fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 692fd4e5da5Sopenharmony_ci %uint_1 = OpConstant %uint 1 693fd4e5da5Sopenharmony_ci %7 = OpUndef %uint 694fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %void %bool 695fd4e5da5Sopenharmony_ci %1 = OpFunction %void None %8 696fd4e5da5Sopenharmony_ci %9 = OpFunctionParameter %bool 697fd4e5da5Sopenharmony_ci %10 = OpLabel 698fd4e5da5Sopenharmony_ci OpBranchConditional %9 %11 %12 699fd4e5da5Sopenharmony_ci %11 = OpLabel 700fd4e5da5Sopenharmony_ci OpBranch %13 701fd4e5da5Sopenharmony_ci %12 = OpLabel 702fd4e5da5Sopenharmony_ci OpBranch %14 703fd4e5da5Sopenharmony_ci %14 = OpLabel 704fd4e5da5Sopenharmony_ci OpBranchConditional %9 %13 %15 705fd4e5da5Sopenharmony_ci %15 = OpLabel 706fd4e5da5Sopenharmony_ci OpBranch %13 707fd4e5da5Sopenharmony_ci %13 = OpLabel 708fd4e5da5Sopenharmony_ci %16 = OpPhi %uint %uint_0 %11 %7 %14 %uint_1 %15 709fd4e5da5Sopenharmony_ci %17 = OpIAdd %uint %16 %uint_1 710fd4e5da5Sopenharmony_ci OpReturn 711fd4e5da5Sopenharmony_ci OpFunctionEnd 712fd4e5da5Sopenharmony_ci)"; 713fd4e5da5Sopenharmony_ci 714fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 715fd4e5da5Sopenharmony_ci} 716fd4e5da5Sopenharmony_ci 717fd4e5da5Sopenharmony_ci// Just test to make sure the constant fold rules are being used. Will rely on 718fd4e5da5Sopenharmony_ci// the folding test for specific testing of specific rules. 719fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UseConstantFoldingRules) { 720fd4e5da5Sopenharmony_ci const std::string text = R"( 721fd4e5da5Sopenharmony_ci; CHECK: [[float1:%\w+]] = OpConstant {{%\w+}} 1 722fd4e5da5Sopenharmony_ci; CHECK: OpReturnValue [[float1]] 723fd4e5da5Sopenharmony_ci OpCapability Shader 724fd4e5da5Sopenharmony_ci OpCapability Linkage 725fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 726fd4e5da5Sopenharmony_ci OpDecorate %1 LinkageAttributes "func" Export 727fd4e5da5Sopenharmony_ci %void = OpTypeVoid 728fd4e5da5Sopenharmony_ci %bool = OpTypeBool 729fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 730fd4e5da5Sopenharmony_ci %float_0 = OpConstant %float 0 731fd4e5da5Sopenharmony_ci %float_1 = OpConstant %float 1 732fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %float 733fd4e5da5Sopenharmony_ci %1 = OpFunction %float None %8 734fd4e5da5Sopenharmony_ci %10 = OpLabel 735fd4e5da5Sopenharmony_ci %17 = OpFAdd %float %float_0 %float_1 736fd4e5da5Sopenharmony_ci OpReturnValue %17 737fd4e5da5Sopenharmony_ci OpFunctionEnd 738fd4e5da5Sopenharmony_ci)"; 739fd4e5da5Sopenharmony_ci 740fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 741fd4e5da5Sopenharmony_ci} 742fd4e5da5Sopenharmony_ci 743fd4e5da5Sopenharmony_ci// Test for #1300. Previously value for %5 would not settle during simulation. 744fd4e5da5Sopenharmony_ciTEST_F(CCPTest, SettlePhiLatticeValue) { 745fd4e5da5Sopenharmony_ci const std::string text = R"( 746fd4e5da5Sopenharmony_ciOpCapability Kernel 747fd4e5da5Sopenharmony_ciOpCapability Linkage 748fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL 749fd4e5da5Sopenharmony_ciOpDecorate %func LinkageAttributes "func" Export 750fd4e5da5Sopenharmony_ci%void = OpTypeVoid 751fd4e5da5Sopenharmony_ci%bool = OpTypeBool 752fd4e5da5Sopenharmony_ci%true = OpConstantTrue %bool 753fd4e5da5Sopenharmony_ci%false = OpConstantFalse %bool 754fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 755fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 756fd4e5da5Sopenharmony_ci%1 = OpLabel 757fd4e5da5Sopenharmony_ciOpBranchConditional %true %2 %3 758fd4e5da5Sopenharmony_ci%3 = OpLabel 759fd4e5da5Sopenharmony_ciOpBranch %2 760fd4e5da5Sopenharmony_ci%2 = OpLabel 761fd4e5da5Sopenharmony_ci%5 = OpPhi %bool %true %1 %false %3 762fd4e5da5Sopenharmony_ciOpReturn 763fd4e5da5Sopenharmony_ciOpFunctionEnd 764fd4e5da5Sopenharmony_ci)"; 765fd4e5da5Sopenharmony_ci 766fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 767fd4e5da5Sopenharmony_ci SinglePassRunToBinary<CCPPass>(text, true); 768fd4e5da5Sopenharmony_ci} 769fd4e5da5Sopenharmony_ci 770fd4e5da5Sopenharmony_ciTEST_F(CCPTest, NullBranchCondition) { 771fd4e5da5Sopenharmony_ci const std::string text = R"( 772fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 773fd4e5da5Sopenharmony_ci; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2 774fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]] 775fd4e5da5Sopenharmony_ciOpCapability Shader 776fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 777fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" 778fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft 779fd4e5da5Sopenharmony_ci%void = OpTypeVoid 780fd4e5da5Sopenharmony_ci%bool = OpTypeBool 781fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 782fd4e5da5Sopenharmony_ci%null = OpConstantNull %bool 783fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1 784fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2 785fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 786fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 787fd4e5da5Sopenharmony_ci%1 = OpLabel 788fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None 789fd4e5da5Sopenharmony_ciOpBranchConditional %null %2 %3 790fd4e5da5Sopenharmony_ci%3 = OpLabel 791fd4e5da5Sopenharmony_ciOpBranch %2 792fd4e5da5Sopenharmony_ci%2 = OpLabel 793fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3 794fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi 795fd4e5da5Sopenharmony_ciOpReturn 796fd4e5da5Sopenharmony_ciOpFunctionEnd 797fd4e5da5Sopenharmony_ci)"; 798fd4e5da5Sopenharmony_ci 799fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 800fd4e5da5Sopenharmony_ci} 801fd4e5da5Sopenharmony_ci 802fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UndefBranchCondition) { 803fd4e5da5Sopenharmony_ci const std::string text = R"( 804fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 805fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi 806fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]] 807fd4e5da5Sopenharmony_ciOpCapability Shader 808fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 809fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" 810fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft 811fd4e5da5Sopenharmony_ci%void = OpTypeVoid 812fd4e5da5Sopenharmony_ci%bool = OpTypeBool 813fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 814fd4e5da5Sopenharmony_ci%undef = OpUndef %bool 815fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1 816fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2 817fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 818fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 819fd4e5da5Sopenharmony_ci%1 = OpLabel 820fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None 821fd4e5da5Sopenharmony_ciOpBranchConditional %undef %2 %3 822fd4e5da5Sopenharmony_ci%3 = OpLabel 823fd4e5da5Sopenharmony_ciOpBranch %2 824fd4e5da5Sopenharmony_ci%2 = OpLabel 825fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3 826fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi 827fd4e5da5Sopenharmony_ciOpReturn 828fd4e5da5Sopenharmony_ciOpFunctionEnd 829fd4e5da5Sopenharmony_ci)"; 830fd4e5da5Sopenharmony_ci 831fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 832fd4e5da5Sopenharmony_ci} 833fd4e5da5Sopenharmony_ci 834fd4e5da5Sopenharmony_ciTEST_F(CCPTest, NullSwitchCondition) { 835fd4e5da5Sopenharmony_ci const std::string text = R"( 836fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 837fd4e5da5Sopenharmony_ci; CHECK: [[int2:%\w+]] = OpConstant {{%\w+}} 2 838fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[int2]] 839fd4e5da5Sopenharmony_ciOpCapability Shader 840fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 841fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" 842fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft 843fd4e5da5Sopenharmony_ci%void = OpTypeVoid 844fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 845fd4e5da5Sopenharmony_ci%null = OpConstantNull %int 846fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1 847fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2 848fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 849fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 850fd4e5da5Sopenharmony_ci%1 = OpLabel 851fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None 852fd4e5da5Sopenharmony_ciOpSwitch %null %2 0 %3 853fd4e5da5Sopenharmony_ci%3 = OpLabel 854fd4e5da5Sopenharmony_ciOpBranch %2 855fd4e5da5Sopenharmony_ci%2 = OpLabel 856fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3 857fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi 858fd4e5da5Sopenharmony_ciOpReturn 859fd4e5da5Sopenharmony_ciOpFunctionEnd 860fd4e5da5Sopenharmony_ci)"; 861fd4e5da5Sopenharmony_ci 862fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 863fd4e5da5Sopenharmony_ci} 864fd4e5da5Sopenharmony_ci 865fd4e5da5Sopenharmony_ciTEST_F(CCPTest, UndefSwitchCondition) { 866fd4e5da5Sopenharmony_ci const std::string text = R"( 867fd4e5da5Sopenharmony_ci; CHECK: [[int1:%\w+]] = OpConstant {{%\w+}} 1 868fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi 869fd4e5da5Sopenharmony_ci; CHECK: OpIAdd {{%\w+}} [[int1]] [[phi]] 870fd4e5da5Sopenharmony_ciOpCapability Shader 871fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 872fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" 873fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft 874fd4e5da5Sopenharmony_ci%void = OpTypeVoid 875fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 876fd4e5da5Sopenharmony_ci%undef = OpUndef %int 877fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1 878fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2 879fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 880fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 881fd4e5da5Sopenharmony_ci%1 = OpLabel 882fd4e5da5Sopenharmony_ciOpSelectionMerge %2 None 883fd4e5da5Sopenharmony_ciOpSwitch %undef %2 0 %3 884fd4e5da5Sopenharmony_ci%3 = OpLabel 885fd4e5da5Sopenharmony_ciOpBranch %2 886fd4e5da5Sopenharmony_ci%2 = OpLabel 887fd4e5da5Sopenharmony_ci%phi = OpPhi %int %int_1 %1 %int_2 %3 888fd4e5da5Sopenharmony_ci%add = OpIAdd %int %int_1 %phi 889fd4e5da5Sopenharmony_ciOpReturn 890fd4e5da5Sopenharmony_ciOpFunctionEnd 891fd4e5da5Sopenharmony_ci)"; 892fd4e5da5Sopenharmony_ci 893fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 894fd4e5da5Sopenharmony_ci} 895fd4e5da5Sopenharmony_ci 896fd4e5da5Sopenharmony_ci// Test for #1361. 897fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CompositeConstructOfGlobalValue) { 898fd4e5da5Sopenharmony_ci const std::string text = R"( 899fd4e5da5Sopenharmony_ci; CHECK: [[phi:%\w+]] = OpPhi 900fd4e5da5Sopenharmony_ci; CHECK-NEXT: OpCompositeExtract {{%\w+}} [[phi]] 0 901fd4e5da5Sopenharmony_ciOpCapability Shader 902fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 903fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %func "func" %in 904fd4e5da5Sopenharmony_ciOpExecutionMode %func OriginUpperLeft 905fd4e5da5Sopenharmony_ci%void = OpTypeVoid 906fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 907fd4e5da5Sopenharmony_ci%bool = OpTypeBool 908fd4e5da5Sopenharmony_ci%functy = OpTypeFunction %void 909fd4e5da5Sopenharmony_ci%ptr_int_Input = OpTypePointer Input %int 910fd4e5da5Sopenharmony_ci%in = OpVariable %ptr_int_Input Input 911fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %ptr_int_Input %ptr_int_Input 912fd4e5da5Sopenharmony_ci%struct_null = OpConstantNull %struct 913fd4e5da5Sopenharmony_ci%func = OpFunction %void None %functy 914fd4e5da5Sopenharmony_ci%1 = OpLabel 915fd4e5da5Sopenharmony_ciOpBranch %2 916fd4e5da5Sopenharmony_ci%2 = OpLabel 917fd4e5da5Sopenharmony_ci%phi = OpPhi %struct %struct_null %1 %5 %4 918fd4e5da5Sopenharmony_ci%extract = OpCompositeExtract %ptr_int_Input %phi 0 919fd4e5da5Sopenharmony_ciOpLoopMerge %3 %4 None 920fd4e5da5Sopenharmony_ciOpBranch %4 921fd4e5da5Sopenharmony_ci%4 = OpLabel 922fd4e5da5Sopenharmony_ci%5 = OpCompositeConstruct %struct %in %in 923fd4e5da5Sopenharmony_ciOpBranch %2 924fd4e5da5Sopenharmony_ci%3 = OpLabel 925fd4e5da5Sopenharmony_ciOpReturn 926fd4e5da5Sopenharmony_ciOpFunctionEnd 927fd4e5da5Sopenharmony_ci)"; 928fd4e5da5Sopenharmony_ci 929fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 930fd4e5da5Sopenharmony_ci} 931fd4e5da5Sopenharmony_ci 932fd4e5da5Sopenharmony_ciTEST_F(CCPTest, FoldWithDecoration) { 933fd4e5da5Sopenharmony_ci const std::string text = R"( 934fd4e5da5Sopenharmony_ci; CHECK: OpCapability 935fd4e5da5Sopenharmony_ci; CHECK-NOT: OpDecorate 936fd4e5da5Sopenharmony_ci; CHECK: OpFunctionEnd 937fd4e5da5Sopenharmony_ci OpCapability Shader 938fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 939fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 940fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 941fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 942fd4e5da5Sopenharmony_ci OpSource ESSL 310 943fd4e5da5Sopenharmony_ci OpDecorate %3 RelaxedPrecision 944fd4e5da5Sopenharmony_ci %void = OpTypeVoid 945fd4e5da5Sopenharmony_ci %5 = OpTypeFunction %void 946fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 947fd4e5da5Sopenharmony_ci %v3float = OpTypeVector %float 3 948fd4e5da5Sopenharmony_ci %float_0 = OpConstant %float 0 949fd4e5da5Sopenharmony_ci %v4float = OpTypeVector %float 4 950fd4e5da5Sopenharmony_ci %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 951fd4e5da5Sopenharmony_ci %2 = OpFunction %void None %5 952fd4e5da5Sopenharmony_ci %11 = OpLabel 953fd4e5da5Sopenharmony_ci %3 = OpVectorShuffle %v3float %10 %10 0 1 2 954fd4e5da5Sopenharmony_ci OpReturn 955fd4e5da5Sopenharmony_ci OpFunctionEnd 956fd4e5da5Sopenharmony_ci)"; 957fd4e5da5Sopenharmony_ci 958fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 959fd4e5da5Sopenharmony_ci} 960fd4e5da5Sopenharmony_ci 961fd4e5da5Sopenharmony_ciTEST_F(CCPTest, DebugSimpleFoldConstant) { 962fd4e5da5Sopenharmony_ci const std::string text = R"( 963fd4e5da5Sopenharmony_ci OpCapability Shader 964fd4e5da5Sopenharmony_ci OpCapability Linkage 965fd4e5da5Sopenharmony_ci %ext = OpExtInstImport "OpenCL.DebugInfo.100" 966fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 967fd4e5da5Sopenharmony_ci %file_name = OpString "test" 968fd4e5da5Sopenharmony_ci %float_name = OpString "float" 969fd4e5da5Sopenharmony_ci %main_name = OpString "main" 970fd4e5da5Sopenharmony_ci %f_name = OpString "f" 971fd4e5da5Sopenharmony_ci OpDecorate %1 LinkageAttributes "func" Export 972fd4e5da5Sopenharmony_ci %void = OpTypeVoid 973fd4e5da5Sopenharmony_ci %bool = OpTypeBool 974fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 975fd4e5da5Sopenharmony_ci %float_0 = OpConstant %float 0 976fd4e5da5Sopenharmony_ci 977fd4e5da5Sopenharmony_ci; CHECK: [[float1:%\w+]] = OpConstant {{%\w+}} 1 978fd4e5da5Sopenharmony_ci %float_1 = OpConstant %float 1 979fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 980fd4e5da5Sopenharmony_ci %uint_32 = OpConstant %uint 32 981fd4e5da5Sopenharmony_ci %8 = OpTypeFunction %float 982fd4e5da5Sopenharmony_ci %null_expr = OpExtInst %void %ext DebugExpression 983fd4e5da5Sopenharmony_ci %src = OpExtInst %void %ext DebugSource %file_name 984fd4e5da5Sopenharmony_ci %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 985fd4e5da5Sopenharmony_ci %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 986fd4e5da5Sopenharmony_ci %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf 987fd4e5da5Sopenharmony_ci %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %1 988fd4e5da5Sopenharmony_ci %dbg_f = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal 989fd4e5da5Sopenharmony_ci %1 = OpFunction %float None %8 990fd4e5da5Sopenharmony_ci %10 = OpLabel 991fd4e5da5Sopenharmony_ci 992fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext:%\w+]] DebugScope 993fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file:%\w+]] 1 0 994fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue {{%\w+}} %float_1 995fd4e5da5Sopenharmony_ci %s0 = OpExtInst %void %ext DebugScope %dbg_main 996fd4e5da5Sopenharmony_ci OpLine %file_name 1 0 997fd4e5da5Sopenharmony_ci %17 = OpFAdd %float %float_0 %float_1 998fd4e5da5Sopenharmony_ci %val = OpExtInst %void %ext DebugValue %dbg_f %17 %null_expr 999fd4e5da5Sopenharmony_ci 1000fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file]] 2 0 1001fd4e5da5Sopenharmony_ci; CHECK: OpReturnValue [[float1]] 1002fd4e5da5Sopenharmony_ci OpLine %file_name 2 0 1003fd4e5da5Sopenharmony_ci OpReturnValue %17 1004fd4e5da5Sopenharmony_ci OpFunctionEnd 1005fd4e5da5Sopenharmony_ci)"; 1006fd4e5da5Sopenharmony_ci 1007fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 1008fd4e5da5Sopenharmony_ci} 1009fd4e5da5Sopenharmony_ci 1010fd4e5da5Sopenharmony_ciTEST_F(CCPTest, DebugFoldMultipleForSingleConstant) { 1011fd4e5da5Sopenharmony_ci const std::string text = R"( 1012fd4e5da5Sopenharmony_ci OpCapability Shader 1013fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1014fd4e5da5Sopenharmony_ci %ext = OpExtInstImport "OpenCL.DebugInfo.100" 1015fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1016fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %outparm 1017fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 1018fd4e5da5Sopenharmony_ci OpSource GLSL 450 1019fd4e5da5Sopenharmony_ci %file_name = OpString "test" 1020fd4e5da5Sopenharmony_ci %float_name = OpString "float" 1021fd4e5da5Sopenharmony_ci %main_name = OpString "main" 1022fd4e5da5Sopenharmony_ci %f_name = OpString "f" 1023fd4e5da5Sopenharmony_ci OpName %main "main" 1024fd4e5da5Sopenharmony_ci OpName %outparm "outparm" 1025fd4e5da5Sopenharmony_ci OpDecorate %outparm Location 0 1026fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1027fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %void 1028fd4e5da5Sopenharmony_ci %int = OpTypeInt 32 1 1029fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1030fd4e5da5Sopenharmony_ci%_ptr_Function_int = OpTypePointer Function %int 1031fd4e5da5Sopenharmony_ci %int_4 = OpConstant %int 4 1032fd4e5da5Sopenharmony_ci %int_3 = OpConstant %int 3 1033fd4e5da5Sopenharmony_ci %int_1 = OpConstant %int 1 1034fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1035fd4e5da5Sopenharmony_ci %uint_32 = OpConstant %uint 32 1036fd4e5da5Sopenharmony_ci%_ptr_Output_int = OpTypePointer Output %int 1037fd4e5da5Sopenharmony_ci %outparm = OpVariable %_ptr_Output_int Output 1038fd4e5da5Sopenharmony_ci %null_expr = OpExtInst %void %ext DebugExpression 1039fd4e5da5Sopenharmony_ci %src = OpExtInst %void %ext DebugSource %file_name 1040fd4e5da5Sopenharmony_ci %cu = OpExtInst %void %ext DebugCompilationUnit 1 4 %src HLSL 1041fd4e5da5Sopenharmony_ci %dbg_tf = OpExtInst %void %ext DebugTypeBasic %float_name %uint_32 Float 1042fd4e5da5Sopenharmony_ci %main_ty = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %dbg_tf 1043fd4e5da5Sopenharmony_ci %dbg_main = OpExtInst %void %ext DebugFunction %main_name %main_ty %src 0 0 %cu %main_name FlagIsProtected|FlagIsPrivate 10 %main 1044fd4e5da5Sopenharmony_ci %bb0 = OpExtInst %void %ext DebugLexicalBlock %src 0 0 %dbg_main 1045fd4e5da5Sopenharmony_ci %bb1 = OpExtInst %void %ext DebugLexicalBlock %src 1 0 %dbg_main 1046fd4e5da5Sopenharmony_ci %bb2 = OpExtInst %void %ext DebugLexicalBlock %src 2 0 %dbg_main 1047fd4e5da5Sopenharmony_ci %bb3 = OpExtInst %void %ext DebugLexicalBlock %src 3 0 %dbg_main 1048fd4e5da5Sopenharmony_ci %dbg_f0 = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 0 0 %dbg_main FlagIsLocal 1049fd4e5da5Sopenharmony_ci %dbg_f1 = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 1 0 %dbg_main FlagIsLocal 1050fd4e5da5Sopenharmony_ci %dbg_f2 = OpExtInst %void %ext DebugLocalVariable %f_name %dbg_tf %src 2 0 %dbg_main FlagIsLocal 1051fd4e5da5Sopenharmony_ci %main = OpFunction %void None %3 1052fd4e5da5Sopenharmony_ci %4 = OpLabel 1053fd4e5da5Sopenharmony_ci 1054fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext:%\w+]] DebugScope 1055fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file:%\w+]] 1 0 1056fd4e5da5Sopenharmony_ci; CHECK: OpIAdd %int %int_4 %int_3 1057fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue {{%\w+}} %int_7 1058fd4e5da5Sopenharmony_ci %s0 = OpExtInst %void %ext DebugScope %bb0 1059fd4e5da5Sopenharmony_ci OpLine %file_name 1 0 1060fd4e5da5Sopenharmony_ci %9 = OpIAdd %int %int_4 %int_3 1061fd4e5da5Sopenharmony_ci %val0 = OpExtInst %void %ext DebugValue %dbg_f0 %9 %null_expr 1062fd4e5da5Sopenharmony_ci 1063fd4e5da5Sopenharmony_ci; CHECK: OpLine [[file]] 2 0 1064fd4e5da5Sopenharmony_ci; CHECK: OpSGreaterThan %bool %int_7 %int_3 1065fd4e5da5Sopenharmony_ci; CHECK: OpExtInst %void [[ext]] DebugValue {{%\w+}} %true 1066fd4e5da5Sopenharmony_ci OpLine %file_name 2 0 1067fd4e5da5Sopenharmony_ci %6 = OpSGreaterThan %bool %9 %int_3 1068fd4e5da5Sopenharmony_ci %val1 = OpExtInst %void %ext DebugValue %dbg_f1 %6 %null_expr 1069fd4e5da5Sopenharmony_ci 1070fd4e5da5Sopenharmony_ci OpSelectionMerge %25 None 1071fd4e5da5Sopenharmony_ci OpBranchConditional %6 %22 %23 1072fd4e5da5Sopenharmony_ci %22 = OpLabel 1073fd4e5da5Sopenharmony_ci %s1 = OpExtInst %void %ext DebugScope %bb1 1074fd4e5da5Sopenharmony_ci %7 = OpCopyObject %int %9 1075fd4e5da5Sopenharmony_ci %val2 = OpExtInst %void %ext DebugValue %dbg_f2 %7 %null_expr 1076fd4e5da5Sopenharmony_ci OpBranch %25 1077fd4e5da5Sopenharmony_ci %23 = OpLabel 1078fd4e5da5Sopenharmony_ci %s2 = OpExtInst %void %ext DebugScope %bb2 1079fd4e5da5Sopenharmony_ci %8 = OpCopyObject %int %int_4 1080fd4e5da5Sopenharmony_ci OpBranch %25 1081fd4e5da5Sopenharmony_ci %25 = OpLabel 1082fd4e5da5Sopenharmony_ci %s3 = OpExtInst %void %ext DebugScope %bb3 1083fd4e5da5Sopenharmony_ci %35 = OpPhi %int %7 %22 %8 %23 1084fd4e5da5Sopenharmony_ci OpStore %outparm %35 1085fd4e5da5Sopenharmony_ci OpReturn 1086fd4e5da5Sopenharmony_ci OpFunctionEnd 1087fd4e5da5Sopenharmony_ci)"; 1088fd4e5da5Sopenharmony_ci 1089fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<CCPPass>(text, true); 1090fd4e5da5Sopenharmony_ci} 1091fd4e5da5Sopenharmony_ci 1092fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/3636 1093fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CCPNoChangeFailure) { 1094fd4e5da5Sopenharmony_ci const std::string text = R"( 1095fd4e5da5Sopenharmony_ci OpCapability Shader 1096fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1097fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1098fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 1099fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 1100fd4e5da5Sopenharmony_ci OpSource ESSL 320 1101fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 1102fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 1103fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 1104fd4e5da5Sopenharmony_ci %7 = OpConstant %6 2 1105fd4e5da5Sopenharmony_ci %13 = OpConstant %6 4 1106fd4e5da5Sopenharmony_ci %21 = OpConstant %6 1 1107fd4e5da5Sopenharmony_ci %10 = OpTypeBool 1108fd4e5da5Sopenharmony_ci %17 = OpTypePointer Function %6 1109fd4e5da5Sopenharmony_ci 1110fd4e5da5Sopenharmony_ci; CCP is generating two new constants during propagation that end up being 1111fd4e5da5Sopenharmony_ci; dead because they cannot be replaced anywhere in the IR. CCP was wrongly 1112fd4e5da5Sopenharmony_ci; considering the IR to be unmodified because of this. 1113fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool 1114fd4e5da5Sopenharmony_ci; CHECK: %int_3 = OpConstant %int 3 1115fd4e5da5Sopenharmony_ci 1116fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 1117fd4e5da5Sopenharmony_ci %11 = OpLabel 1118fd4e5da5Sopenharmony_ci OpBranch %5 1119fd4e5da5Sopenharmony_ci %5 = OpLabel 1120fd4e5da5Sopenharmony_ci %23 = OpPhi %6 %7 %11 %20 %15 1121fd4e5da5Sopenharmony_ci %9 = OpSLessThan %10 %23 %13 1122fd4e5da5Sopenharmony_ci OpLoopMerge %8 %15 None 1123fd4e5da5Sopenharmony_ci OpBranchConditional %9 %15 %8 1124fd4e5da5Sopenharmony_ci %15 = OpLabel 1125fd4e5da5Sopenharmony_ci %20 = OpIAdd %6 %23 %21 1126fd4e5da5Sopenharmony_ci OpBranch %5 1127fd4e5da5Sopenharmony_ci %8 = OpLabel 1128fd4e5da5Sopenharmony_ci OpReturn 1129fd4e5da5Sopenharmony_ci OpFunctionEnd 1130fd4e5da5Sopenharmony_ci)"; 1131fd4e5da5Sopenharmony_ci 1132fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndMatch<CCPPass>(text, true); 1133fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 1134fd4e5da5Sopenharmony_ci} 1135fd4e5da5Sopenharmony_ci 1136fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/3738 1137fd4e5da5Sopenharmony_ci// Similar to the previous one but more than one constant is generated in a 1138fd4e5da5Sopenharmony_ci// single call to the instruction folder. 1139fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CCPNoChangeFailureSeveralConstantsDuringFolding) { 1140fd4e5da5Sopenharmony_ci const std::string text = R"( 1141fd4e5da5Sopenharmony_ci OpCapability Shader 1142fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1143fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1144fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 1145fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 1146fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1147fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %void 1148fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 1149fd4e5da5Sopenharmony_ci %v3float = OpTypeVector %float 3 1150fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1151fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 1152fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1153fd4e5da5Sopenharmony_ci %v3bool = OpTypeVector %bool 3 1154fd4e5da5Sopenharmony_ci %float_0 = OpConstant %float 0 1155fd4e5da5Sopenharmony_ci %12 = OpConstantComposite %v3float %float_0 %float_0 %float_0 1156fd4e5da5Sopenharmony_ci%float_0_300000012 = OpConstant %float 0.300000012 1157fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %v3float %float_0_300000012 %float_0_300000012 %float_0_300000012 1158fd4e5da5Sopenharmony_ci 1159fd4e5da5Sopenharmony_ci; CCP is generating several constants during a single instruction evaluation. 1160fd4e5da5Sopenharmony_ci; When folding %19, it generates the constants %true and %24. They are dead 1161fd4e5da5Sopenharmony_ci; because they cannot be replaced anywhere in the IR. CCP was wrongly 1162fd4e5da5Sopenharmony_ci; considering the IR to be unmodified because of this. 1163fd4e5da5Sopenharmony_ci; 1164fd4e5da5Sopenharmony_ci; CHECK: %true = OpConstantTrue %bool 1165fd4e5da5Sopenharmony_ci; CHECK: %24 = OpConstantComposite %v3bool %true %true %true 1166fd4e5da5Sopenharmony_ci; CHECK: %float_1 = OpConstant %float 1 1167fd4e5da5Sopenharmony_ci; CHECK: %float_0_699999988 = OpConstant %float 0.699999988 1168fd4e5da5Sopenharmony_ci 1169fd4e5da5Sopenharmony_ci %2 = OpFunction %void None %4 1170fd4e5da5Sopenharmony_ci %15 = OpLabel 1171fd4e5da5Sopenharmony_ci OpBranch %16 1172fd4e5da5Sopenharmony_ci %16 = OpLabel 1173fd4e5da5Sopenharmony_ci %17 = OpPhi %v3float %12 %15 %14 %18 1174fd4e5da5Sopenharmony_ci %19 = OpFOrdLessThan %v3bool %17 %14 1175fd4e5da5Sopenharmony_ci %20 = OpAll %bool %19 1176fd4e5da5Sopenharmony_ci OpLoopMerge %21 %18 None 1177fd4e5da5Sopenharmony_ci OpBranchConditional %20 %18 %21 1178fd4e5da5Sopenharmony_ci %18 = OpLabel 1179fd4e5da5Sopenharmony_ci OpBranch %16 1180fd4e5da5Sopenharmony_ci %21 = OpLabel 1181fd4e5da5Sopenharmony_ci %22 = OpExtInst %v3float %1 FMix %12 %17 %14 1182fd4e5da5Sopenharmony_ci OpReturn 1183fd4e5da5Sopenharmony_ci OpFunctionEnd 1184fd4e5da5Sopenharmony_ci)"; 1185fd4e5da5Sopenharmony_ci 1186fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndMatch<CCPPass>(text, true); 1187fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 1188fd4e5da5Sopenharmony_ci} 1189fd4e5da5Sopenharmony_ci 1190fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/3991 1191fd4e5da5Sopenharmony_ci// Similar to the previous one but constants are created even when no 1192fd4e5da5Sopenharmony_ci// instruction are ever folded during propagation. 1193fd4e5da5Sopenharmony_ciTEST_F(CCPTest, CCPNoChangeFailureWithUnfoldableInstr) { 1194fd4e5da5Sopenharmony_ci const std::string text = R"( 1195fd4e5da5Sopenharmony_ci OpCapability Shader 1196fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1197fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1198fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 1199fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 1200fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1201fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %void 1202fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 1203fd4e5da5Sopenharmony_ci %v3float = OpTypeVector %float 3 1204fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1205fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 1206fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1207fd4e5da5Sopenharmony_ci %float_0 = OpConstant %float 0 1208fd4e5da5Sopenharmony_ci %11 = OpConstantComposite %v3float %float_0 %float_0 %float_0 1209fd4e5da5Sopenharmony_ci%float_0_300000012 = OpConstant %float 0.300000012 1210fd4e5da5Sopenharmony_ci %13 = OpConstantComposite %v3float %float_0_300000012 %float_0_300000012 %float_0_300000012 1211fd4e5da5Sopenharmony_ci 1212fd4e5da5Sopenharmony_ci; CCP generates two constants when trying to fold an instruction, which it 1213fd4e5da5Sopenharmony_ci; ultimately fails to fold. The instruction folder in CCP was only 1214fd4e5da5Sopenharmony_ci; checking for newly added constants if the instruction folds successfully. 1215fd4e5da5Sopenharmony_ci; 1216fd4e5da5Sopenharmony_ci; CHECK: %float_1 = OpConstant %float 1 1217fd4e5da5Sopenharmony_ci; CHECK: %float_0_699999988 = OpConstant %float 0.69999998 1218fd4e5da5Sopenharmony_ci 1219fd4e5da5Sopenharmony_ci %2 = OpFunction %void None %4 1220fd4e5da5Sopenharmony_ci %14 = OpLabel 1221fd4e5da5Sopenharmony_ci %15 = OpBitcast %uint %float_0_300000012 1222fd4e5da5Sopenharmony_ci %16 = OpUGreaterThan %bool %15 %uint_0 1223fd4e5da5Sopenharmony_ci OpBranch %17 1224fd4e5da5Sopenharmony_ci %17 = OpLabel 1225fd4e5da5Sopenharmony_ci %18 = OpPhi %v3float %11 %14 %13 %19 1226fd4e5da5Sopenharmony_ci OpLoopMerge %20 %19 None 1227fd4e5da5Sopenharmony_ci OpBranchConditional %16 %19 %20 1228fd4e5da5Sopenharmony_ci %19 = OpLabel 1229fd4e5da5Sopenharmony_ci OpBranch %17 1230fd4e5da5Sopenharmony_ci %20 = OpLabel 1231fd4e5da5Sopenharmony_ci %21 = OpExtInst %v3float %1 FMix %11 %18 %13 1232fd4e5da5Sopenharmony_ci OpReturn 1233fd4e5da5Sopenharmony_ci OpFunctionEnd 1234fd4e5da5Sopenharmony_ci)"; 1235fd4e5da5Sopenharmony_ci 1236fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndMatch<CCPPass>(text, true); 1237fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 1238fd4e5da5Sopenharmony_ci} 1239fd4e5da5Sopenharmony_ci 1240fd4e5da5Sopenharmony_ciTEST_F(CCPTest, FunctionDeclaration) { 1241fd4e5da5Sopenharmony_ci // Make sure the pass works with a function declaration that is called. 1242fd4e5da5Sopenharmony_ci const std::string text = R"(OpCapability Addresses 1243fd4e5da5Sopenharmony_ciOpCapability Linkage 1244fd4e5da5Sopenharmony_ciOpCapability Kernel 1245fd4e5da5Sopenharmony_ciOpCapability Int8 1246fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std" 1247fd4e5da5Sopenharmony_ciOpMemoryModel Physical64 OpenCL 1248fd4e5da5Sopenharmony_ciOpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool" 1249fd4e5da5Sopenharmony_ciOpExecutionMode %2 ContractionOff 1250fd4e5da5Sopenharmony_ciOpSource Unknown 0 1251fd4e5da5Sopenharmony_ciOpDecorate %3 LinkageAttributes "julia_error_7712" Import 1252fd4e5da5Sopenharmony_ci%void = OpTypeVoid 1253fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void 1254fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %5 1255fd4e5da5Sopenharmony_ciOpFunctionEnd 1256fd4e5da5Sopenharmony_ci%2 = OpFunction %void None %5 1257fd4e5da5Sopenharmony_ci%6 = OpLabel 1258fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %void %3 1259fd4e5da5Sopenharmony_ciOpReturn 1260fd4e5da5Sopenharmony_ciOpFunctionEnd 1261fd4e5da5Sopenharmony_ci)"; 1262fd4e5da5Sopenharmony_ci 1263fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<CCPPass>(text, text, false); 1264fd4e5da5Sopenharmony_ci} 1265fd4e5da5Sopenharmony_ci 1266fd4e5da5Sopenharmony_ci// Test from https://github.com/KhronosGroup/SPIRV-Tools/issues/4462. 1267fd4e5da5Sopenharmony_ci// The test was causing a lateral movement in the constant lattice, which was 1268fd4e5da5Sopenharmony_ci// not being detected as varying by CCP. In this test, FClamp is evaluated 1269fd4e5da5Sopenharmony_ci// twice. On the first evaluation, if computes FClamp(0.5, 0.5, -1) which 1270fd4e5da5Sopenharmony_ci// returns -1. On the second evaluation, it computes FClamp(0.5, 0.5, VARYING) 1271fd4e5da5Sopenharmony_ci// which returns 0.5. 1272fd4e5da5Sopenharmony_ci// 1273fd4e5da5Sopenharmony_ci// Both fold() computations are correct given the semantics of FClamp() but 1274fd4e5da5Sopenharmony_ci// this causes a lateral transition in the constant lattice which was not being 1275fd4e5da5Sopenharmony_ci// considered VARYING by CCP. 1276fd4e5da5Sopenharmony_ciTEST_F(CCPTest, LateralLatticeTransition) { 1277fd4e5da5Sopenharmony_ci const std::string text = R"(OpCapability Shader 1278fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 1279fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 1280fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %main "main" %gl_FragCoord %outColor 1281fd4e5da5Sopenharmony_ci OpExecutionMode %main OriginUpperLeft 1282fd4e5da5Sopenharmony_ci OpSource ESSL 310 1283fd4e5da5Sopenharmony_ci OpName %main "main" 1284fd4e5da5Sopenharmony_ci OpName %gl_FragCoord "gl_FragCoord" 1285fd4e5da5Sopenharmony_ci OpName %outColor "outColor" 1286fd4e5da5Sopenharmony_ci OpDecorate %gl_FragCoord BuiltIn FragCoord 1287fd4e5da5Sopenharmony_ci OpDecorate %outColor Location 0 1288fd4e5da5Sopenharmony_ci %void = OpTypeVoid 1289fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %void 1290fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 1291fd4e5da5Sopenharmony_ci %float_0_5 = OpConstant %float 0.5 1292fd4e5da5Sopenharmony_ci %v4float = OpTypeVector %float 4 1293fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float 1294fd4e5da5Sopenharmony_ci%gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1295fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1296fd4e5da5Sopenharmony_ci %uint_0 = OpConstant %uint 0 1297fd4e5da5Sopenharmony_ci%_ptr_Input_float = OpTypePointer Input %float 1298fd4e5da5Sopenharmony_ci %float_0 = OpConstant %float 0 1299fd4e5da5Sopenharmony_ci %bool = OpTypeBool 1300fd4e5da5Sopenharmony_ci %float_n1 = OpConstant %float -1 1301fd4e5da5Sopenharmony_ci %float_1 = OpConstant %float 1 1302fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float 1303fd4e5da5Sopenharmony_ci %outColor = OpVariable %_ptr_Output_v4float Output 1304fd4e5da5Sopenharmony_ci 1305fd4e5da5Sopenharmony_ci; This constant is created during the first evaluation of the CompositeConstruct 1306fd4e5da5Sopenharmony_ci; CHECK: [[new_constant:%\d+]] = OpConstantComposite %v4float %float_n1 %float_0_5 %float_0 %float_1 1307fd4e5da5Sopenharmony_ci 1308fd4e5da5Sopenharmony_ci %main = OpFunction %void None %6 1309fd4e5da5Sopenharmony_ci %19 = OpLabel 1310fd4e5da5Sopenharmony_ci %20 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0 1311fd4e5da5Sopenharmony_ci %21 = OpLoad %float %20 1312fd4e5da5Sopenharmony_ci %22 = OpFOrdLessThan %bool %21 %float_0 1313fd4e5da5Sopenharmony_ci OpSelectionMerge %23 None 1314fd4e5da5Sopenharmony_ci OpBranchConditional %22 %24 %25 1315fd4e5da5Sopenharmony_ci %24 = OpLabel 1316fd4e5da5Sopenharmony_ci OpBranch %23 1317fd4e5da5Sopenharmony_ci %25 = OpLabel 1318fd4e5da5Sopenharmony_ci OpBranch %26 1319fd4e5da5Sopenharmony_ci %26 = OpLabel 1320fd4e5da5Sopenharmony_ci OpBranch %23 1321fd4e5da5Sopenharmony_ci %23 = OpLabel 1322fd4e5da5Sopenharmony_ci %27 = OpPhi %float %float_n1 %24 %float_0_5 %26 1323fd4e5da5Sopenharmony_ci %28 = OpExtInst %float %1 FClamp %float_0_5 %float_0_5 %27 1324fd4e5da5Sopenharmony_ci 1325fd4e5da5Sopenharmony_ci ; On first evaluation, the result from FClamp will return 0.5. 1326fd4e5da5Sopenharmony_ci ; But on second evaluation, FClamp should return VARYING. Check 1327fd4e5da5Sopenharmony_ci ; that CCP is not keeping the first result. 1328fd4e5da5Sopenharmony_ci ; CHECK-NOT: %29 = OpCompositeConstruct %v4float %float_0_5 %float_0_5 %float_0 %float_1 1329fd4e5da5Sopenharmony_ci %29 = OpCompositeConstruct %v4float %28 %float_0_5 %float_0 %float_1 1330fd4e5da5Sopenharmony_ci 1331fd4e5da5Sopenharmony_ci ; CHECK-NOT: OpCopyObject %v4float [[new_constant]] 1332fd4e5da5Sopenharmony_ci %42 = OpCopyObject %v4float %29 1333fd4e5da5Sopenharmony_ci 1334fd4e5da5Sopenharmony_ci ; CHECK-NOT: OpStore %outColor [[new_constant]] 1335fd4e5da5Sopenharmony_ci OpStore %outColor %42 1336fd4e5da5Sopenharmony_ci 1337fd4e5da5Sopenharmony_ci OpReturn 1338fd4e5da5Sopenharmony_ci OpFunctionEnd 1339fd4e5da5Sopenharmony_ci)"; 1340fd4e5da5Sopenharmony_ci 1341fd4e5da5Sopenharmony_ci auto result = SinglePassRunAndMatch<CCPPass>(text, true); 1342fd4e5da5Sopenharmony_ci EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); 1343fd4e5da5Sopenharmony_ci} 1344fd4e5da5Sopenharmony_ci 1345fd4e5da5Sopenharmony_ci} // namespace 1346fd4e5da5Sopenharmony_ci} // namespace opt 1347fd4e5da5Sopenharmony_ci} // namespace spvtools 1348