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