1 // Copyright (c) 2017 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 "source/opt/ir_context.h"
16 
17 #include <algorithm>
18 #include <memory>
19 #include <utility>
20 
21 #include "OpenCLDebugInfo100.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "source/opt/pass.h"
25 #include "test/opt/pass_fixture.h"
26 #include "test/opt/pass_utils.h"
27 
28 static const uint32_t kDebugDeclareOperandVariableIndex = 5;
29 static const uint32_t kDebugValueOperandValueIndex = 5;
30 
31 namespace spvtools {
32 namespace opt {
33 namespace {
34 
35 using Analysis = IRContext::Analysis;
36 using ::testing::Each;
37 using ::testing::UnorderedElementsAre;
38 
39 class NoopPassPreservesNothing : public Pass {
40  public:
NoopPassPreservesNothing(Status s)41   NoopPassPreservesNothing(Status s) : Pass(), status_to_return_(s) {}
42 
name() const43   const char* name() const override { return "noop-pass"; }
Process()44   Status Process() override { return status_to_return_; }
45 
46  private:
47   Status status_to_return_;
48 };
49 
50 class NoopPassPreservesAll : public Pass {
51  public:
NoopPassPreservesAll(Status s)52   NoopPassPreservesAll(Status s) : Pass(), status_to_return_(s) {}
53 
name() const54   const char* name() const override { return "noop-pass"; }
Process()55   Status Process() override { return status_to_return_; }
56 
GetPreservedAnalyses()57   Analysis GetPreservedAnalyses() override {
58     return Analysis(IRContext::kAnalysisEnd - 1);
59   }
60 
61  private:
62   Status status_to_return_;
63 };
64 
65 class NoopPassPreservesFirst : public Pass {
66  public:
NoopPassPreservesFirst(Status s)67   NoopPassPreservesFirst(Status s) : Pass(), status_to_return_(s) {}
68 
name() const69   const char* name() const override { return "noop-pass"; }
Process()70   Status Process() override { return status_to_return_; }
71 
GetPreservedAnalyses()72   Analysis GetPreservedAnalyses() override { return IRContext::kAnalysisBegin; }
73 
74  private:
75   Status status_to_return_;
76 };
77 
78 using IRContextTest = PassTest<::testing::Test>;
79 
TEST_F(IRContextTest,IndividualValidAfterBuild)80 TEST_F(IRContextTest, IndividualValidAfterBuild) {
81   std::unique_ptr<Module> module(new Module());
82   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
83                          spvtools::MessageConsumer());
84 
85   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
86        i <<= 1) {
87     localContext.BuildInvalidAnalyses(i);
88     EXPECT_TRUE(localContext.AreAnalysesValid(i));
89   }
90 }
91 
TEST_F(IRContextTest,DontRebuildValidAnalysis)92 TEST_F(IRContextTest, DontRebuildValidAnalysis) {
93   std::unique_ptr<Module> module(new Module());
94   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
95                          spvtools::MessageConsumer());
96 
97   auto* oldCfg = localContext.cfg();
98   auto* oldDefUse = localContext.get_def_use_mgr();
99   localContext.BuildInvalidAnalyses(IRContext::kAnalysisCFG |
100                                     IRContext::kAnalysisDefUse);
101   auto* newCfg = localContext.cfg();
102   auto* newDefUse = localContext.get_def_use_mgr();
103   EXPECT_EQ(oldCfg, newCfg);
104   EXPECT_EQ(oldDefUse, newDefUse);
105 }
106 
TEST_F(IRContextTest,AllValidAfterBuild)107 TEST_F(IRContextTest, AllValidAfterBuild) {
108   std::unique_ptr<Module> module = MakeUnique<Module>();
109   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
110                          spvtools::MessageConsumer());
111 
112   Analysis built_analyses = IRContext::kAnalysisNone;
113   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
114        i <<= 1) {
115     localContext.BuildInvalidAnalyses(i);
116     built_analyses |= i;
117   }
118   EXPECT_TRUE(localContext.AreAnalysesValid(built_analyses));
119 }
120 
TEST_F(IRContextTest,AllValidAfterPassNoChange)121 TEST_F(IRContextTest, AllValidAfterPassNoChange) {
122   std::unique_ptr<Module> module = MakeUnique<Module>();
123   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
124                          spvtools::MessageConsumer());
125 
126   Analysis built_analyses = IRContext::kAnalysisNone;
127   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
128        i <<= 1) {
129     localContext.BuildInvalidAnalyses(i);
130     built_analyses |= i;
131   }
132 
133   NoopPassPreservesNothing pass(Pass::Status::SuccessWithoutChange);
134   Pass::Status s = pass.Run(&localContext);
135   EXPECT_EQ(s, Pass::Status::SuccessWithoutChange);
136   EXPECT_TRUE(localContext.AreAnalysesValid(built_analyses));
137 }
138 
TEST_F(IRContextTest,NoneValidAfterPassWithChange)139 TEST_F(IRContextTest, NoneValidAfterPassWithChange) {
140   std::unique_ptr<Module> module = MakeUnique<Module>();
141   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
142                          spvtools::MessageConsumer());
143 
144   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
145        i <<= 1) {
146     localContext.BuildInvalidAnalyses(i);
147   }
148 
149   NoopPassPreservesNothing pass(Pass::Status::SuccessWithChange);
150   Pass::Status s = pass.Run(&localContext);
151   EXPECT_EQ(s, Pass::Status::SuccessWithChange);
152   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
153        i <<= 1) {
154     EXPECT_FALSE(localContext.AreAnalysesValid(i));
155   }
156 }
157 
TEST_F(IRContextTest,AllPreservedAfterPassWithChange)158 TEST_F(IRContextTest, AllPreservedAfterPassWithChange) {
159   std::unique_ptr<Module> module = MakeUnique<Module>();
160   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
161                          spvtools::MessageConsumer());
162 
163   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
164        i <<= 1) {
165     localContext.BuildInvalidAnalyses(i);
166   }
167 
168   NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
169   Pass::Status s = pass.Run(&localContext);
170   EXPECT_EQ(s, Pass::Status::SuccessWithChange);
171   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
172        i <<= 1) {
173     EXPECT_TRUE(localContext.AreAnalysesValid(i));
174   }
175 }
176 
TEST_F(IRContextTest,PreserveFirstOnlyAfterPassWithChange)177 TEST_F(IRContextTest, PreserveFirstOnlyAfterPassWithChange) {
178   std::unique_ptr<Module> module = MakeUnique<Module>();
179   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, std::move(module),
180                          spvtools::MessageConsumer());
181 
182   for (Analysis i = IRContext::kAnalysisBegin; i < IRContext::kAnalysisEnd;
183        i <<= 1) {
184     localContext.BuildInvalidAnalyses(i);
185   }
186 
187   NoopPassPreservesFirst pass(Pass::Status::SuccessWithChange);
188   Pass::Status s = pass.Run(&localContext);
189   EXPECT_EQ(s, Pass::Status::SuccessWithChange);
190   EXPECT_TRUE(localContext.AreAnalysesValid(IRContext::kAnalysisBegin));
191   for (Analysis i = IRContext::kAnalysisBegin << 1; i < IRContext::kAnalysisEnd;
192        i <<= 1) {
193     EXPECT_FALSE(localContext.AreAnalysesValid(i));
194   }
195 }
196 
TEST_F(IRContextTest,KillMemberName)197 TEST_F(IRContextTest, KillMemberName) {
198   const std::string text = R"(
199               OpCapability Shader
200           %1 = OpExtInstImport "GLSL.std.450"
201                OpMemoryModel Logical GLSL450
202                OpEntryPoint Fragment %2 "main"
203                OpExecutionMode %2 OriginUpperLeft
204                OpSource GLSL 430
205                OpName %3 "stuff"
206                OpMemberName %3 0 "refZ"
207                OpMemberDecorate %3 0 Offset 0
208                OpDecorate %3 Block
209           %4 = OpTypeFloat 32
210           %3 = OpTypeStruct %4
211           %5 = OpTypeVoid
212           %6 = OpTypeFunction %5
213           %2 = OpFunction %5 None %6
214           %7 = OpLabel
215                OpReturn
216                OpFunctionEnd
217 )";
218 
219   std::unique_ptr<IRContext> context =
220       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
221 
222   // Build the decoration manager.
223   context->get_decoration_mgr();
224 
225   // Delete the OpTypeStruct.  Should delete the OpName, OpMemberName, and
226   // OpMemberDecorate associated with it.
227   context->KillDef(3);
228 
229   // Make sure all of the name are removed.
230   for (auto& inst : context->debugs2()) {
231     EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
232   }
233 
234   // Make sure all of the decorations are removed.
235   for (auto& inst : context->annotations()) {
236     EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
237   }
238 }
239 
TEST_F(IRContextTest,KillGroupDecoration)240 TEST_F(IRContextTest, KillGroupDecoration) {
241   const std::string text = R"(
242                OpCapability Shader
243           %1 = OpExtInstImport "GLSL.std.450"
244                OpMemoryModel Logical GLSL450
245                OpEntryPoint Fragment %2 "main"
246                OpExecutionMode %2 OriginUpperLeft
247                OpSource GLSL 430
248                OpDecorate %3 Restrict
249           %3 = OpDecorationGroup
250                OpGroupDecorate %3 %4 %5
251           %6 = OpTypeFloat 32
252           %7 = OpTypePointer Function %6
253           %8 = OpTypeStruct %6
254           %9 = OpTypeVoid
255          %10 = OpTypeFunction %9
256           %2 = OpFunction %9 None %10
257          %11 = OpLabel
258           %4 = OpVariable %7 Function
259           %5 = OpVariable %7 Function
260                OpReturn
261                OpFunctionEnd
262 )";
263 
264   std::unique_ptr<IRContext> context =
265       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
266 
267   // Build the decoration manager.
268   context->get_decoration_mgr();
269 
270   // Delete the second variable.
271   context->KillDef(5);
272 
273   // The three decorations instructions should still be there.  The first two
274   // should be the same, but the third should have %5 removed.
275 
276   // Check the OpDecorate instruction
277   auto inst = context->annotation_begin();
278   EXPECT_EQ(inst->opcode(), spv::Op::OpDecorate);
279   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
280 
281   // Check the OpDecorationGroup Instruction
282   ++inst;
283   EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
284   EXPECT_EQ(inst->result_id(), 3);
285 
286   // Check that %5 is no longer part of the group.
287   ++inst;
288   EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
289   EXPECT_EQ(inst->NumInOperands(), 2);
290   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
291   EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
292 
293   // Check that we are at the end.
294   ++inst;
295   EXPECT_EQ(inst, context->annotation_end());
296 }
297 
TEST_F(IRContextTest,TakeNextUniqueIdIncrementing)298 TEST_F(IRContextTest, TakeNextUniqueIdIncrementing) {
299   const uint32_t NUM_TESTS = 1000;
300   IRContext localContext(SPV_ENV_UNIVERSAL_1_2, nullptr);
301   for (uint32_t i = 1; i < NUM_TESTS; ++i)
302     EXPECT_EQ(i, localContext.TakeNextUniqueId());
303 }
304 
TEST_F(IRContextTest,KillGroupDecorationWitNoDecorations)305 TEST_F(IRContextTest, KillGroupDecorationWitNoDecorations) {
306   const std::string text = R"(
307                OpCapability Shader
308           %1 = OpExtInstImport "GLSL.std.450"
309                OpMemoryModel Logical GLSL450
310                OpEntryPoint Fragment %2 "main"
311                OpExecutionMode %2 OriginUpperLeft
312                OpSource GLSL 430
313           %3 = OpDecorationGroup
314                OpGroupDecorate %3 %4 %5
315           %6 = OpTypeFloat 32
316           %7 = OpTypePointer Function %6
317           %8 = OpTypeStruct %6
318           %9 = OpTypeVoid
319          %10 = OpTypeFunction %9
320           %2 = OpFunction %9 None %10
321          %11 = OpLabel
322           %4 = OpVariable %7 Function
323           %5 = OpVariable %7 Function
324                OpReturn
325                OpFunctionEnd
326 )";
327 
328   std::unique_ptr<IRContext> context =
329       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
330 
331   // Build the decoration manager.
332   context->get_decoration_mgr();
333 
334   // Delete the second variable.
335   context->KillDef(5);
336 
337   // The two decoration instructions should still be there.  The first one
338   // should be the same, but the second should have %5 removed.
339 
340   // Check the OpDecorationGroup Instruction
341   auto inst = context->annotation_begin();
342   EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
343   EXPECT_EQ(inst->result_id(), 3);
344 
345   // Check that %5 is no longer part of the group.
346   ++inst;
347   EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
348   EXPECT_EQ(inst->NumInOperands(), 2);
349   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
350   EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
351 
352   // Check that we are at the end.
353   ++inst;
354   EXPECT_EQ(inst, context->annotation_end());
355 }
356 
TEST_F(IRContextTest,KillDecorationGroup)357 TEST_F(IRContextTest, KillDecorationGroup) {
358   const std::string text = R"(
359                OpCapability Shader
360           %1 = OpExtInstImport "GLSL.std.450"
361                OpMemoryModel Logical GLSL450
362                OpEntryPoint Fragment %2 "main"
363                OpExecutionMode %2 OriginUpperLeft
364                OpSource GLSL 430
365           %3 = OpDecorationGroup
366                OpGroupDecorate %3 %4 %5
367           %6 = OpTypeFloat 32
368           %7 = OpTypePointer Function %6
369           %8 = OpTypeStruct %6
370           %9 = OpTypeVoid
371          %10 = OpTypeFunction %9
372           %2 = OpFunction %9 None %10
373          %11 = OpLabel
374           %4 = OpVariable %7 Function
375           %5 = OpVariable %7 Function
376                OpReturn
377                OpFunctionEnd
378 )";
379 
380   std::unique_ptr<IRContext> context =
381       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
382 
383   // Build the decoration manager.
384   context->get_decoration_mgr();
385 
386   // Delete the second variable.
387   context->KillDef(3);
388 
389   // Check the OpDecorationGroup Instruction is still there.
390   EXPECT_TRUE(context->annotations().empty());
391 }
392 
TEST_F(IRContextTest,KillFunctionFromDebugFunction)393 TEST_F(IRContextTest, KillFunctionFromDebugFunction) {
394   const std::string text = R"(
395                OpCapability Shader
396           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
397                OpMemoryModel Logical GLSL450
398                OpEntryPoint Fragment %2 "main"
399                OpExecutionMode %2 OriginUpperLeft
400           %3 = OpString "ps.hlsl"
401           %4 = OpString "foo"
402                OpSource HLSL 600
403        %void = OpTypeVoid
404           %6 = OpTypeFunction %void
405           %7 = OpExtInst %void %1 DebugSource %3
406           %8 = OpExtInst %void %1 DebugCompilationUnit 1 4 %7 HLSL
407           %9 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
408          %10 = OpExtInst %void %1 DebugFunction %4 %9 %7 1 1 %8 %4 FlagIsProtected|FlagIsPrivate 1 %11
409           %2 = OpFunction %void None %6
410          %12 = OpLabel
411                OpReturn
412                OpFunctionEnd
413          %11 = OpFunction %void None %6
414          %13 = OpLabel
415                OpReturn
416                OpFunctionEnd
417 )";
418 
419   std::unique_ptr<IRContext> context =
420       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
421 
422   // Delete the second variable.
423   context->KillDef(11);
424 
425   // Get DebugInfoNone id.
426   uint32_t debug_info_none_id = 0;
427   for (auto it = context->ext_inst_debuginfo_begin();
428        it != context->ext_inst_debuginfo_end(); ++it) {
429     if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
430       debug_info_none_id = it->result_id();
431     }
432   }
433   EXPECT_NE(0, debug_info_none_id);
434 
435   // Check the Function operand of DebugFunction is DebugInfoNone.
436   const uint32_t kDebugFunctionOperandFunctionIndex = 13;
437   bool checked = false;
438   for (auto it = context->ext_inst_debuginfo_begin();
439        it != context->ext_inst_debuginfo_end(); ++it) {
440     if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
441       EXPECT_FALSE(checked);
442       EXPECT_EQ(it->GetOperand(kDebugFunctionOperandFunctionIndex).words[0],
443                 debug_info_none_id);
444       checked = true;
445     }
446   }
447   EXPECT_TRUE(checked);
448 }
449 
TEST_F(IRContextTest,KillVariableFromDebugGlobalVariable)450 TEST_F(IRContextTest, KillVariableFromDebugGlobalVariable) {
451   const std::string text = R"(
452                OpCapability Shader
453           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
454                OpMemoryModel Logical GLSL450
455                OpEntryPoint Fragment %2 "main"
456                OpExecutionMode %2 OriginUpperLeft
457           %3 = OpString "ps.hlsl"
458           %4 = OpString "foo"
459           %5 = OpString "int"
460                OpSource HLSL 600
461        %uint = OpTypeInt 32 0
462     %uint_32 = OpConstant %uint 32
463 %_ptr_Private_uint = OpTypePointer Private %uint
464        %void = OpTypeVoid
465          %10 = OpTypeFunction %void
466          %11 = OpVariable %_ptr_Private_uint Private
467          %12 = OpExtInst %void %1 DebugSource %3
468          %13 = OpExtInst %void %1 DebugCompilationUnit 1 4 %12 HLSL
469          %14 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 Signed
470          %15 = OpExtInst %void %1 DebugGlobalVariable %4 %14 %12 1 12 %13 %4 %11 FlagIsDefinition
471           %2 = OpFunction %void None %10
472          %16 = OpLabel
473                OpReturn
474                OpFunctionEnd
475 )";
476 
477   std::unique_ptr<IRContext> context =
478       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
479 
480   // Delete the second variable.
481   context->KillDef(11);
482 
483   // Get DebugInfoNone id.
484   uint32_t debug_info_none_id = 0;
485   for (auto it = context->ext_inst_debuginfo_begin();
486        it != context->ext_inst_debuginfo_end(); ++it) {
487     if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
488       debug_info_none_id = it->result_id();
489     }
490   }
491   EXPECT_NE(0, debug_info_none_id);
492 
493   // Check the Function operand of DebugFunction is DebugInfoNone.
494   const uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
495   bool checked = false;
496   for (auto it = context->ext_inst_debuginfo_begin();
497        it != context->ext_inst_debuginfo_end(); ++it) {
498     if (it->GetOpenCL100DebugOpcode() ==
499         OpenCLDebugInfo100DebugGlobalVariable) {
500       EXPECT_FALSE(checked);
501       EXPECT_EQ(
502           it->GetOperand(kDebugGlobalVariableOperandVariableIndex).words[0],
503           debug_info_none_id);
504       checked = true;
505     }
506   }
507   EXPECT_TRUE(checked);
508 }
509 
TEST_F(IRContextTest,BasicVisitFromEntryPoint)510 TEST_F(IRContextTest, BasicVisitFromEntryPoint) {
511   // Make sure we visit the entry point, and the function it calls.
512   // Do not visit Dead or Exported.
513   const std::string text = R"(
514                OpCapability Shader
515                OpMemoryModel Logical GLSL450
516                OpEntryPoint Fragment %10 "main"
517                OpName %10 "main"
518                OpName %Dead "Dead"
519                OpName %11 "Constant"
520                OpName %ExportedFunc "ExportedFunc"
521                OpDecorate %ExportedFunc LinkageAttributes "ExportedFunc" Export
522        %void = OpTypeVoid
523           %6 = OpTypeFunction %void
524          %10 = OpFunction %void None %6
525          %14 = OpLabel
526          %15 = OpFunctionCall %void %11
527          %16 = OpFunctionCall %void %11
528                OpReturn
529                OpFunctionEnd
530          %11 = OpFunction %void None %6
531          %18 = OpLabel
532                OpReturn
533                OpFunctionEnd
534        %Dead = OpFunction %void None %6
535          %19 = OpLabel
536                OpReturn
537                OpFunctionEnd
538 %ExportedFunc = OpFunction %void None %7
539          %20 = OpLabel
540          %21 = OpFunctionCall %void %11
541                OpReturn
542                OpFunctionEnd
543 )";
544   // clang-format on
545 
546   std::unique_ptr<IRContext> localContext =
547       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
548                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
549   EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
550                                    << text << std::endl;
551   std::vector<uint32_t> processed;
552   Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
553     processed.push_back(fp->result_id());
554     return false;
555   };
556   localContext->ProcessEntryPointCallTree(mark_visited);
557   EXPECT_THAT(processed, UnorderedElementsAre(10, 11));
558 }
559 
TEST_F(IRContextTest,BasicVisitReachable)560 TEST_F(IRContextTest, BasicVisitReachable) {
561   // Make sure we visit the entry point, exported function, and the function
562   // they call. Do not visit Dead.
563   const std::string text = R"(
564                OpCapability Shader
565                OpMemoryModel Logical GLSL450
566                OpEntryPoint Fragment %10 "main"
567                OpName %10 "main"
568                OpName %Dead "Dead"
569                OpName %11 "Constant"
570                OpName %12 "ExportedFunc"
571                OpName %13 "Constant2"
572                OpDecorate %12 LinkageAttributes "ExportedFunc" Export
573        %void = OpTypeVoid
574           %6 = OpTypeFunction %void
575          %10 = OpFunction %void None %6
576          %14 = OpLabel
577          %15 = OpFunctionCall %void %11
578          %16 = OpFunctionCall %void %11
579                OpReturn
580                OpFunctionEnd
581          %11 = OpFunction %void None %6
582          %18 = OpLabel
583                OpReturn
584                OpFunctionEnd
585        %Dead = OpFunction %void None %6
586          %19 = OpLabel
587                OpReturn
588                OpFunctionEnd
589          %12 = OpFunction %void None %6
590          %20 = OpLabel
591          %21 = OpFunctionCall %void %13
592                OpReturn
593                OpFunctionEnd
594          %13 = OpFunction %void None %6
595          %22 = OpLabel
596                OpReturn
597                OpFunctionEnd
598 )";
599   // clang-format on
600 
601   std::unique_ptr<IRContext> localContext =
602       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
603                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
604   EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
605                                    << text << std::endl;
606 
607   std::vector<uint32_t> processed;
608   Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
609     processed.push_back(fp->result_id());
610     return false;
611   };
612   localContext->ProcessReachableCallTree(mark_visited);
613   EXPECT_THAT(processed, UnorderedElementsAre(10, 11, 12, 13));
614 }
615 
TEST_F(IRContextTest,BasicVisitOnlyOnce)616 TEST_F(IRContextTest, BasicVisitOnlyOnce) {
617   // Make sure we visit %12 only once, even if it is called from two different
618   // functions.
619   const std::string text = R"(
620                OpCapability Shader
621                OpMemoryModel Logical GLSL450
622                OpEntryPoint Fragment %10 "main"
623                OpName %10 "main"
624                OpName %Dead "Dead"
625                OpName %11 "Constant"
626                OpName %12 "ExportedFunc"
627                OpDecorate %12 LinkageAttributes "ExportedFunc" Export
628        %void = OpTypeVoid
629           %6 = OpTypeFunction %void
630          %10 = OpFunction %void None %6
631          %14 = OpLabel
632          %15 = OpFunctionCall %void %11
633          %16 = OpFunctionCall %void %12
634                OpReturn
635                OpFunctionEnd
636          %11 = OpFunction %void None %6
637          %18 = OpLabel
638          %19 = OpFunctionCall %void %12
639                OpReturn
640                OpFunctionEnd
641        %Dead = OpFunction %void None %6
642          %20 = OpLabel
643                OpReturn
644                OpFunctionEnd
645          %12 = OpFunction %void None %6
646          %21 = OpLabel
647                OpReturn
648                OpFunctionEnd
649 )";
650   // clang-format on
651 
652   std::unique_ptr<IRContext> localContext =
653       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
654                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
655   EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
656                                    << text << std::endl;
657 
658   std::vector<uint32_t> processed;
659   Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
660     processed.push_back(fp->result_id());
661     return false;
662   };
663   localContext->ProcessReachableCallTree(mark_visited);
664   EXPECT_THAT(processed, UnorderedElementsAre(10, 11, 12));
665 }
666 
TEST_F(IRContextTest,BasicDontVisitExportedVariable)667 TEST_F(IRContextTest, BasicDontVisitExportedVariable) {
668   // Make sure we only visit functions and not exported variables.
669   const std::string text = R"(
670                OpCapability Shader
671                OpMemoryModel Logical GLSL450
672                OpEntryPoint Fragment %10 "main"
673                OpExecutionMode %10 OriginUpperLeft
674                OpSource GLSL 150
675                OpName %10 "main"
676                OpName %12 "export_var"
677                OpDecorate %12 LinkageAttributes "export_var" Export
678        %void = OpTypeVoid
679           %6 = OpTypeFunction %void
680       %float = OpTypeFloat 32
681   %float_1 = OpConstant %float 1
682          %12 = OpVariable %float Output
683          %10 = OpFunction %void None %6
684          %14 = OpLabel
685                OpStore %12 %float_1
686                OpReturn
687                OpFunctionEnd
688 )";
689   // clang-format on
690 
691   std::unique_ptr<IRContext> localContext =
692       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
693                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
694   EXPECT_NE(nullptr, localContext) << "Assembling failed for shader:\n"
695                                    << text << std::endl;
696 
697   std::vector<uint32_t> processed;
698   Pass::ProcessFunction mark_visited = [&processed](Function* fp) {
699     processed.push_back(fp->result_id());
700     return false;
701   };
702   localContext->ProcessReachableCallTree(mark_visited);
703   EXPECT_THAT(processed, UnorderedElementsAre(10));
704 }
705 
TEST_F(IRContextTest,IdBoundTestAtLimit)706 TEST_F(IRContextTest, IdBoundTestAtLimit) {
707   const std::string text = R"(
708 OpCapability Shader
709 OpCapability Linkage
710 OpMemoryModel Logical GLSL450
711 %1 = OpTypeVoid
712 %2 = OpTypeFunction %1
713 %3 = OpFunction %1 None %2
714 %4 = OpLabel
715 OpReturn
716 OpFunctionEnd)";
717 
718   std::unique_ptr<IRContext> context =
719       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
720                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
721   uint32_t current_bound = context->module()->id_bound();
722   context->set_max_id_bound(current_bound);
723   uint32_t next_id_bound = context->TakeNextId();
724   EXPECT_EQ(next_id_bound, 0);
725   EXPECT_EQ(current_bound, context->module()->id_bound());
726   next_id_bound = context->TakeNextId();
727   EXPECT_EQ(next_id_bound, 0);
728 }
729 
TEST_F(IRContextTest,IdBoundTestBelowLimit)730 TEST_F(IRContextTest, IdBoundTestBelowLimit) {
731   const std::string text = R"(
732 OpCapability Shader
733 OpCapability Linkage
734 OpMemoryModel Logical GLSL450
735 %1 = OpTypeVoid
736 %2 = OpTypeFunction %1
737 %3 = OpFunction %1 None %2
738 %4 = OpLabel
739 OpReturn
740 OpFunctionEnd)";
741 
742   std::unique_ptr<IRContext> context =
743       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
744                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
745   uint32_t current_bound = context->module()->id_bound();
746   context->set_max_id_bound(current_bound + 100);
747   uint32_t next_id_bound = context->TakeNextId();
748   EXPECT_EQ(next_id_bound, current_bound);
749   EXPECT_EQ(current_bound + 1, context->module()->id_bound());
750   next_id_bound = context->TakeNextId();
751   EXPECT_EQ(next_id_bound, current_bound + 1);
752 }
753 
TEST_F(IRContextTest,IdBoundTestNearLimit)754 TEST_F(IRContextTest, IdBoundTestNearLimit) {
755   const std::string text = R"(
756 OpCapability Shader
757 OpCapability Linkage
758 OpMemoryModel Logical GLSL450
759 %1 = OpTypeVoid
760 %2 = OpTypeFunction %1
761 %3 = OpFunction %1 None %2
762 %4 = OpLabel
763 OpReturn
764 OpFunctionEnd)";
765 
766   std::unique_ptr<IRContext> context =
767       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
768                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
769   uint32_t current_bound = context->module()->id_bound();
770   context->set_max_id_bound(current_bound + 1);
771   uint32_t next_id_bound = context->TakeNextId();
772   EXPECT_EQ(next_id_bound, current_bound);
773   EXPECT_EQ(current_bound + 1, context->module()->id_bound());
774   next_id_bound = context->TakeNextId();
775   EXPECT_EQ(next_id_bound, 0);
776 }
777 
TEST_F(IRContextTest,IdBoundTestUIntMax)778 TEST_F(IRContextTest, IdBoundTestUIntMax) {
779   const std::string text = R"(
780 OpCapability Shader
781 OpCapability Linkage
782 OpMemoryModel Logical GLSL450
783 %1 = OpTypeVoid
784 %2 = OpTypeFunction %1
785 %3 = OpFunction %1 None %2
786 %4294967294 = OpLabel ; ID is UINT_MAX-1
787 OpReturn
788 OpFunctionEnd)";
789 
790   std::unique_ptr<IRContext> context =
791       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
792                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
793   uint32_t current_bound = context->module()->id_bound();
794 
795   // Expecting |BuildModule| to preserve the numeric ids.
796   EXPECT_EQ(current_bound, std::numeric_limits<uint32_t>::max());
797 
798   context->set_max_id_bound(current_bound);
799   uint32_t next_id_bound = context->TakeNextId();
800   EXPECT_EQ(next_id_bound, 0);
801   EXPECT_EQ(current_bound, context->module()->id_bound());
802 }
803 
TEST_F(IRContextTest,CfgAndDomAnalysis)804 TEST_F(IRContextTest, CfgAndDomAnalysis) {
805   const std::string text = R"(
806 OpCapability Shader
807 OpCapability Linkage
808 OpMemoryModel Logical GLSL450
809 %1 = OpTypeVoid
810 %2 = OpTypeFunction %1
811 %3 = OpFunction %1 None %2
812 %4 = OpLabel
813 OpReturn
814 OpFunctionEnd)";
815 
816   std::unique_ptr<IRContext> ctx =
817       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
818                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
819 
820   // Building the dominator analysis should build the CFG.
821   ASSERT_TRUE(ctx->module()->begin() != ctx->module()->end());
822   ctx->GetDominatorAnalysis(&*ctx->module()->begin());
823 
824   EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisCFG));
825   EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDominatorAnalysis));
826 
827   // Invalidating the CFG analysis should invalidate the dominator analysis.
828   ctx->InvalidateAnalyses(IRContext::kAnalysisCFG);
829   EXPECT_FALSE(ctx->AreAnalysesValid(IRContext::kAnalysisCFG));
830   EXPECT_FALSE(ctx->AreAnalysesValid(IRContext::kAnalysisDominatorAnalysis));
831 }
832 
TEST_F(IRContextTest,AsanErrorTest)833 TEST_F(IRContextTest, AsanErrorTest) {
834   std::string shader = R"(
835                OpCapability Shader
836           %1 = OpExtInstImport "GLSL.std.450"
837                OpMemoryModel Logical GLSL450
838                OpEntryPoint Fragment %4 "main"
839                OpExecutionMode %4 OriginUpperLeft
840                OpSource ESSL 310
841                OpName %4 "main"
842                OpName %8 "x"
843                OpName %10 "y"
844                OpDecorate %8 RelaxedPrecision
845                OpDecorate %10 RelaxedPrecision
846                OpDecorate %11 RelaxedPrecision
847           %2 = OpTypeVoid
848           %3 = OpTypeFunction %2
849           %6 = OpTypeInt 32 1
850           %7 = OpTypePointer Function %6
851           %9 = OpConstant %6 1
852           %4 = OpFunction %2 None %3
853           %5 = OpLabel
854           %8 = OpVariable %7 Function
855          %10 = OpVariable %7 Function
856                OpStore %8 %9
857          %11 = OpLoad %6 %8
858 	       OpBranch %20
859 	 %20 = OpLabel
860 	 %21 = OpPhi %6 %11 %5
861          OpStore %10 %21
862          OpReturn
863          OpFunctionEnd
864   )";
865 
866   const auto env = SPV_ENV_UNIVERSAL_1_3;
867   const auto consumer = nullptr;
868   const auto context = BuildModule(
869       env, consumer, shader, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
870 
871   opt::Function* fun =
872       context->cfg()->block(5)->GetParent();  // Computes the CFG analysis
873   opt::DominatorAnalysis* dom = nullptr;
874   dom = context->GetDominatorAnalysis(fun);  // Computes the dominator analysis,
875                                              // which depends on the CFG
876                                              // analysis
877   context->InvalidateAnalysesExceptFor(
878       opt::IRContext::Analysis::kAnalysisDominatorAnalysis);  // Invalidates the
879                                                               // CFG analysis
880   dom = context->GetDominatorAnalysis(
881       fun);  // Recompute the CFG analysis because the Dominator tree uses it.
882   auto bb = dom->ImmediateDominator(5);
883   std::cout
884       << bb->id();  // Make sure asan does not complain about use after free.
885 }
886 
TEST_F(IRContextTest,DebugInstructionReplaceSingleUse)887 TEST_F(IRContextTest, DebugInstructionReplaceSingleUse) {
888   const std::string text = R"(
889 OpCapability Shader
890 OpCapability Linkage
891 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
892 OpMemoryModel Logical GLSL450
893 %2 = OpString "test"
894 %3 = OpTypeVoid
895 %4 = OpTypeFunction %3
896 %5 = OpTypeFloat 32
897 %6 = OpTypePointer Function %5
898 %7 = OpConstant %5 0
899 %8 = OpTypeInt 32 0
900 %9 = OpConstant %8 32
901 %10 = OpExtInst %3 %1 DebugExpression
902 %11 = OpExtInst %3 %1 DebugSource %2
903 %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
904 %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
905 %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
906 %15 = OpExtInst %3 %1 DebugTypeBasic %2 %9 Float
907 %16 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 0 0 %14 FlagIsLocal
908 %17 = OpFunction %3 None %4
909 %18 = OpLabel
910 %19 = OpExtInst %3 %1 DebugScope %14
911 %20 = OpVariable %6 Function
912 %26 = OpVariable %6 Function
913 OpBranch %21
914 %21 = OpLabel
915 %22 = OpPhi %5 %7 %18
916 OpBranch %23
917 %23 = OpLabel
918 OpLine %2 0 0
919 OpStore %20 %7
920 %24 = OpExtInst %3 %1 DebugValue %16 %22 %10
921 %25 = OpExtInst %3 %1 DebugDeclare %16 %26 %10
922 OpReturn
923 OpFunctionEnd)";
924 
925   std::unique_ptr<IRContext> ctx =
926       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
927                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
928   ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
929   NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
930   pass.Run(ctx.get());
931   EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
932 
933   auto* dbg_value = ctx->get_def_use_mgr()->GetDef(24);
934   EXPECT_TRUE(dbg_value->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
935               22);
936   EXPECT_TRUE(ctx->ReplaceAllUsesWith(22, 7));
937   dbg_value = ctx->get_def_use_mgr()->GetDef(24);
938   EXPECT_TRUE(dbg_value->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
939               7);
940 
941   auto* dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
942   EXPECT_TRUE(
943       dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 26);
944   EXPECT_TRUE(ctx->ReplaceAllUsesWith(26, 20));
945   dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
946   EXPECT_TRUE(
947       dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 20);
948 }
949 
TEST_F(IRContextTest,DebugInstructionReplaceAllUses)950 TEST_F(IRContextTest, DebugInstructionReplaceAllUses) {
951   const std::string text = R"(
952 OpCapability Shader
953 OpCapability Linkage
954 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
955 OpMemoryModel Logical GLSL450
956 %2 = OpString "test"
957 %3 = OpTypeVoid
958 %4 = OpTypeFunction %3
959 %5 = OpTypeFloat 32
960 %6 = OpTypePointer Function %5
961 %7 = OpConstant %5 0
962 %8 = OpTypeInt 32 0
963 %9 = OpConstant %8 32
964 %10 = OpExtInst %3 %1 DebugExpression
965 %11 = OpExtInst %3 %1 DebugSource %2
966 %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
967 %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
968 %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
969 %15 = OpExtInst %3 %1 DebugTypeBasic %2 %9 Float
970 %16 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 0 0 %14 FlagIsLocal
971 %27 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 1 0 %14 FlagIsLocal
972 %17 = OpFunction %3 None %4
973 %18 = OpLabel
974 %19 = OpExtInst %3 %1 DebugScope %14
975 %20 = OpVariable %6 Function
976 %26 = OpVariable %6 Function
977 OpBranch %21
978 %21 = OpLabel
979 %22 = OpPhi %5 %7 %18
980 OpBranch %23
981 %23 = OpLabel
982 OpLine %2 0 0
983 OpStore %20 %7
984 %24 = OpExtInst %3 %1 DebugValue %16 %22 %10
985 %25 = OpExtInst %3 %1 DebugDeclare %16 %26 %10
986 %28 = OpExtInst %3 %1 DebugValue %27 %22 %10
987 %29 = OpExtInst %3 %1 DebugDeclare %27 %26 %10
988 OpReturn
989 OpFunctionEnd)";
990 
991   std::unique_ptr<IRContext> ctx =
992       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
993                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
994   ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
995   NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
996   pass.Run(ctx.get());
997   EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
998 
999   auto* dbg_value0 = ctx->get_def_use_mgr()->GetDef(24);
1000   auto* dbg_value1 = ctx->get_def_use_mgr()->GetDef(28);
1001   EXPECT_TRUE(dbg_value0->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
1002               22);
1003   EXPECT_TRUE(dbg_value1->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
1004               22);
1005   EXPECT_TRUE(ctx->ReplaceAllUsesWith(22, 7));
1006   dbg_value0 = ctx->get_def_use_mgr()->GetDef(24);
1007   dbg_value1 = ctx->get_def_use_mgr()->GetDef(28);
1008   EXPECT_TRUE(dbg_value0->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
1009               7);
1010   EXPECT_TRUE(dbg_value1->GetSingleWordOperand(kDebugValueOperandValueIndex) ==
1011               7);
1012 
1013   auto* dbg_decl0 = ctx->get_def_use_mgr()->GetDef(25);
1014   auto* dbg_decl1 = ctx->get_def_use_mgr()->GetDef(29);
1015   EXPECT_TRUE(
1016       dbg_decl0->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 26);
1017   EXPECT_TRUE(
1018       dbg_decl1->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 26);
1019   EXPECT_TRUE(ctx->ReplaceAllUsesWith(26, 20));
1020   dbg_decl0 = ctx->get_def_use_mgr()->GetDef(25);
1021   dbg_decl1 = ctx->get_def_use_mgr()->GetDef(29);
1022   EXPECT_TRUE(
1023       dbg_decl0->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 20);
1024   EXPECT_TRUE(
1025       dbg_decl1->GetSingleWordOperand(kDebugDeclareOperandVariableIndex) == 20);
1026 }
1027 
TEST_F(IRContextTest,DebugInstructionReplaceDebugScopeAndDebugInlinedAt)1028 TEST_F(IRContextTest, DebugInstructionReplaceDebugScopeAndDebugInlinedAt) {
1029   const std::string text = R"(
1030 OpCapability Shader
1031 OpCapability Linkage
1032 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1033 OpMemoryModel Logical GLSL450
1034 %2 = OpString "test"
1035 %3 = OpTypeVoid
1036 %4 = OpTypeFunction %3
1037 %5 = OpTypeFloat 32
1038 %6 = OpTypePointer Function %5
1039 %7 = OpConstant %5 0
1040 %8 = OpTypeInt 32 0
1041 %9 = OpConstant %8 32
1042 %10 = OpExtInst %3 %1 DebugExpression
1043 %11 = OpExtInst %3 %1 DebugSource %2
1044 %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
1045 %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
1046 %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
1047 %15 = OpExtInst %3 %1 DebugInfoNone
1048 %16 = OpExtInst %3 %1 DebugFunction %2 %13 %11 10 10 %12 %2 FlagIsProtected|FlagIsPrivate 0 %15
1049 %25 = OpExtInst %3 %1 DebugInlinedAt 0 %14
1050 %26 = OpExtInst %3 %1 DebugInlinedAt 2 %14
1051 %17 = OpFunction %3 None %4
1052 %18 = OpLabel
1053 %19 = OpExtInst %3 %1 DebugScope %14
1054 %20 = OpVariable %6 Function
1055 OpBranch %21
1056 %21 = OpLabel
1057 %24 = OpExtInst %3 %1 DebugScope %16
1058 %22 = OpPhi %5 %7 %18
1059 OpBranch %23
1060 %23 = OpLabel
1061 %27 = OpExtInst %3 %1 DebugScope %16 %25
1062 OpLine %2 0 0
1063 %28 = OpFAdd %5 %7 %7
1064 OpStore %20 %28
1065 OpReturn
1066 OpFunctionEnd)";
1067 
1068   std::unique_ptr<IRContext> ctx =
1069       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
1070                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1071   ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
1072   NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
1073   pass.Run(ctx.get());
1074   EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
1075 
1076   auto* inst0 = ctx->get_def_use_mgr()->GetDef(20);
1077   auto* inst1 = ctx->get_def_use_mgr()->GetDef(22);
1078   auto* inst2 = ctx->get_def_use_mgr()->GetDef(28);
1079   EXPECT_EQ(inst0->GetDebugScope().GetLexicalScope(), 14);
1080   EXPECT_EQ(inst1->GetDebugScope().GetLexicalScope(), 16);
1081   EXPECT_EQ(inst2->GetDebugScope().GetLexicalScope(), 16);
1082   EXPECT_EQ(inst2->GetDebugInlinedAt(), 25);
1083 
1084   EXPECT_TRUE(ctx->ReplaceAllUsesWith(14, 12));
1085   EXPECT_TRUE(ctx->ReplaceAllUsesWith(16, 14));
1086   EXPECT_TRUE(ctx->ReplaceAllUsesWith(25, 26));
1087   EXPECT_EQ(inst0->GetDebugScope().GetLexicalScope(), 12);
1088   EXPECT_EQ(inst1->GetDebugScope().GetLexicalScope(), 14);
1089   EXPECT_EQ(inst2->GetDebugScope().GetLexicalScope(), 14);
1090   EXPECT_EQ(inst2->GetDebugInlinedAt(), 26);
1091 }
1092 
TEST_F(IRContextTest,AddDebugValueAfterReplaceUse)1093 TEST_F(IRContextTest, AddDebugValueAfterReplaceUse) {
1094   const std::string text = R"(
1095 OpCapability Shader
1096 OpCapability Linkage
1097 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
1098 OpMemoryModel Logical GLSL450
1099 %2 = OpString "test"
1100 %3 = OpTypeVoid
1101 %4 = OpTypeFunction %3
1102 %5 = OpTypeFloat 32
1103 %6 = OpTypePointer Function %5
1104 %7 = OpConstant %5 0
1105 %8 = OpTypeInt 32 0
1106 %9 = OpConstant %8 32
1107 %10 = OpExtInst %3 %1 DebugExpression
1108 %11 = OpExtInst %3 %1 DebugSource %2
1109 %12 = OpExtInst %3 %1 DebugCompilationUnit 1 4 %11 HLSL
1110 %13 = OpExtInst %3 %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %3
1111 %14 = OpExtInst %3 %1 DebugFunction %2 %13 %11 0 0 %12 %2 FlagIsProtected|FlagIsPrivate 0 %17
1112 %15 = OpExtInst %3 %1 DebugTypeBasic %2 %9 Float
1113 %16 = OpExtInst %3 %1 DebugLocalVariable %2 %15 %11 0 0 %14 FlagIsLocal
1114 %17 = OpFunction %3 None %4
1115 %18 = OpLabel
1116 %19 = OpExtInst %3 %1 DebugScope %14
1117 %20 = OpVariable %6 Function
1118 %26 = OpVariable %6 Function
1119 OpBranch %21
1120 %21 = OpLabel
1121 %27 = OpExtInst %3 %1 DebugScope %14
1122 %22 = OpPhi %5 %7 %18
1123 OpBranch %23
1124 %23 = OpLabel
1125 %28 = OpExtInst %3 %1 DebugScope %14
1126 OpLine %2 0 0
1127 OpStore %20 %7
1128 %24 = OpExtInst %3 %1 DebugValue %16 %22 %10
1129 %25 = OpExtInst %3 %1 DebugDeclare %16 %26 %10
1130 OpReturn
1131 OpFunctionEnd)";
1132 
1133   std::unique_ptr<IRContext> ctx =
1134       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
1135                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1136   ctx->BuildInvalidAnalyses(IRContext::kAnalysisDebugInfo);
1137   NoopPassPreservesAll pass(Pass::Status::SuccessWithChange);
1138   pass.Run(ctx.get());
1139   EXPECT_TRUE(ctx->AreAnalysesValid(IRContext::kAnalysisDebugInfo));
1140 
1141   // Replace all uses of result it '26' with '20'
1142   auto* dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
1143   EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
1144             26);
1145   EXPECT_TRUE(ctx->ReplaceAllUsesWith(26, 20));
1146   dbg_decl = ctx->get_def_use_mgr()->GetDef(25);
1147   EXPECT_EQ(dbg_decl->GetSingleWordOperand(kDebugDeclareOperandVariableIndex),
1148             20);
1149 }
1150 
1151 struct TargetEnvCompareTestData {
1152   spv_target_env later_env, earlier_env;
1153 };
1154 
1155 using TargetEnvCompareTest = ::testing::TestWithParam<TargetEnvCompareTestData>;
1156 
TEST_P(TargetEnvCompareTest,Case)1157 TEST_P(TargetEnvCompareTest, Case) {
1158   // If new environments are added, then we must update the list of tests.
1159   ASSERT_EQ(SPV_ENV_VULKAN_1_3 + 1, SPV_ENV_MAX);
1160 
1161   const auto& tc = GetParam();
1162 
1163   std::unique_ptr<Module> module(new Module());
1164   IRContext localContext(tc.later_env, std::move(module),
1165                          spvtools::MessageConsumer());
1166   EXPECT_TRUE(localContext.IsTargetEnvAtLeast(tc.earlier_env));
1167 
1168   if (tc.earlier_env != tc.later_env) {
1169     std::unique_ptr<Module> module(new Module());
1170     IRContext localContext(tc.earlier_env, std::move(module),
1171                            spvtools::MessageConsumer());
1172     EXPECT_FALSE(localContext.IsTargetEnvAtLeast(tc.later_env));
1173   }
1174 }
1175 
TEST_F(IRContextTest,ReturnsTrueWhenExtensionIsRemoved)1176 TEST_F(IRContextTest, ReturnsTrueWhenExtensionIsRemoved) {
1177   const std::string text = R"(
1178                OpCapability Shader
1179                OpExtension "SPV_KHR_shader_clock"
1180                OpMemoryModel Logical GLSL450
1181                OpEntryPoint GLCompute %1 "main"
1182        %void = OpTypeVoid
1183           %6 = OpTypeFunction %void
1184           %1 = OpFunction %void None %6
1185           %9 = OpLabel
1186                OpReturn
1187                OpFunctionEnd)";
1188 
1189   std::unique_ptr<IRContext> ctx =
1190       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1191                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1192   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1193   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1194                           ctx->module()->extension_end()),
1195             1);
1196 
1197   EXPECT_TRUE(ctx->RemoveExtension(kSPV_KHR_shader_clock));
1198 
1199   EXPECT_FALSE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1200   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1201                           ctx->module()->extension_end()),
1202             0);
1203 }
1204 
TEST_F(IRContextTest,ReturnsFalseWhenExtensionIsNotRemoved)1205 TEST_F(IRContextTest, ReturnsFalseWhenExtensionIsNotRemoved) {
1206   const std::string text = R"(
1207                OpCapability Shader
1208                OpExtension "SPV_KHR_device_group"
1209                OpMemoryModel Logical GLSL450
1210                OpEntryPoint GLCompute %1 "main"
1211        %void = OpTypeVoid
1212           %6 = OpTypeFunction %void
1213           %1 = OpFunction %void None %6
1214           %9 = OpLabel
1215                OpReturn
1216                OpFunctionEnd)";
1217 
1218   std::unique_ptr<IRContext> ctx =
1219       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1220                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1221   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_device_group));
1222   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1223                           ctx->module()->extension_end()),
1224             1);
1225 
1226   EXPECT_FALSE(ctx->RemoveExtension(kSPV_KHR_shader_clock));
1227 
1228   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_device_group));
1229   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1230                           ctx->module()->extension_end()),
1231             1);
1232 }
1233 
TEST_F(IRContextTest,RemovesExtensionIfLast)1234 TEST_F(IRContextTest, RemovesExtensionIfLast) {
1235   const std::string text = R"(
1236                OpCapability Shader
1237                OpExtension "SPV_KHR_device_group"
1238                OpExtension "SPV_KHR_shader_clock"
1239                OpMemoryModel Logical GLSL450
1240                OpEntryPoint GLCompute %1 "main"
1241        %void = OpTypeVoid
1242           %6 = OpTypeFunction %void
1243           %1 = OpFunction %void None %6
1244           %9 = OpLabel
1245                OpReturn
1246                OpFunctionEnd)";
1247 
1248   std::unique_ptr<IRContext> ctx =
1249       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1250                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1251   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_device_group));
1252   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1253   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1254                           ctx->module()->extension_end()),
1255             2);
1256 
1257   EXPECT_TRUE(ctx->RemoveExtension(kSPV_KHR_shader_clock));
1258 
1259   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_device_group));
1260   EXPECT_FALSE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1261   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1262                           ctx->module()->extension_end()),
1263             1);
1264 }
1265 
TEST_F(IRContextTest,RemovesExtensionIfFirst)1266 TEST_F(IRContextTest, RemovesExtensionIfFirst) {
1267   const std::string text = R"(
1268                OpCapability Shader
1269                OpExtension "SPV_KHR_shader_clock"
1270                OpExtension "SPV_KHR_device_group"
1271                OpMemoryModel Logical GLSL450
1272                OpEntryPoint GLCompute %1 "main"
1273        %void = OpTypeVoid
1274           %6 = OpTypeFunction %void
1275           %1 = OpFunction %void None %6
1276           %9 = OpLabel
1277                OpReturn
1278                OpFunctionEnd)";
1279   std::unique_ptr<IRContext> ctx =
1280       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1281                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1282   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_device_group));
1283   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1284   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1285                           ctx->module()->extension_end()),
1286             2);
1287 
1288   EXPECT_TRUE(ctx->RemoveExtension(kSPV_KHR_shader_clock));
1289 
1290   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_device_group));
1291   EXPECT_FALSE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1292   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1293                           ctx->module()->extension_end()),
1294             1);
1295 }
1296 
TEST_F(IRContextTest,RemovesMultipleExtensions)1297 TEST_F(IRContextTest, RemovesMultipleExtensions) {
1298   const std::string text = R"(
1299                OpCapability Shader
1300                OpExtension "SPV_KHR_shader_clock"
1301                OpExtension "SPV_KHR_shader_clock"
1302                OpMemoryModel Logical GLSL450
1303                OpEntryPoint GLCompute %1 "main"
1304        %void = OpTypeVoid
1305           %6 = OpTypeFunction %void
1306           %1 = OpFunction %void None %6
1307           %9 = OpLabel
1308                OpReturn
1309                OpFunctionEnd)";
1310 
1311   std::unique_ptr<IRContext> ctx =
1312       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1313                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1314   EXPECT_TRUE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1315   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1316                           ctx->module()->extension_end()),
1317             2);
1318 
1319   EXPECT_TRUE(ctx->RemoveExtension(kSPV_KHR_shader_clock));
1320 
1321   EXPECT_FALSE(ctx->get_feature_mgr()->HasExtension(kSPV_KHR_shader_clock));
1322   EXPECT_EQ(std::distance(ctx->module()->extension_begin(),
1323                           ctx->module()->extension_end()),
1324             0);
1325 }
1326 
TEST_F(IRContextTest,ReturnsTrueWhenCapabilityIsRemoved)1327 TEST_F(IRContextTest, ReturnsTrueWhenCapabilityIsRemoved) {
1328   const std::string text = R"(
1329                OpCapability Shader
1330                OpCapability ShaderClockKHR
1331                OpExtension "SPV_KHR_shader_clock"
1332                OpMemoryModel Logical GLSL450
1333                OpEntryPoint GLCompute %1 "main"
1334        %void = OpTypeVoid
1335           %6 = OpTypeFunction %void
1336           %1 = OpFunction %void None %6
1337           %9 = OpLabel
1338                OpReturn
1339                OpFunctionEnd)";
1340 
1341   std::unique_ptr<IRContext> ctx =
1342       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1343                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1344   EXPECT_TRUE(
1345       ctx->get_feature_mgr()->HasCapability(spv::Capability::ShaderClockKHR));
1346   EXPECT_EQ(std::distance(ctx->module()->capability_begin(),
1347                           ctx->module()->capability_end()),
1348             2);
1349 
1350   EXPECT_TRUE(ctx->RemoveCapability(spv::Capability::ShaderClockKHR));
1351 
1352   EXPECT_FALSE(
1353       ctx->get_feature_mgr()->HasCapability(spv::Capability::ShaderClockKHR));
1354   EXPECT_EQ(std::distance(ctx->module()->capability_begin(),
1355                           ctx->module()->capability_end()),
1356             1);
1357 }
1358 
TEST_F(IRContextTest,ReturnsFalseWhenCapabilityIsNotRemoved)1359 TEST_F(IRContextTest, ReturnsFalseWhenCapabilityIsNotRemoved) {
1360   const std::string text = R"(
1361                OpCapability Shader
1362                OpCapability DeviceGroup
1363                OpExtension "SPV_KHR_device_group"
1364                OpMemoryModel Logical GLSL450
1365                OpEntryPoint GLCompute %1 "main"
1366        %void = OpTypeVoid
1367           %6 = OpTypeFunction %void
1368           %1 = OpFunction %void None %6
1369           %9 = OpLabel
1370                OpReturn
1371                OpFunctionEnd)";
1372 
1373   std::unique_ptr<IRContext> ctx =
1374       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1375                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1376   EXPECT_TRUE(
1377       ctx->get_feature_mgr()->HasCapability(spv::Capability::DeviceGroup));
1378   EXPECT_EQ(std::distance(ctx->module()->capability_begin(),
1379                           ctx->module()->capability_end()),
1380             2);
1381 
1382   EXPECT_FALSE(ctx->RemoveCapability(spv::Capability::ShaderClockKHR));
1383 
1384   EXPECT_TRUE(
1385       ctx->get_feature_mgr()->HasCapability(spv::Capability::DeviceGroup));
1386   EXPECT_EQ(std::distance(ctx->module()->capability_begin(),
1387                           ctx->module()->capability_end()),
1388             2);
1389 }
1390 
TEST_F(IRContextTest,RemovesMultipleCapabilities)1391 TEST_F(IRContextTest, RemovesMultipleCapabilities) {
1392   const std::string text = R"(
1393                OpCapability Shader
1394                OpCapability DeviceGroup
1395                OpCapability DeviceGroup
1396                OpExtension "SPV_KHR_device_group"
1397                OpMemoryModel Logical GLSL450
1398                OpEntryPoint GLCompute %1 "main"
1399        %void = OpTypeVoid
1400           %6 = OpTypeFunction %void
1401           %1 = OpFunction %void None %6
1402           %9 = OpLabel
1403                OpReturn
1404                OpFunctionEnd)";
1405 
1406   std::unique_ptr<IRContext> ctx =
1407       BuildModule(SPV_ENV_UNIVERSAL_1_6, nullptr, text,
1408                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1409   EXPECT_TRUE(
1410       ctx->get_feature_mgr()->HasCapability(spv::Capability::DeviceGroup));
1411   EXPECT_EQ(std::distance(ctx->module()->capability_begin(),
1412                           ctx->module()->capability_end()),
1413             3);
1414 
1415   EXPECT_TRUE(ctx->RemoveCapability(spv::Capability::DeviceGroup));
1416 
1417   EXPECT_FALSE(
1418       ctx->get_feature_mgr()->HasCapability(spv::Capability::DeviceGroup));
1419   EXPECT_EQ(std::distance(ctx->module()->capability_begin(),
1420                           ctx->module()->capability_end()),
1421             1);
1422 }
1423 
1424 INSTANTIATE_TEST_SUITE_P(
1425     TestCase, TargetEnvCompareTest,
1426     ::testing::Values(
1427         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_0},
1428         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_0},
1429         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_0},
1430         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_0},
1431         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_0},
1432         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_UNIVERSAL_1_0},
1433         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_0},
1434         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_1},
1435         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_1},
1436         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_1},
1437         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_1},
1438         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_UNIVERSAL_1_1},
1439         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_1},
1440         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_2},
1441         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_2},
1442         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_2},
1443         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_UNIVERSAL_1_2},
1444         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_2},
1445         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_3},
1446         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_3},
1447         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_UNIVERSAL_1_3},
1448         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_3},
1449         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_4},
1450         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_UNIVERSAL_1_4},
1451         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_4},
1452         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_UNIVERSAL_1_5},
1453         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_5},
1454         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_UNIVERSAL_1_6},
1455         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_0, SPV_ENV_UNIVERSAL_1_0},
1456         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_1, SPV_ENV_VULKAN_1_0},
1457         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0},
1458         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0},
1459         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_0},
1460         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_0},
1461         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_0},
1462         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_0},
1463         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_1},
1464         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_2},
1465         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_1, SPV_ENV_UNIVERSAL_1_3},
1466         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_4, SPV_ENV_VULKAN_1_1},
1467         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_1},
1468         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_1},
1469         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_0},
1470         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_1},
1471         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_2},
1472         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_3},
1473         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_4},
1474         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_2, SPV_ENV_UNIVERSAL_1_5},
1475         TargetEnvCompareTestData{SPV_ENV_UNIVERSAL_1_6, SPV_ENV_VULKAN_1_2},
1476         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_0},
1477         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_1},
1478         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_2},
1479         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_3},
1480         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_4},
1481         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_5},
1482         TargetEnvCompareTestData{SPV_ENV_VULKAN_1_3, SPV_ENV_UNIVERSAL_1_6}));
1483 
1484 }  // namespace
1485 }  // namespace opt
1486 }  // namespace spvtools
1487