1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 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 <vector>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
19fd4e5da5Sopenharmony_ci#include "spirv-tools/libspirv.hpp"
20fd4e5da5Sopenharmony_ci#include "spirv-tools/optimizer.hpp"
21fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace opt {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciusing ::testing::Eq;
28fd4e5da5Sopenharmony_ci
29fd4e5da5Sopenharmony_ci// Return a string that contains the minimum instructions needed to form
30fd4e5da5Sopenharmony_ci// a valid module.  Other instructions can be appended to this string.
31fd4e5da5Sopenharmony_cistd::string Header() {
32fd4e5da5Sopenharmony_ci  return R"(OpCapability Shader
33fd4e5da5Sopenharmony_ciOpCapability Linkage
34fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
35fd4e5da5Sopenharmony_ci)";
36fd4e5da5Sopenharmony_ci}
37fd4e5da5Sopenharmony_ci
38fd4e5da5Sopenharmony_ciTEST(Optimizer, CanRunNullPassWithDistinctInputOutputVectors) {
39fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
40fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_in;
41fd4e5da5Sopenharmony_ci  tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid",
42fd4e5da5Sopenharmony_ci                 &binary_in);
43fd4e5da5Sopenharmony_ci
44fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
45fd4e5da5Sopenharmony_ci  opt.RegisterPass(CreateNullPass());
46fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_out;
47fd4e5da5Sopenharmony_ci  opt.Run(binary_in.data(), binary_in.size(), &binary_out);
48fd4e5da5Sopenharmony_ci
49fd4e5da5Sopenharmony_ci  std::string disassembly;
50fd4e5da5Sopenharmony_ci  tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly);
51fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly,
52fd4e5da5Sopenharmony_ci              Eq(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid\n"));
53fd4e5da5Sopenharmony_ci}
54fd4e5da5Sopenharmony_ci
55fd4e5da5Sopenharmony_ciTEST(Optimizer, CanRunTransformingPassWithDistinctInputOutputVectors) {
56fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
57fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_in;
58fd4e5da5Sopenharmony_ci  tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid",
59fd4e5da5Sopenharmony_ci                 &binary_in);
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
62fd4e5da5Sopenharmony_ci  opt.RegisterPass(CreateStripDebugInfoPass());
63fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_out;
64fd4e5da5Sopenharmony_ci  opt.Run(binary_in.data(), binary_in.size(), &binary_out);
65fd4e5da5Sopenharmony_ci
66fd4e5da5Sopenharmony_ci  std::string disassembly;
67fd4e5da5Sopenharmony_ci  tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly);
68fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(Header() + "%void = OpTypeVoid\n"));
69fd4e5da5Sopenharmony_ci}
70fd4e5da5Sopenharmony_ci
71fd4e5da5Sopenharmony_ciTEST(Optimizer, CanRunNullPassWithAliasedVectors) {
72fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
73fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
74fd4e5da5Sopenharmony_ci  tools.Assemble("OpName %foo \"foo\"\n%foo = OpTypeVoid", &binary);
75fd4e5da5Sopenharmony_ci
76fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
77fd4e5da5Sopenharmony_ci  opt.RegisterPass(CreateNullPass());
78fd4e5da5Sopenharmony_ci  opt.Run(binary.data(), binary.size(), &binary);  // This is the key.
79fd4e5da5Sopenharmony_ci
80fd4e5da5Sopenharmony_ci  std::string disassembly;
81fd4e5da5Sopenharmony_ci  tools.Disassemble(binary.data(), binary.size(), &disassembly);
82fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq("OpName %foo \"foo\"\n%foo = OpTypeVoid\n"));
83fd4e5da5Sopenharmony_ci}
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ciTEST(Optimizer, CanRunNullPassWithAliasedVectorDataButDifferentSize) {
86fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
87fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
88fd4e5da5Sopenharmony_ci  tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid", &binary);
89fd4e5da5Sopenharmony_ci
90fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
91fd4e5da5Sopenharmony_ci  opt.RegisterPass(CreateNullPass());
92fd4e5da5Sopenharmony_ci  auto orig_size = binary.size();
93fd4e5da5Sopenharmony_ci  // Now change the size.  Add a word that will be ignored
94fd4e5da5Sopenharmony_ci  // by the optimizer.
95fd4e5da5Sopenharmony_ci  binary.push_back(42);
96fd4e5da5Sopenharmony_ci  EXPECT_THAT(orig_size + 1, Eq(binary.size()));
97fd4e5da5Sopenharmony_ci  opt.Run(binary.data(), orig_size, &binary);  // This is the key.
98fd4e5da5Sopenharmony_ci  // The binary vector should have been rewritten.
99fd4e5da5Sopenharmony_ci  EXPECT_THAT(binary.size(), Eq(orig_size));
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ci  std::string disassembly;
102fd4e5da5Sopenharmony_ci  tools.Disassemble(binary.data(), binary.size(), &disassembly);
103fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly,
104fd4e5da5Sopenharmony_ci              Eq(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid\n"));
105fd4e5da5Sopenharmony_ci}
106fd4e5da5Sopenharmony_ci
107fd4e5da5Sopenharmony_ciTEST(Optimizer, CanRunTransformingPassWithAliasedVectors) {
108fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
109fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
110fd4e5da5Sopenharmony_ci  tools.Assemble(Header() + "OpName %foo \"foo\"\n%foo = OpTypeVoid", &binary);
111fd4e5da5Sopenharmony_ci
112fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
113fd4e5da5Sopenharmony_ci  opt.RegisterPass(CreateStripDebugInfoPass());
114fd4e5da5Sopenharmony_ci  opt.Run(binary.data(), binary.size(), &binary);  // This is the key
115fd4e5da5Sopenharmony_ci
116fd4e5da5Sopenharmony_ci  std::string disassembly;
117fd4e5da5Sopenharmony_ci  tools.Disassemble(binary.data(), binary.size(), &disassembly);
118fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(Header() + "%void = OpTypeVoid\n"));
119fd4e5da5Sopenharmony_ci}
120fd4e5da5Sopenharmony_ci
121fd4e5da5Sopenharmony_ciTEST(Optimizer, CanValidateFlags) {
122fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
123fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.FlagHasValidForm("bad-flag"));
124fd4e5da5Sopenharmony_ci  EXPECT_TRUE(opt.FlagHasValidForm("-O"));
125fd4e5da5Sopenharmony_ci  EXPECT_TRUE(opt.FlagHasValidForm("-Os"));
126fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.FlagHasValidForm("-O2"));
127fd4e5da5Sopenharmony_ci  EXPECT_TRUE(opt.FlagHasValidForm("--this_flag"));
128fd4e5da5Sopenharmony_ci}
129fd4e5da5Sopenharmony_ci
130fd4e5da5Sopenharmony_ciTEST(Optimizer, CanRegisterPassesFromFlags) {
131fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_0);
132fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
133fd4e5da5Sopenharmony_ci
134fd4e5da5Sopenharmony_ci  spv_message_level_t msg_level;
135fd4e5da5Sopenharmony_ci  const char* msg_fname;
136fd4e5da5Sopenharmony_ci  spv_position_t msg_position;
137fd4e5da5Sopenharmony_ci  const char* msg;
138fd4e5da5Sopenharmony_ci  auto examine_message = [&msg_level, &msg_fname, &msg_position, &msg](
139fd4e5da5Sopenharmony_ci                             spv_message_level_t ml, const char* f,
140fd4e5da5Sopenharmony_ci                             const spv_position_t& p, const char* m) {
141fd4e5da5Sopenharmony_ci    msg_level = ml;
142fd4e5da5Sopenharmony_ci    msg_fname = f;
143fd4e5da5Sopenharmony_ci    msg_position = p;
144fd4e5da5Sopenharmony_ci    msg = m;
145fd4e5da5Sopenharmony_ci  };
146fd4e5da5Sopenharmony_ci  opt.SetMessageConsumer(examine_message);
147fd4e5da5Sopenharmony_ci
148fd4e5da5Sopenharmony_ci  std::vector<std::string> pass_flags = {
149fd4e5da5Sopenharmony_ci      "--strip-debug",
150fd4e5da5Sopenharmony_ci      "--strip-nonsemantic",
151fd4e5da5Sopenharmony_ci      "--set-spec-const-default-value=23:42 21:12",
152fd4e5da5Sopenharmony_ci      "--if-conversion",
153fd4e5da5Sopenharmony_ci      "--freeze-spec-const",
154fd4e5da5Sopenharmony_ci      "--inline-entry-points-exhaustive",
155fd4e5da5Sopenharmony_ci      "--inline-entry-points-opaque",
156fd4e5da5Sopenharmony_ci      "--convert-local-access-chains",
157fd4e5da5Sopenharmony_ci      "--eliminate-dead-code-aggressive",
158fd4e5da5Sopenharmony_ci      "--eliminate-insert-extract",
159fd4e5da5Sopenharmony_ci      "--eliminate-local-single-block",
160fd4e5da5Sopenharmony_ci      "--eliminate-local-single-store",
161fd4e5da5Sopenharmony_ci      "--merge-blocks",
162fd4e5da5Sopenharmony_ci      "--merge-return",
163fd4e5da5Sopenharmony_ci      "--eliminate-dead-branches",
164fd4e5da5Sopenharmony_ci      "--eliminate-dead-functions",
165fd4e5da5Sopenharmony_ci      "--eliminate-local-multi-store",
166fd4e5da5Sopenharmony_ci      "--eliminate-dead-const",
167fd4e5da5Sopenharmony_ci      "--eliminate-dead-inserts",
168fd4e5da5Sopenharmony_ci      "--eliminate-dead-variables",
169fd4e5da5Sopenharmony_ci      "--fold-spec-const-op-composite",
170fd4e5da5Sopenharmony_ci      "--loop-unswitch",
171fd4e5da5Sopenharmony_ci      "--scalar-replacement=300",
172fd4e5da5Sopenharmony_ci      "--scalar-replacement",
173fd4e5da5Sopenharmony_ci      "--strength-reduction",
174fd4e5da5Sopenharmony_ci      "--unify-const",
175fd4e5da5Sopenharmony_ci      "--flatten-decorations",
176fd4e5da5Sopenharmony_ci      "--compact-ids",
177fd4e5da5Sopenharmony_ci      "--cfg-cleanup",
178fd4e5da5Sopenharmony_ci      "--local-redundancy-elimination",
179fd4e5da5Sopenharmony_ci      "--loop-invariant-code-motion",
180fd4e5da5Sopenharmony_ci      "--reduce-load-size",
181fd4e5da5Sopenharmony_ci      "--redundancy-elimination",
182fd4e5da5Sopenharmony_ci      "--private-to-local",
183fd4e5da5Sopenharmony_ci      "--remove-duplicates",
184fd4e5da5Sopenharmony_ci      "--workaround-1209",
185fd4e5da5Sopenharmony_ci      "--replace-invalid-opcode",
186fd4e5da5Sopenharmony_ci      "--simplify-instructions",
187fd4e5da5Sopenharmony_ci      "--ssa-rewrite",
188fd4e5da5Sopenharmony_ci      "--copy-propagate-arrays",
189fd4e5da5Sopenharmony_ci      "--loop-fission=20",
190fd4e5da5Sopenharmony_ci      "--loop-fusion=2",
191fd4e5da5Sopenharmony_ci      "--loop-unroll",
192fd4e5da5Sopenharmony_ci      "--vector-dce",
193fd4e5da5Sopenharmony_ci      "--loop-unroll-partial=3",
194fd4e5da5Sopenharmony_ci      "--loop-peeling",
195fd4e5da5Sopenharmony_ci      "--ccp",
196fd4e5da5Sopenharmony_ci      "-O",
197fd4e5da5Sopenharmony_ci      "-Os",
198fd4e5da5Sopenharmony_ci      "--legalize-hlsl"};
199fd4e5da5Sopenharmony_ci  EXPECT_TRUE(opt.RegisterPassesFromFlags(pass_flags));
200fd4e5da5Sopenharmony_ci
201fd4e5da5Sopenharmony_ci  // Test some invalid flags.
202fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("-O2"));
203fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
204fd4e5da5Sopenharmony_ci
205fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("-loop-unroll"));
206fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
207fd4e5da5Sopenharmony_ci
208fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("--set-spec-const-default-value"));
209fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
210fd4e5da5Sopenharmony_ci
211fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("--scalar-replacement=s"));
212fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
213fd4e5da5Sopenharmony_ci
214fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("--loop-fission=-4"));
215fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
216fd4e5da5Sopenharmony_ci
217fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("--loop-fusion=xx"));
218fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
219fd4e5da5Sopenharmony_ci
220fd4e5da5Sopenharmony_ci  EXPECT_FALSE(opt.RegisterPassFromFlag("--loop-unroll-partial"));
221fd4e5da5Sopenharmony_ci  EXPECT_EQ(msg_level, SPV_MSG_ERROR);
222fd4e5da5Sopenharmony_ci}
223fd4e5da5Sopenharmony_ci
224fd4e5da5Sopenharmony_ci
225fd4e5da5Sopenharmony_ciTEST(Optimizer, RemoveNop) {
226fd4e5da5Sopenharmony_ci  // Test that OpNops are removed even if no optimizations are run.
227fd4e5da5Sopenharmony_ci  const std::string before = R"(OpCapability Shader
228fd4e5da5Sopenharmony_ciOpCapability Linkage
229fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
230fd4e5da5Sopenharmony_ci%void = OpTypeVoid
231fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
232fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %2
233fd4e5da5Sopenharmony_ci%4 = OpLabel
234fd4e5da5Sopenharmony_ciOpNop
235fd4e5da5Sopenharmony_ciOpReturn
236fd4e5da5Sopenharmony_ciOpFunctionEnd
237fd4e5da5Sopenharmony_ci)";
238fd4e5da5Sopenharmony_ci
239fd4e5da5Sopenharmony_ci  const std::string after = R"(OpCapability Shader
240fd4e5da5Sopenharmony_ciOpCapability Linkage
241fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
242fd4e5da5Sopenharmony_ci%void = OpTypeVoid
243fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
244fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %2
245fd4e5da5Sopenharmony_ci%4 = OpLabel
246fd4e5da5Sopenharmony_ciOpReturn
247fd4e5da5Sopenharmony_ciOpFunctionEnd
248fd4e5da5Sopenharmony_ci)";
249fd4e5da5Sopenharmony_ci
250fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
251fd4e5da5Sopenharmony_ci  {
252fd4e5da5Sopenharmony_ci    SpirvTools tools(SPV_ENV_VULKAN_1_1);
253fd4e5da5Sopenharmony_ci    tools.Assemble(before, &binary);
254fd4e5da5Sopenharmony_ci  }
255fd4e5da5Sopenharmony_ci
256fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_VULKAN_1_1);
257fd4e5da5Sopenharmony_ci
258fd4e5da5Sopenharmony_ci  std::vector<uint32_t> optimized;
259fd4e5da5Sopenharmony_ci  class ValidatorOptions validator_options;
260fd4e5da5Sopenharmony_ci  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
261fd4e5da5Sopenharmony_ci                      validator_options, true))
262fd4e5da5Sopenharmony_ci      << before << "\n";
263fd4e5da5Sopenharmony_ci  std::string disassembly;
264fd4e5da5Sopenharmony_ci  {
265fd4e5da5Sopenharmony_ci    SpirvTools tools(SPV_ENV_VULKAN_1_1);
266fd4e5da5Sopenharmony_ci    tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
267fd4e5da5Sopenharmony_ci  }
268fd4e5da5Sopenharmony_ci
269fd4e5da5Sopenharmony_ci  EXPECT_EQ(after, disassembly)
270fd4e5da5Sopenharmony_ci      << "Was expecting the OpNop to have been removed.";
271fd4e5da5Sopenharmony_ci}
272fd4e5da5Sopenharmony_ci
273fd4e5da5Sopenharmony_ciTEST(Optimizer, AvoidIntegrityCheckForExtraLineInfo) {
274fd4e5da5Sopenharmony_ci  // Test that it avoids the integrity check when no optimizations are run and
275fd4e5da5Sopenharmony_ci  // OpLines are propagated.
276fd4e5da5Sopenharmony_ci  const std::string before = R"(OpCapability Shader
277fd4e5da5Sopenharmony_ciOpCapability Linkage
278fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
279fd4e5da5Sopenharmony_ci%1 = OpString "Test"
280fd4e5da5Sopenharmony_ci%void = OpTypeVoid
281fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void
282fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
283fd4e5da5Sopenharmony_ci%_ptr_Function_uint = OpTypePointer Function %uint
284fd4e5da5Sopenharmony_ci%6 = OpFunction %void None %3
285fd4e5da5Sopenharmony_ci%7 = OpLabel
286fd4e5da5Sopenharmony_ciOpLine %1 10 0
287fd4e5da5Sopenharmony_ci%8 = OpVariable %_ptr_Function_uint Function
288fd4e5da5Sopenharmony_ciOpLine %1 10 0
289fd4e5da5Sopenharmony_ci%9 = OpVariable %_ptr_Function_uint Function
290fd4e5da5Sopenharmony_ciOpLine %1 20 0
291fd4e5da5Sopenharmony_ciOpReturn
292fd4e5da5Sopenharmony_ciOpFunctionEnd
293fd4e5da5Sopenharmony_ci)";
294fd4e5da5Sopenharmony_ci
295fd4e5da5Sopenharmony_ci  const std::string after = R"(OpCapability Shader
296fd4e5da5Sopenharmony_ciOpCapability Linkage
297fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
298fd4e5da5Sopenharmony_ci%1 = OpString "Test"
299fd4e5da5Sopenharmony_ci%void = OpTypeVoid
300fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void
301fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
302fd4e5da5Sopenharmony_ci%_ptr_Function_uint = OpTypePointer Function %uint
303fd4e5da5Sopenharmony_ci%6 = OpFunction %void None %3
304fd4e5da5Sopenharmony_ci%7 = OpLabel
305fd4e5da5Sopenharmony_ciOpLine %1 10 0
306fd4e5da5Sopenharmony_ci%8 = OpVariable %_ptr_Function_uint Function
307fd4e5da5Sopenharmony_ci%9 = OpVariable %_ptr_Function_uint Function
308fd4e5da5Sopenharmony_ciOpLine %1 20 0
309fd4e5da5Sopenharmony_ciOpReturn
310fd4e5da5Sopenharmony_ciOpFunctionEnd
311fd4e5da5Sopenharmony_ci)";
312fd4e5da5Sopenharmony_ci
313fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
314fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_VULKAN_1_1);
315fd4e5da5Sopenharmony_ci  tools.Assemble(before, &binary);
316fd4e5da5Sopenharmony_ci
317fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_VULKAN_1_1);
318fd4e5da5Sopenharmony_ci
319fd4e5da5Sopenharmony_ci  std::vector<uint32_t> optimized;
320fd4e5da5Sopenharmony_ci  class ValidatorOptions validator_options;
321fd4e5da5Sopenharmony_ci  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
322fd4e5da5Sopenharmony_ci                      validator_options, true))
323fd4e5da5Sopenharmony_ci      << before << "\n";
324fd4e5da5Sopenharmony_ci
325fd4e5da5Sopenharmony_ci  std::string disassembly;
326fd4e5da5Sopenharmony_ci  tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
327fd4e5da5Sopenharmony_ci
328fd4e5da5Sopenharmony_ci  EXPECT_EQ(after, disassembly)
329fd4e5da5Sopenharmony_ci      << "Was expecting the OpLine to have been propagated.";
330fd4e5da5Sopenharmony_ci}
331fd4e5da5Sopenharmony_ci
332fd4e5da5Sopenharmony_ciTEST(Optimizer, AvoidIntegrityCheckForDebugScope) {
333fd4e5da5Sopenharmony_ci  // Test that it avoids the integrity check when the code contains DebugScope.
334fd4e5da5Sopenharmony_ci  const std::string before = R"(OpCapability Shader
335fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.DebugInfo.100"
336fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
337fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
338fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
339fd4e5da5Sopenharmony_ci%3 = OpString "simple_vs.hlsl"
340fd4e5da5Sopenharmony_ciOpSource HLSL 600 %3
341fd4e5da5Sopenharmony_ciOpName %main "main"
342fd4e5da5Sopenharmony_ci%void = OpTypeVoid
343fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
344fd4e5da5Sopenharmony_ci%6 = OpExtInst %void %1 DebugSource %3
345fd4e5da5Sopenharmony_ci%7 = OpExtInst %void %1 DebugCompilationUnit 2 4 %6 HLSL
346fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5
347fd4e5da5Sopenharmony_ci%14 = OpLabel
348fd4e5da5Sopenharmony_ci%26 = OpExtInst %void %1 DebugScope %7
349fd4e5da5Sopenharmony_ciOpReturn
350fd4e5da5Sopenharmony_ci%27 = OpExtInst %void %1 DebugNoScope
351fd4e5da5Sopenharmony_ciOpFunctionEnd
352fd4e5da5Sopenharmony_ci)";
353fd4e5da5Sopenharmony_ci
354fd4e5da5Sopenharmony_ci  const std::string after = R"(OpCapability Shader
355fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.DebugInfo.100"
356fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
357fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main"
358fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
359fd4e5da5Sopenharmony_ci%3 = OpString "simple_vs.hlsl"
360fd4e5da5Sopenharmony_ciOpSource HLSL 600 %3
361fd4e5da5Sopenharmony_ciOpName %main "main"
362fd4e5da5Sopenharmony_ci%void = OpTypeVoid
363fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void
364fd4e5da5Sopenharmony_ci%6 = OpExtInst %void %1 DebugSource %3
365fd4e5da5Sopenharmony_ci%7 = OpExtInst %void %1 DebugCompilationUnit 2 4 %6 HLSL
366fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5
367fd4e5da5Sopenharmony_ci%8 = OpLabel
368fd4e5da5Sopenharmony_ci%11 = OpExtInst %void %1 DebugScope %7
369fd4e5da5Sopenharmony_ciOpReturn
370fd4e5da5Sopenharmony_ci%12 = OpExtInst %void %1 DebugNoScope
371fd4e5da5Sopenharmony_ciOpFunctionEnd
372fd4e5da5Sopenharmony_ci)";
373fd4e5da5Sopenharmony_ci
374fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
375fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_VULKAN_1_1);
376fd4e5da5Sopenharmony_ci  tools.Assemble(before, &binary);
377fd4e5da5Sopenharmony_ci
378fd4e5da5Sopenharmony_ci  Optimizer opt(SPV_ENV_VULKAN_1_1);
379fd4e5da5Sopenharmony_ci
380fd4e5da5Sopenharmony_ci  std::vector<uint32_t> optimized;
381fd4e5da5Sopenharmony_ci  ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized))
382fd4e5da5Sopenharmony_ci      << before << "\n";
383fd4e5da5Sopenharmony_ci
384fd4e5da5Sopenharmony_ci  std::string disassembly;
385fd4e5da5Sopenharmony_ci  tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
386fd4e5da5Sopenharmony_ci
387fd4e5da5Sopenharmony_ci  EXPECT_EQ(after, disassembly)
388fd4e5da5Sopenharmony_ci      << "Was expecting the result id of DebugScope to have been changed.";
389fd4e5da5Sopenharmony_ci}
390fd4e5da5Sopenharmony_ci
391fd4e5da5Sopenharmony_ci}  // namespace
392fd4e5da5Sopenharmony_ci}  // namespace opt
393fd4e5da5Sopenharmony_ci}  // namespace spvtools
394