1 // Copyright (c) 2016 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 <tuple>
17 #include <utility>
18 #include <vector>
19
20 #include "test/opt/pass_fixture.h"
21 #include "test/opt/pass_utils.h"
22
23 namespace spvtools {
24 namespace opt {
25 namespace {
26
27 struct FreezeSpecConstantValueTypeTestCase {
28 const char* type_decl;
29 const char* spec_const;
30 const char* expected_frozen_const;
31 };
32
33 using FreezeSpecConstantValueTypeTest =
34 PassTest<::testing::TestWithParam<FreezeSpecConstantValueTypeTestCase>>;
35
TEST_P(FreezeSpecConstantValueTypeTest,PrimaryType)36 TEST_P(FreezeSpecConstantValueTypeTest, PrimaryType) {
37 auto& test_case = GetParam();
38 std::vector<const char*> text = {"OpCapability Shader",
39 "OpMemoryModel Logical GLSL450",
40 test_case.type_decl, test_case.spec_const};
41 std::vector<const char*> expected = {
42 "OpCapability Shader", "OpMemoryModel Logical GLSL450",
43 test_case.type_decl, test_case.expected_frozen_const};
44 SinglePassRunAndCheck<FreezeSpecConstantValuePass>(
45 JoinAllInsts(text), JoinAllInsts(expected), /* skip_nop = */ false);
46 }
47
48 // Test each primary type.
49 INSTANTIATE_TEST_SUITE_P(
50 PrimaryTypeSpecConst, FreezeSpecConstantValueTypeTest,
51 ::testing::ValuesIn(std::vector<FreezeSpecConstantValueTypeTestCase>({
52 // Type declaration, original spec constant definition, expected frozen
53 // spec constants.
54 {"%int = OpTypeInt 32 1", "%2 = OpSpecConstant %int 1",
55 "%int_1 = OpConstant %int 1"},
56 {"%uint = OpTypeInt 32 0", "%2 = OpSpecConstant %uint 1",
57 "%uint_1 = OpConstant %uint 1"},
58 {"%float = OpTypeFloat 32", "%2 = OpSpecConstant %float 3.1415",
59 "%float_3_1415 = OpConstant %float 3.1415"},
60 {"%double = OpTypeFloat 64", "%2 = OpSpecConstant %double 3.141592653",
61 "%double_3_141592653 = OpConstant %double 3.141592653"},
62 {"%bool = OpTypeBool", "%2 = OpSpecConstantTrue %bool",
63 "%true = OpConstantTrue %bool"},
64 {"%bool = OpTypeBool", "%2 = OpSpecConstantFalse %bool",
65 "%false = OpConstantFalse %bool"},
66 })));
67
68 using FreezeSpecConstantValueRemoveDecorationTest = PassTest<::testing::Test>;
69
TEST_F(FreezeSpecConstantValueRemoveDecorationTest,RemoveDecorationInstWithSpecId)70 TEST_F(FreezeSpecConstantValueRemoveDecorationTest,
71 RemoveDecorationInstWithSpecId) {
72 std::vector<const char*> text = {
73 // clang-format off
74 "OpCapability Shader",
75 "OpCapability Float64",
76 "%1 = OpExtInstImport \"GLSL.std.450\"",
77 "OpMemoryModel Logical GLSL450",
78 "OpEntryPoint Vertex %main \"main\"",
79 "OpSource GLSL 450",
80 "OpSourceExtension \"GL_GOOGLE_cpp_style_line_directive\"",
81 "OpSourceExtension \"GL_GOOGLE_include_directive\"",
82 "OpName %main \"main\"",
83 "OpDecorate %3 SpecId 200",
84 "OpDecorate %4 SpecId 201",
85 "OpDecorate %5 SpecId 202",
86 "OpDecorate %6 SpecId 203",
87 "%void = OpTypeVoid",
88 "%8 = OpTypeFunction %void",
89 "%int = OpTypeInt 32 1",
90 "%3 = OpSpecConstant %int 3",
91 "%float = OpTypeFloat 32",
92 "%4 = OpSpecConstant %float 3.1415",
93 "%double = OpTypeFloat 64",
94 "%5 = OpSpecConstant %double 3.14159265358979",
95 "%bool = OpTypeBool",
96 "%6 = OpSpecConstantTrue %bool",
97 "%13 = OpSpecConstantFalse %bool",
98 "%main = OpFunction %void None %8",
99 "%14 = OpLabel",
100 "OpReturn",
101 "OpFunctionEnd",
102 // clang-format on
103 };
104 std::string expected_disassembly = SelectiveJoin(text, [](const char* line) {
105 return std::string(line).find("SpecId") != std::string::npos;
106 });
107 std::vector<std::pair<const char*, const char*>> replacement_pairs = {
108 {"%3 = OpSpecConstant %int 3", "%int_3 = OpConstant %int 3"},
109 {"%4 = OpSpecConstant %float 3.1415",
110 "%float_3_1415 = OpConstant %float 3.1415"},
111 {"%5 = OpSpecConstant %double 3.14159265358979",
112 "%double_3_14159265358979 = OpConstant %double 3.14159265358979"},
113 {"%6 = OpSpecConstantTrue ", "%true = OpConstantTrue "},
114 {"%13 = OpSpecConstantFalse ", "%false = OpConstantFalse "},
115 };
116 for (auto& p : replacement_pairs) {
117 EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second))
118 << "text:\n"
119 << expected_disassembly << "\n"
120 << "find_str:\n"
121 << p.first << "\n"
122 << "replace_str:\n"
123 << p.second << "\n";
124 }
125 SinglePassRunAndCheck<FreezeSpecConstantValuePass>(JoinAllInsts(text),
126 expected_disassembly,
127 /* skip_nop = */ true);
128 }
129
TEST_F(FreezeSpecConstantValueRemoveDecorationTest,RemoveDecorationForLocalSizeIdWithSpecId)130 TEST_F(FreezeSpecConstantValueRemoveDecorationTest,
131 RemoveDecorationForLocalSizeIdWithSpecId) {
132 std::vector<const char*> text = {
133 // clang-format off
134 "OpCapability Shader",
135 "%1 = OpExtInstImport \"GLSL.std.450\"",
136 "OpMemoryModel Logical GLSL450",
137 "OpEntryPoint GLCompute %2 \"main\"",
138 "OpExecutionModeId %2 LocalSizeId %uint_32 %uint_1 %uint_1_0",
139 "OpSource GLSL 450",
140 "OpDecorate %3 SpecId 18",
141 "OpDecorate %5 SpecId 19",
142 "%void = OpTypeVoid",
143 "%9 = OpTypeFunction %void",
144 "%uint = OpTypeInt 32 0",
145 "%uint_32 = OpSpecConstant %uint 32",
146 "%uint_1 = OpConstant %uint 1",
147 "%uint_1_0 = OpSpecConstant %uint 1",
148 "%2 = OpFunction %void None %9",
149 "%11 = OpLabel",
150 "OpReturn",
151 "OpFunctionEnd",
152 // clang-format on
153 };
154 std::string expected_disassembly = SelectiveJoin(text, [](const char* line) {
155 return std::string(line).find("SpecId") != std::string::npos;
156 });
157 std::vector<std::pair<const char*, const char*>> replacement_pairs = {
158 {"%uint_32 = OpSpecConstant %uint 32", "%uint_32 = OpConstant %uint 32"},
159 {"%uint_1_0 = OpSpecConstant %uint 1", "%uint_1_0 = OpConstant %uint 1"},
160 };
161 for (auto& p : replacement_pairs) {
162 EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second))
163 << "text:\n"
164 << expected_disassembly << "\n"
165 << "find_str:\n"
166 << p.first << "\n"
167 << "replace_str:\n"
168 << p.second << "\n";
169 }
170 SinglePassRunAndCheck<FreezeSpecConstantValuePass>(JoinAllInsts(text),
171 expected_disassembly,
172 /* skip_nop = */ true);
173 }
174
175 } // namespace
176 } // namespace opt
177 } // namespace spvtools
178