1fd4e5da5Sopenharmony_ci// Copyright (c) 2016 Google Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <string>
16fd4e5da5Sopenharmony_ci#include <tuple>
17fd4e5da5Sopenharmony_ci#include <utility>
18fd4e5da5Sopenharmony_ci#include <vector>
19fd4e5da5Sopenharmony_ci
20fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
21fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace opt {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_cistruct FreezeSpecConstantValueTypeTestCase {
28fd4e5da5Sopenharmony_ci  const char* type_decl;
29fd4e5da5Sopenharmony_ci  const char* spec_const;
30fd4e5da5Sopenharmony_ci  const char* expected_frozen_const;
31fd4e5da5Sopenharmony_ci};
32fd4e5da5Sopenharmony_ci
33fd4e5da5Sopenharmony_ciusing FreezeSpecConstantValueTypeTest =
34fd4e5da5Sopenharmony_ci    PassTest<::testing::TestWithParam<FreezeSpecConstantValueTypeTestCase>>;
35fd4e5da5Sopenharmony_ci
36fd4e5da5Sopenharmony_ciTEST_P(FreezeSpecConstantValueTypeTest, PrimaryType) {
37fd4e5da5Sopenharmony_ci  auto& test_case = GetParam();
38fd4e5da5Sopenharmony_ci  std::vector<const char*> text = {"OpCapability Shader",
39fd4e5da5Sopenharmony_ci                                   "OpMemoryModel Logical GLSL450",
40fd4e5da5Sopenharmony_ci                                   test_case.type_decl, test_case.spec_const};
41fd4e5da5Sopenharmony_ci  std::vector<const char*> expected = {
42fd4e5da5Sopenharmony_ci      "OpCapability Shader", "OpMemoryModel Logical GLSL450",
43fd4e5da5Sopenharmony_ci      test_case.type_decl, test_case.expected_frozen_const};
44fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<FreezeSpecConstantValuePass>(
45fd4e5da5Sopenharmony_ci      JoinAllInsts(text), JoinAllInsts(expected), /* skip_nop = */ false);
46fd4e5da5Sopenharmony_ci}
47fd4e5da5Sopenharmony_ci
48fd4e5da5Sopenharmony_ci// Test each primary type.
49fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
50fd4e5da5Sopenharmony_ci    PrimaryTypeSpecConst, FreezeSpecConstantValueTypeTest,
51fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<FreezeSpecConstantValueTypeTestCase>({
52fd4e5da5Sopenharmony_ci        // Type declaration, original spec constant definition, expected frozen
53fd4e5da5Sopenharmony_ci        // spec constants.
54fd4e5da5Sopenharmony_ci        {"%int = OpTypeInt 32 1", "%2 = OpSpecConstant %int 1",
55fd4e5da5Sopenharmony_ci         "%int_1 = OpConstant %int 1"},
56fd4e5da5Sopenharmony_ci        {"%uint = OpTypeInt 32 0", "%2 = OpSpecConstant %uint 1",
57fd4e5da5Sopenharmony_ci         "%uint_1 = OpConstant %uint 1"},
58fd4e5da5Sopenharmony_ci        {"%float = OpTypeFloat 32", "%2 = OpSpecConstant %float 3.1415",
59fd4e5da5Sopenharmony_ci         "%float_3_1415 = OpConstant %float 3.1415"},
60fd4e5da5Sopenharmony_ci        {"%double = OpTypeFloat 64", "%2 = OpSpecConstant %double 3.141592653",
61fd4e5da5Sopenharmony_ci         "%double_3_141592653 = OpConstant %double 3.141592653"},
62fd4e5da5Sopenharmony_ci        {"%bool = OpTypeBool", "%2 = OpSpecConstantTrue %bool",
63fd4e5da5Sopenharmony_ci         "%true = OpConstantTrue %bool"},
64fd4e5da5Sopenharmony_ci        {"%bool = OpTypeBool", "%2 = OpSpecConstantFalse %bool",
65fd4e5da5Sopenharmony_ci         "%false = OpConstantFalse %bool"},
66fd4e5da5Sopenharmony_ci    })));
67fd4e5da5Sopenharmony_ci
68fd4e5da5Sopenharmony_ciusing FreezeSpecConstantValueRemoveDecorationTest = PassTest<::testing::Test>;
69fd4e5da5Sopenharmony_ci
70fd4e5da5Sopenharmony_ciTEST_F(FreezeSpecConstantValueRemoveDecorationTest,
71fd4e5da5Sopenharmony_ci       RemoveDecorationInstWithSpecId) {
72fd4e5da5Sopenharmony_ci  std::vector<const char*> text = {
73fd4e5da5Sopenharmony_ci      // clang-format off
74fd4e5da5Sopenharmony_ci               "OpCapability Shader",
75fd4e5da5Sopenharmony_ci               "OpCapability Float64",
76fd4e5da5Sopenharmony_ci          "%1 = OpExtInstImport \"GLSL.std.450\"",
77fd4e5da5Sopenharmony_ci               "OpMemoryModel Logical GLSL450",
78fd4e5da5Sopenharmony_ci               "OpEntryPoint Vertex %main \"main\"",
79fd4e5da5Sopenharmony_ci               "OpSource GLSL 450",
80fd4e5da5Sopenharmony_ci               "OpSourceExtension \"GL_GOOGLE_cpp_style_line_directive\"",
81fd4e5da5Sopenharmony_ci               "OpSourceExtension \"GL_GOOGLE_include_directive\"",
82fd4e5da5Sopenharmony_ci               "OpName %main \"main\"",
83fd4e5da5Sopenharmony_ci               "OpDecorate %3 SpecId 200",
84fd4e5da5Sopenharmony_ci               "OpDecorate %4 SpecId 201",
85fd4e5da5Sopenharmony_ci               "OpDecorate %5 SpecId 202",
86fd4e5da5Sopenharmony_ci               "OpDecorate %6 SpecId 203",
87fd4e5da5Sopenharmony_ci       "%void = OpTypeVoid",
88fd4e5da5Sopenharmony_ci          "%8 = OpTypeFunction %void",
89fd4e5da5Sopenharmony_ci        "%int = OpTypeInt 32 1",
90fd4e5da5Sopenharmony_ci          "%3 = OpSpecConstant %int 3",
91fd4e5da5Sopenharmony_ci      "%float = OpTypeFloat 32",
92fd4e5da5Sopenharmony_ci          "%4 = OpSpecConstant %float 3.1415",
93fd4e5da5Sopenharmony_ci     "%double = OpTypeFloat 64",
94fd4e5da5Sopenharmony_ci          "%5 = OpSpecConstant %double 3.14159265358979",
95fd4e5da5Sopenharmony_ci       "%bool = OpTypeBool",
96fd4e5da5Sopenharmony_ci          "%6 = OpSpecConstantTrue %bool",
97fd4e5da5Sopenharmony_ci          "%13 = OpSpecConstantFalse %bool",
98fd4e5da5Sopenharmony_ci       "%main = OpFunction %void None %8",
99fd4e5da5Sopenharmony_ci         "%14 = OpLabel",
100fd4e5da5Sopenharmony_ci               "OpReturn",
101fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
102fd4e5da5Sopenharmony_ci      // clang-format on
103fd4e5da5Sopenharmony_ci  };
104fd4e5da5Sopenharmony_ci  std::string expected_disassembly = SelectiveJoin(text, [](const char* line) {
105fd4e5da5Sopenharmony_ci    return std::string(line).find("SpecId") != std::string::npos;
106fd4e5da5Sopenharmony_ci  });
107fd4e5da5Sopenharmony_ci  std::vector<std::pair<const char*, const char*>> replacement_pairs = {
108fd4e5da5Sopenharmony_ci      {"%3 = OpSpecConstant %int 3", "%int_3 = OpConstant %int 3"},
109fd4e5da5Sopenharmony_ci      {"%4 = OpSpecConstant %float 3.1415",
110fd4e5da5Sopenharmony_ci       "%float_3_1415 = OpConstant %float 3.1415"},
111fd4e5da5Sopenharmony_ci      {"%5 = OpSpecConstant %double 3.14159265358979",
112fd4e5da5Sopenharmony_ci       "%double_3_14159265358979 = OpConstant %double 3.14159265358979"},
113fd4e5da5Sopenharmony_ci      {"%6 = OpSpecConstantTrue ", "%true = OpConstantTrue "},
114fd4e5da5Sopenharmony_ci      {"%13 = OpSpecConstantFalse ", "%false = OpConstantFalse "},
115fd4e5da5Sopenharmony_ci  };
116fd4e5da5Sopenharmony_ci  for (auto& p : replacement_pairs) {
117fd4e5da5Sopenharmony_ci    EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second))
118fd4e5da5Sopenharmony_ci        << "text:\n"
119fd4e5da5Sopenharmony_ci        << expected_disassembly << "\n"
120fd4e5da5Sopenharmony_ci        << "find_str:\n"
121fd4e5da5Sopenharmony_ci        << p.first << "\n"
122fd4e5da5Sopenharmony_ci        << "replace_str:\n"
123fd4e5da5Sopenharmony_ci        << p.second << "\n";
124fd4e5da5Sopenharmony_ci  }
125fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<FreezeSpecConstantValuePass>(JoinAllInsts(text),
126fd4e5da5Sopenharmony_ci                                                     expected_disassembly,
127fd4e5da5Sopenharmony_ci                                                     /* skip_nop = */ true);
128fd4e5da5Sopenharmony_ci}
129fd4e5da5Sopenharmony_ci
130fd4e5da5Sopenharmony_ciTEST_F(FreezeSpecConstantValueRemoveDecorationTest,
131fd4e5da5Sopenharmony_ci       RemoveDecorationForLocalSizeIdWithSpecId) {
132fd4e5da5Sopenharmony_ci  std::vector<const char*> text = {
133fd4e5da5Sopenharmony_ci      // clang-format off
134fd4e5da5Sopenharmony_ci               "OpCapability Shader",
135fd4e5da5Sopenharmony_ci          "%1 = OpExtInstImport \"GLSL.std.450\"",
136fd4e5da5Sopenharmony_ci               "OpMemoryModel Logical GLSL450",
137fd4e5da5Sopenharmony_ci               "OpEntryPoint GLCompute %2 \"main\"",
138fd4e5da5Sopenharmony_ci               "OpExecutionModeId %2 LocalSizeId %uint_32 %uint_1 %uint_1_0",
139fd4e5da5Sopenharmony_ci               "OpSource GLSL 450",
140fd4e5da5Sopenharmony_ci               "OpDecorate %3 SpecId 18",
141fd4e5da5Sopenharmony_ci               "OpDecorate %5 SpecId 19",
142fd4e5da5Sopenharmony_ci       "%void = OpTypeVoid",
143fd4e5da5Sopenharmony_ci          "%9 = OpTypeFunction %void",
144fd4e5da5Sopenharmony_ci       "%uint = OpTypeInt 32 0",
145fd4e5da5Sopenharmony_ci    "%uint_32 = OpSpecConstant %uint 32",
146fd4e5da5Sopenharmony_ci     "%uint_1 = OpConstant %uint 1",
147fd4e5da5Sopenharmony_ci   "%uint_1_0 = OpSpecConstant %uint 1",
148fd4e5da5Sopenharmony_ci          "%2 = OpFunction %void None %9",
149fd4e5da5Sopenharmony_ci         "%11 = OpLabel",
150fd4e5da5Sopenharmony_ci               "OpReturn",
151fd4e5da5Sopenharmony_ci               "OpFunctionEnd",
152fd4e5da5Sopenharmony_ci      // clang-format on
153fd4e5da5Sopenharmony_ci  };
154fd4e5da5Sopenharmony_ci  std::string expected_disassembly = SelectiveJoin(text, [](const char* line) {
155fd4e5da5Sopenharmony_ci    return std::string(line).find("SpecId") != std::string::npos;
156fd4e5da5Sopenharmony_ci  });
157fd4e5da5Sopenharmony_ci  std::vector<std::pair<const char*, const char*>> replacement_pairs = {
158fd4e5da5Sopenharmony_ci      {"%uint_32 = OpSpecConstant %uint 32", "%uint_32 = OpConstant %uint 32"},
159fd4e5da5Sopenharmony_ci      {"%uint_1_0 = OpSpecConstant %uint 1", "%uint_1_0 = OpConstant %uint 1"},
160fd4e5da5Sopenharmony_ci  };
161fd4e5da5Sopenharmony_ci  for (auto& p : replacement_pairs) {
162fd4e5da5Sopenharmony_ci    EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second))
163fd4e5da5Sopenharmony_ci        << "text:\n"
164fd4e5da5Sopenharmony_ci        << expected_disassembly << "\n"
165fd4e5da5Sopenharmony_ci        << "find_str:\n"
166fd4e5da5Sopenharmony_ci        << p.first << "\n"
167fd4e5da5Sopenharmony_ci        << "replace_str:\n"
168fd4e5da5Sopenharmony_ci        << p.second << "\n";
169fd4e5da5Sopenharmony_ci  }
170fd4e5da5Sopenharmony_ci  SinglePassRunAndCheck<FreezeSpecConstantValuePass>(JoinAllInsts(text),
171fd4e5da5Sopenharmony_ci                                                     expected_disassembly,
172fd4e5da5Sopenharmony_ci                                                     /* skip_nop = */ true);
173fd4e5da5Sopenharmony_ci}
174fd4e5da5Sopenharmony_ci
175fd4e5da5Sopenharmony_ci}  // namespace
176fd4e5da5Sopenharmony_ci}  // namespace opt
177fd4e5da5Sopenharmony_ci}  // namespace spvtools
178