1// Copyright (c) 2017 Google Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <string> 16#include <unordered_set> 17 18#include "test/opt/pass_fixture.h" 19#include "test/opt/pass_utils.h" 20 21namespace spvtools { 22namespace opt { 23namespace { 24 25using Workaround1209Test = PassTest<::testing::Test>; 26 27TEST_F(Workaround1209Test, RemoveOpUnreachableInLoop) { 28 const std::string text = R"( 29 OpCapability Shader 30 %1 = OpExtInstImport "GLSL.std.450" 31 OpMemoryModel Logical GLSL450 32 OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_ 33 OpSource GLSL 400 34 OpSourceExtension "GL_ARB_separate_shader_objects" 35 OpSourceExtension "GL_ARB_shading_language_420pack" 36 OpName %main "main" 37 OpName %texcoord "texcoord" 38 OpName %buf "buf" 39 OpMemberName %buf 0 "MVP" 40 OpMemberName %buf 1 "position" 41 OpMemberName %buf 2 "attr" 42 OpName %ubuf "ubuf" 43 OpName %gl_VertexIndex "gl_VertexIndex" 44 OpName %gl_PerVertex "gl_PerVertex" 45 OpMemberName %gl_PerVertex 0 "gl_Position" 46 OpName %_ "" 47 OpDecorate %texcoord Location 0 48 OpDecorate %_arr_v4float_uint_72 ArrayStride 16 49 OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16 50 OpMemberDecorate %buf 0 ColMajor 51 OpMemberDecorate %buf 0 Offset 0 52 OpMemberDecorate %buf 0 MatrixStride 16 53 OpMemberDecorate %buf 1 Offset 64 54 OpMemberDecorate %buf 2 Offset 1216 55 OpDecorate %buf Block 56 OpDecorate %ubuf DescriptorSet 0 57 OpDecorate %ubuf Binding 0 58 OpDecorate %gl_VertexIndex BuiltIn VertexIndex 59 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position 60 OpDecorate %gl_PerVertex Block 61 %void = OpTypeVoid 62 %12 = OpTypeFunction %void 63 %float = OpTypeFloat 32 64 %v4float = OpTypeVector %float 4 65%_ptr_Output_v4float = OpTypePointer Output %v4float 66 %texcoord = OpVariable %_ptr_Output_v4float Output 67%mat4v4float = OpTypeMatrix %v4float 4 68 %uint = OpTypeInt 32 0 69 %uint_72 = OpConstant %uint 72 70%_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72 71%_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72 72 %buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0 73%_ptr_Uniform_buf = OpTypePointer Uniform %buf 74 %ubuf = OpVariable %_ptr_Uniform_buf Uniform 75 %int = OpTypeInt 32 1 76 %int_2 = OpConstant %int 2 77%_ptr_Input_int = OpTypePointer Input %int 78%gl_VertexIndex = OpVariable %_ptr_Input_int Input 79%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float 80%gl_PerVertex = OpTypeStruct %v4float 81%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex 82 %_ = OpVariable %_ptr_Output_gl_PerVertex Output 83 %int_0 = OpConstant %int 0 84 %int_1 = OpConstant %int 1 85 %float_1 = OpConstant %float 1 86 %28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 87 %main = OpFunction %void None %12 88 %29 = OpLabel 89 OpBranch %30 90 %30 = OpLabel 91; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]] 92 OpLoopMerge %31 %32 None 93 OpBranch %33 94 %33 = OpLabel 95; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]] 96 OpSelectionMerge %34 None 97 OpSwitch %int_1 %35 98 %35 = OpLabel 99 %36 = OpLoad %int %gl_VertexIndex 100 %37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36 101 %38 = OpLoad %v4float %37 102 OpStore %texcoord %38 103 %39 = OpAccessChain %_ptr_Output_v4float %_ %int_0 104 OpStore %39 %28 105 OpBranch %31 106; CHECK: [[sel_merge]] = OpLabel 107 %34 = OpLabel 108; CHECK-NEXT: OpBranch [[merge]] 109 OpUnreachable 110 %32 = OpLabel 111 OpBranch %30 112 %31 = OpLabel 113 OpReturn 114 OpFunctionEnd)"; 115 116 SinglePassRunAndMatch<Workaround1209>(text, false); 117} 118 119TEST_F(Workaround1209Test, RemoveOpUnreachableInNestedLoop) { 120 const std::string text = R"( 121 OpCapability Shader 122 %1 = OpExtInstImport "GLSL.std.450" 123 OpMemoryModel Logical GLSL450 124 OpEntryPoint Vertex %2 "main" %3 %4 %5 125 OpSource GLSL 400 126 OpSourceExtension "GL_ARB_separate_shader_objects" 127 OpSourceExtension "GL_ARB_shading_language_420pack" 128 OpName %2 "main" 129 OpName %3 "texcoord" 130 OpName %6 "buf" 131 OpMemberName %6 0 "MVP" 132 OpMemberName %6 1 "position" 133 OpMemberName %6 2 "attr" 134 OpName %7 "ubuf" 135 OpName %4 "gl_VertexIndex" 136 OpName %8 "gl_PerVertex" 137 OpMemberName %8 0 "gl_Position" 138 OpName %5 "" 139 OpDecorate %3 Location 0 140 OpDecorate %9 ArrayStride 16 141 OpDecorate %10 ArrayStride 16 142 OpMemberDecorate %6 0 ColMajor 143 OpMemberDecorate %6 0 Offset 0 144 OpMemberDecorate %6 0 MatrixStride 16 145 OpMemberDecorate %6 1 Offset 64 146 OpMemberDecorate %6 2 Offset 1216 147 OpDecorate %6 Block 148 OpDecorate %7 DescriptorSet 0 149 OpDecorate %7 Binding 0 150 OpDecorate %4 BuiltIn VertexIndex 151 OpMemberDecorate %8 0 BuiltIn Position 152 OpDecorate %8 Block 153 %11 = OpTypeVoid 154 %12 = OpTypeFunction %11 155 %13 = OpTypeFloat 32 156 %14 = OpTypeVector %13 4 157 %15 = OpTypePointer Output %14 158 %3 = OpVariable %15 Output 159 %16 = OpTypeMatrix %14 4 160 %17 = OpTypeInt 32 0 161 %18 = OpConstant %17 72 162 %9 = OpTypeArray %14 %18 163 %10 = OpTypeArray %14 %18 164 %6 = OpTypeStruct %16 %9 %10 165 %19 = OpTypePointer Uniform %6 166 %7 = OpVariable %19 Uniform 167 %20 = OpTypeInt 32 1 168 %21 = OpConstant %20 2 169 %22 = OpTypePointer Input %20 170 %4 = OpVariable %22 Input 171 %23 = OpTypePointer Uniform %14 172 %8 = OpTypeStruct %14 173 %24 = OpTypePointer Output %8 174 %5 = OpVariable %24 Output 175 %25 = OpConstant %20 0 176 %26 = OpConstant %20 1 177 %27 = OpConstant %13 1 178 %28 = OpConstantComposite %14 %27 %27 %27 %27 179 %2 = OpFunction %11 None %12 180 %29 = OpLabel 181 OpBranch %31 182 %31 = OpLabel 183; CHECK: OpLoopMerge 184 OpLoopMerge %32 %33 None 185 OpBranch %30 186 %30 = OpLabel 187; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]] 188 OpLoopMerge %34 %35 None 189 OpBranch %36 190 %36 = OpLabel 191; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]] 192 OpSelectionMerge %37 None 193 OpSwitch %26 %38 194 %38 = OpLabel 195 %39 = OpLoad %20 %4 196 %40 = OpAccessChain %23 %7 %21 %39 197 %41 = OpLoad %14 %40 198 OpStore %3 %41 199 %42 = OpAccessChain %15 %5 %25 200 OpStore %42 %28 201 OpBranch %34 202; CHECK: [[sel_merge]] = OpLabel 203 %37 = OpLabel 204; CHECK-NEXT: OpBranch [[merge]] 205 OpUnreachable 206 %35 = OpLabel 207 OpBranch %30 208 %34 = OpLabel 209 OpBranch %32 210 %33 = OpLabel 211 OpBranch %31 212 %32 = OpLabel 213 OpReturn 214 OpFunctionEnd)"; 215 216 SinglePassRunAndMatch<Workaround1209>(text, false); 217} 218 219TEST_F(Workaround1209Test, RemoveOpUnreachableInAdjacentLoops) { 220 const std::string text = R"( 221 OpCapability Shader 222 %1 = OpExtInstImport "GLSL.std.450" 223 OpMemoryModel Logical GLSL450 224 OpEntryPoint Vertex %2 "main" %3 %4 %5 225 OpSource GLSL 400 226 OpSourceExtension "GL_ARB_separate_shader_objects" 227 OpSourceExtension "GL_ARB_shading_language_420pack" 228 OpName %2 "main" 229 OpName %3 "texcoord" 230 OpName %6 "buf" 231 OpMemberName %6 0 "MVP" 232 OpMemberName %6 1 "position" 233 OpMemberName %6 2 "attr" 234 OpName %7 "ubuf" 235 OpName %4 "gl_VertexIndex" 236 OpName %8 "gl_PerVertex" 237 OpMemberName %8 0 "gl_Position" 238 OpName %5 "" 239 OpDecorate %3 Location 0 240 OpDecorate %9 ArrayStride 16 241 OpDecorate %10 ArrayStride 16 242 OpMemberDecorate %6 0 ColMajor 243 OpMemberDecorate %6 0 Offset 0 244 OpMemberDecorate %6 0 MatrixStride 16 245 OpMemberDecorate %6 1 Offset 64 246 OpMemberDecorate %6 2 Offset 1216 247 OpDecorate %6 Block 248 OpDecorate %7 DescriptorSet 0 249 OpDecorate %7 Binding 0 250 OpDecorate %4 BuiltIn VertexIndex 251 OpMemberDecorate %8 0 BuiltIn Position 252 OpDecorate %8 Block 253 %11 = OpTypeVoid 254 %12 = OpTypeFunction %11 255 %13 = OpTypeFloat 32 256 %14 = OpTypeVector %13 4 257 %15 = OpTypePointer Output %14 258 %3 = OpVariable %15 Output 259 %16 = OpTypeMatrix %14 4 260 %17 = OpTypeInt 32 0 261 %18 = OpConstant %17 72 262 %9 = OpTypeArray %14 %18 263 %10 = OpTypeArray %14 %18 264 %6 = OpTypeStruct %16 %9 %10 265 %19 = OpTypePointer Uniform %6 266 %7 = OpVariable %19 Uniform 267 %20 = OpTypeInt 32 1 268 %21 = OpConstant %20 2 269 %22 = OpTypePointer Input %20 270 %4 = OpVariable %22 Input 271 %23 = OpTypePointer Uniform %14 272 %8 = OpTypeStruct %14 273 %24 = OpTypePointer Output %8 274 %5 = OpVariable %24 Output 275 %25 = OpConstant %20 0 276 %26 = OpConstant %20 1 277 %27 = OpConstant %13 1 278 %28 = OpConstantComposite %14 %27 %27 %27 %27 279 %2 = OpFunction %11 None %12 280 %29 = OpLabel 281 OpBranch %30 282 %30 = OpLabel 283; CHECK: OpLoopMerge [[merge1:%[a-zA-Z_\d]+]] 284 OpLoopMerge %31 %32 None 285 OpBranch %33 286 %33 = OpLabel 287; CHECK: OpSelectionMerge [[sel_merge1:%[a-zA-Z_\d]+]] 288 OpSelectionMerge %34 None 289 OpSwitch %26 %35 290 %35 = OpLabel 291 %36 = OpLoad %20 %4 292 %37 = OpAccessChain %23 %7 %21 %36 293 %38 = OpLoad %14 %37 294 OpStore %3 %38 295 %39 = OpAccessChain %15 %5 %25 296 OpStore %39 %28 297 OpBranch %31 298; CHECK: [[sel_merge1]] = OpLabel 299 %34 = OpLabel 300; CHECK-NEXT: OpBranch [[merge1]] 301 OpUnreachable 302 %32 = OpLabel 303 OpBranch %30 304 %31 = OpLabel 305; CHECK: OpLoopMerge [[merge2:%[a-zA-Z_\d]+]] 306 OpLoopMerge %40 %41 None 307 OpBranch %42 308 %42 = OpLabel 309; CHECK: OpSelectionMerge [[sel_merge2:%[a-zA-Z_\d]+]] 310 OpSelectionMerge %43 None 311 OpSwitch %26 %44 312 %44 = OpLabel 313 %45 = OpLoad %20 %4 314 %46 = OpAccessChain %23 %7 %21 %45 315 %47 = OpLoad %14 %46 316 OpStore %3 %47 317 %48 = OpAccessChain %15 %5 %25 318 OpStore %48 %28 319 OpBranch %40 320; CHECK: [[sel_merge2]] = OpLabel 321 %43 = OpLabel 322; CHECK-NEXT: OpBranch [[merge2]] 323 OpUnreachable 324 %41 = OpLabel 325 OpBranch %31 326 %40 = OpLabel 327 OpReturn 328 OpFunctionEnd)"; 329 330 SinglePassRunAndMatch<Workaround1209>(text, false); 331} 332 333TEST_F(Workaround1209Test, LeaveUnreachableNotInLoop) { 334 const std::string text = R"( 335 OpCapability Shader 336 %1 = OpExtInstImport "GLSL.std.450" 337 OpMemoryModel Logical GLSL450 338 OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_ 339 OpSource GLSL 400 340 OpSourceExtension "GL_ARB_separate_shader_objects" 341 OpSourceExtension "GL_ARB_shading_language_420pack" 342 OpName %main "main" 343 OpName %texcoord "texcoord" 344 OpName %buf "buf" 345 OpMemberName %buf 0 "MVP" 346 OpMemberName %buf 1 "position" 347 OpMemberName %buf 2 "attr" 348 OpName %ubuf "ubuf" 349 OpName %gl_VertexIndex "gl_VertexIndex" 350 OpName %gl_PerVertex "gl_PerVertex" 351 OpMemberName %gl_PerVertex 0 "gl_Position" 352 OpName %_ "" 353 OpDecorate %texcoord Location 0 354 OpDecorate %_arr_v4float_uint_72 ArrayStride 16 355 OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16 356 OpMemberDecorate %buf 0 ColMajor 357 OpMemberDecorate %buf 0 Offset 0 358 OpMemberDecorate %buf 0 MatrixStride 16 359 OpMemberDecorate %buf 1 Offset 64 360 OpMemberDecorate %buf 2 Offset 1216 361 OpDecorate %buf Block 362 OpDecorate %ubuf DescriptorSet 0 363 OpDecorate %ubuf Binding 0 364 OpDecorate %gl_VertexIndex BuiltIn VertexIndex 365 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position 366 OpDecorate %gl_PerVertex Block 367 %void = OpTypeVoid 368 %12 = OpTypeFunction %void 369 %float = OpTypeFloat 32 370 %v4float = OpTypeVector %float 4 371%_ptr_Output_v4float = OpTypePointer Output %v4float 372 %texcoord = OpVariable %_ptr_Output_v4float Output 373%mat4v4float = OpTypeMatrix %v4float 4 374 %uint = OpTypeInt 32 0 375 %uint_72 = OpConstant %uint 72 376%_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72 377%_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72 378 %buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0 379%_ptr_Uniform_buf = OpTypePointer Uniform %buf 380 %ubuf = OpVariable %_ptr_Uniform_buf Uniform 381 %int = OpTypeInt 32 1 382 %int_2 = OpConstant %int 2 383%_ptr_Input_int = OpTypePointer Input %int 384%gl_VertexIndex = OpVariable %_ptr_Input_int Input 385%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float 386%gl_PerVertex = OpTypeStruct %v4float 387%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex 388 %_ = OpVariable %_ptr_Output_gl_PerVertex Output 389 %int_0 = OpConstant %int 0 390 %int_1 = OpConstant %int 1 391 %float_1 = OpConstant %float 1 392 %28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 393 %main = OpFunction %void None %12 394 %29 = OpLabel 395 OpBranch %30 396 %30 = OpLabel 397 OpSelectionMerge %34 None 398 OpSwitch %int_1 %35 399 %35 = OpLabel 400 %36 = OpLoad %int %gl_VertexIndex 401 %37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36 402 %38 = OpLoad %v4float %37 403 OpStore %texcoord %38 404 %39 = OpAccessChain %_ptr_Output_v4float %_ %int_0 405 OpStore %39 %28 406 OpReturn 407 %34 = OpLabel 408; CHECK: OpUnreachable 409 OpUnreachable 410 OpFunctionEnd)"; 411 412 SinglePassRunAndMatch<Workaround1209>(text, false); 413} 414 415} // namespace 416} // namespace opt 417} // namespace spvtools 418