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