// Copyright (c) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <algorithm>
#include <cstdarg>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_set>
#include "gmock/gmock.h"
#include "test/opt/assembly_builder.h"
#include "test/opt/pass_fixture.h"
#include "test/opt/pass_utils.h"
namespace spvtools {
namespace opt {
namespace {
using Workaround1209Test = PassTest<::testing::Test>;
TEST_F(Workaround1209Test, RemoveOpUnreachableInLoop) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_
OpSource GLSL 400
OpSourceExtension "GL_ARB_separate_shader_objects"
OpSourceExtension "GL_ARB_shading_language_420pack"
OpName %main "main"
OpName %texcoord "texcoord"
OpName %buf "buf"
OpMemberName %buf 0 "MVP"
OpMemberName %buf 1 "position"
OpMemberName %buf 2 "attr"
OpName %ubuf "ubuf"
OpName %gl_VertexIndex "gl_VertexIndex"
OpName %gl_PerVertex "gl_PerVertex"
OpMemberName %gl_PerVertex 0 "gl_Position"
OpName %_ ""
OpDecorate %texcoord Location 0
OpDecorate %_arr_v4float_uint_72 ArrayStride 16
OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16
OpMemberDecorate %buf 0 ColMajor
OpMemberDecorate %buf 0 Offset 0
OpMemberDecorate %buf 0 MatrixStride 16
OpMemberDecorate %buf 1 Offset 64
OpMemberDecorate %buf 2 Offset 1216
OpDecorate %buf Block
OpDecorate %ubuf DescriptorSet 0
OpDecorate %ubuf Binding 0
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
OpDecorate %gl_PerVertex Block
%void = OpTypeVoid
%12 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%texcoord = OpVariable %_ptr_Output_v4float Output
%mat4v4float = OpTypeMatrix %v4float 4
%uint = OpTypeInt 32 0
%uint_72 = OpConstant %uint 72
%_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72
%_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72
%buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0
%_ptr_Uniform_buf = OpTypePointer Uniform %buf
%ubuf = OpVariable %_ptr_Uniform_buf Uniform
%int = OpTypeInt 32 1
%int_2 = OpConstant %int 2
%_ptr_Input_int = OpTypePointer Input %int
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%gl_PerVertex = OpTypeStruct %v4float
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%float_1 = OpConstant %float 1
%28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%main = OpFunction %void None %12
%29 = OpLabel
OpBranch %30
%30 = OpLabel
; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]]
OpLoopMerge %31 %32 None
OpBranch %33
%33 = OpLabel
; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]]
OpSelectionMerge %34 None
OpSwitch %int_1 %35
%35 = OpLabel
%36 = OpLoad %int %gl_VertexIndex
%37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36
%38 = OpLoad %v4float %37
OpStore %texcoord %38
%39 = OpAccessChain %_ptr_Output_v4float %_ %int_0
OpStore %39 %28
OpBranch %31
; CHECK: [[sel_merge]] = OpLabel
%34 = OpLabel
; CHECK-NEXT: OpBranch [[merge]]
OpUnreachable
%32 = OpLabel
OpBranch %30
%31 = OpLabel
OpReturn
OpFunctionEnd)";
SinglePassRunAndMatch<Workaround1209>(text, false);
}
TEST_F(Workaround1209Test, RemoveOpUnreachableInNestedLoop) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %2 "main" %3 %4 %5
OpSource GLSL 400
OpSourceExtension "GL_ARB_separate_shader_objects"
OpSourceExtension "GL_ARB_shading_language_420pack"
OpName %2 "main"
OpName %3 "texcoord"
OpName %6 "buf"
OpMemberName %6 0 "MVP"
OpMemberName %6 1 "position"
OpMemberName %6 2 "attr"
OpName %7 "ubuf"
OpName %4 "gl_VertexIndex"
OpName %8 "gl_PerVertex"
OpMemberName %8 0 "gl_Position"
OpName %5 ""
OpDecorate %3 Location 0
OpDecorate %9 ArrayStride 16
OpDecorate %10 ArrayStride 16
OpMemberDecorate %6 0 ColMajor
OpMemberDecorate %6 0 Offset 0
OpMemberDecorate %6 0 MatrixStride 16
OpMemberDecorate %6 1 Offset 64
OpMemberDecorate %6 2 Offset 1216
OpDecorate %6 Block
OpDecorate %7 DescriptorSet 0
OpDecorate %7 Binding 0
OpDecorate %4 BuiltIn VertexIndex
OpMemberDecorate %8 0 BuiltIn Position
OpDecorate %8 Block
%11 = OpTypeVoid
%12 = OpTypeFunction %11
%13 = OpTypeFloat 32
%14 = OpTypeVector %13 4
%15 = OpTypePointer Output %14
%3 = OpVariable %15 Output
%16 = OpTypeMatrix %14 4
%17 = OpTypeInt 32 0
%18 = OpConstant %17 72
%9 = OpTypeArray %14 %18
%10 = OpTypeArray %14 %18
%6 = OpTypeStruct %16 %9 %10
%19 = OpTypePointer Uniform %6
%7 = OpVariable %19 Uniform
%20 = OpTypeInt 32 1
%21 = OpConstant %20 2
%22 = OpTypePointer Input %20
%4 = OpVariable %22 Input
%23 = OpTypePointer Uniform %14
%8 = OpTypeStruct %14
%24 = OpTypePointer Output %8
%5 = OpVariable %24 Output
%25 = OpConstant %20 0
%26 = OpConstant %20 1
%27 = OpConstant %13 1
%28 = OpConstantComposite %14 %27 %27 %27 %27
%2 = OpFunction %11 None %12
%29 = OpLabel
OpBranch %31
%31 = OpLabel
; CHECK: OpLoopMerge
OpLoopMerge %32 %33 None
OpBranch %30
%30 = OpLabel
; CHECK: OpLoopMerge [[merge:%[a-zA-Z_\d]+]]
OpLoopMerge %34 %35 None
OpBranch %36
%36 = OpLabel
; CHECK: OpSelectionMerge [[sel_merge:%[a-zA-Z_\d]+]]
OpSelectionMerge %37 None
OpSwitch %26 %38
%38 = OpLabel
%39 = OpLoad %20 %4
%40 = OpAccessChain %23 %7 %21 %39
%41 = OpLoad %14 %40
OpStore %3 %41
%42 = OpAccessChain %15 %5 %25
OpStore %42 %28
OpBranch %34
; CHECK: [[sel_merge]] = OpLabel
%37 = OpLabel
; CHECK-NEXT: OpBranch [[merge]]
OpUnreachable
%35 = OpLabel
OpBranch %30
%34 = OpLabel
OpBranch %32
%33 = OpLabel
OpBranch %31
%32 = OpLabel
OpReturn
OpFunctionEnd)";
SinglePassRunAndMatch<Workaround1209>(text, false);
}
TEST_F(Workaround1209Test, RemoveOpUnreachableInAdjacentLoops) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %2 "main" %3 %4 %5
OpSource GLSL 400
OpSourceExtension "GL_ARB_separate_shader_objects"
OpSourceExtension "GL_ARB_shading_language_420pack"
OpName %2 "main"
OpName %3 "texcoord"
OpName %6 "buf"
OpMemberName %6 0 "MVP"
OpMemberName %6 1 "position"
OpMemberName %6 2 "attr"
OpName %7 "ubuf"
OpName %4 "gl_VertexIndex"
OpName %8 "gl_PerVertex"
OpMemberName %8 0 "gl_Position"
OpName %5 ""
OpDecorate %3 Location 0
OpDecorate %9 ArrayStride 16
OpDecorate %10 ArrayStride 16
OpMemberDecorate %6 0 ColMajor
OpMemberDecorate %6 0 Offset 0
OpMemberDecorate %6 0 MatrixStride 16
OpMemberDecorate %6 1 Offset 64
OpMemberDecorate %6 2 Offset 1216
OpDecorate %6 Block
OpDecorate %7 DescriptorSet 0
OpDecorate %7 Binding 0
OpDecorate %4 BuiltIn VertexIndex
OpMemberDecorate %8 0 BuiltIn Position
OpDecorate %8 Block
%11 = OpTypeVoid
%12 = OpTypeFunction %11
%13 = OpTypeFloat 32
%14 = OpTypeVector %13 4
%15 = OpTypePointer Output %14
%3 = OpVariable %15 Output
%16 = OpTypeMatrix %14 4
%17 = OpTypeInt 32 0
%18 = OpConstant %17 72
%9 = OpTypeArray %14 %18
%10 = OpTypeArray %14 %18
%6 = OpTypeStruct %16 %9 %10
%19 = OpTypePointer Uniform %6
%7 = OpVariable %19 Uniform
%20 = OpTypeInt 32 1
%21 = OpConstant %20 2
%22 = OpTypePointer Input %20
%4 = OpVariable %22 Input
%23 = OpTypePointer Uniform %14
%8 = OpTypeStruct %14
%24 = OpTypePointer Output %8
%5 = OpVariable %24 Output
%25 = OpConstant %20 0
%26 = OpConstant %20 1
%27 = OpConstant %13 1
%28 = OpConstantComposite %14 %27 %27 %27 %27
%2 = OpFunction %11 None %12
%29 = OpLabel
OpBranch %30
%30 = OpLabel
; CHECK: OpLoopMerge [[merge1:%[a-zA-Z_\d]+]]
OpLoopMerge %31 %32 None
OpBranch %33
%33 = OpLabel
; CHECK: OpSelectionMerge [[sel_merge1:%[a-zA-Z_\d]+]]
OpSelectionMerge %34 None
OpSwitch %26 %35
%35 = OpLabel
%36 = OpLoad %20 %4
%37 = OpAccessChain %23 %7 %21 %36
%38 = OpLoad %14 %37
OpStore %3 %38
%39 = OpAccessChain %15 %5 %25
OpStore %39 %28
OpBranch %31
; CHECK: [[sel_merge1]] = OpLabel
%34 = OpLabel
; CHECK-NEXT: OpBranch [[merge1]]
OpUnreachable
%32 = OpLabel
OpBranch %30
%31 = OpLabel
; CHECK: OpLoopMerge [[merge2:%[a-zA-Z_\d]+]]
OpLoopMerge %40 %41 None
OpBranch %42
%42 = OpLabel
; CHECK: OpSelectionMerge [[sel_merge2:%[a-zA-Z_\d]+]]
OpSelectionMerge %43 None
OpSwitch %26 %44
%44 = OpLabel
%45 = OpLoad %20 %4
%46 = OpAccessChain %23 %7 %21 %45
%47 = OpLoad %14 %46
OpStore %3 %47
%48 = OpAccessChain %15 %5 %25
OpStore %48 %28
OpBranch %40
; CHECK: [[sel_merge2]] = OpLabel
%43 = OpLabel
; CHECK-NEXT: OpBranch [[merge2]]
OpUnreachable
%41 = OpLabel
OpBranch %31
%40 = OpLabel
OpReturn
OpFunctionEnd)";
SinglePassRunAndMatch<Workaround1209>(text, false);
}
TEST_F(Workaround1209Test, LeaveUnreachableNotInLoop) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %main "main" %texcoord %gl_VertexIndex %_
OpSource GLSL 400
OpSourceExtension "GL_ARB_separate_shader_objects"
OpSourceExtension "GL_ARB_shading_language_420pack"
OpName %main "main"
OpName %texcoord "texcoord"
OpName %buf "buf"
OpMemberName %buf 0 "MVP"
OpMemberName %buf 1 "position"
OpMemberName %buf 2 "attr"
OpName %ubuf "ubuf"
OpName %gl_VertexIndex "gl_VertexIndex"
OpName %gl_PerVertex "gl_PerVertex"
OpMemberName %gl_PerVertex 0 "gl_Position"
OpName %_ ""
OpDecorate %texcoord Location 0
OpDecorate %_arr_v4float_uint_72 ArrayStride 16
OpDecorate %_arr_v4float_uint_72_0 ArrayStride 16
OpMemberDecorate %buf 0 ColMajor
OpMemberDecorate %buf 0 Offset 0
OpMemberDecorate %buf 0 MatrixStride 16
OpMemberDecorate %buf 1 Offset 64
OpMemberDecorate %buf 2 Offset 1216
OpDecorate %buf Block
OpDecorate %ubuf DescriptorSet 0
OpDecorate %ubuf Binding 0
OpDecorate %gl_VertexIndex BuiltIn VertexIndex
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
OpDecorate %gl_PerVertex Block
%void = OpTypeVoid
%12 = OpTypeFunction %void
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%texcoord = OpVariable %_ptr_Output_v4float Output
%mat4v4float = OpTypeMatrix %v4float 4
%uint = OpTypeInt 32 0
%uint_72 = OpConstant %uint 72
%_arr_v4float_uint_72 = OpTypeArray %v4float %uint_72
%_arr_v4float_uint_72_0 = OpTypeArray %v4float %uint_72
%buf = OpTypeStruct %mat4v4float %_arr_v4float_uint_72 %_arr_v4float_uint_72_0
%_ptr_Uniform_buf = OpTypePointer Uniform %buf
%ubuf = OpVariable %_ptr_Uniform_buf Uniform
%int = OpTypeInt 32 1
%int_2 = OpConstant %int 2
%_ptr_Input_int = OpTypePointer Input %int
%gl_VertexIndex = OpVariable %_ptr_Input_int Input
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%gl_PerVertex = OpTypeStruct %v4float
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%float_1 = OpConstant %float 1
%28 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
%main = OpFunction %void None %12
%29 = OpLabel
OpBranch %30
%30 = OpLabel
OpSelectionMerge %34 None
OpSwitch %int_1 %35
%35 = OpLabel
%36 = OpLoad %int %gl_VertexIndex
%37 = OpAccessChain %_ptr_Uniform_v4float %ubuf %int_2 %36
%38 = OpLoad %v4float %37
OpStore %texcoord %38
%39 = OpAccessChain %_ptr_Output_v4float %_ %int_0
OpStore %39 %28
OpReturn
%34 = OpLabel
; CHECK: OpUnreachable
OpUnreachable
OpFunctionEnd)";
SinglePassRunAndMatch<Workaround1209>(text, false);
}
} // namespace
} // namespace opt
} // namespace spvtools