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