• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
16 
17 #include "gmock/gmock.h"
18 #include "source/opt/build_module.h"
19 #include "source/opt/value_number_table.h"
20 #include "test/opt/assembly_builder.h"
21 #include "test/opt/pass_fixture.h"
22 
23 namespace spvtools {
24 namespace opt {
25 namespace {
26 
27 using ::testing::HasSubstr;
28 using ::testing::MatchesRegex;
29 using ValueTableTest = PassTest<::testing::Test>;
30 
TEST_F(ValueTableTest,SameInstructionSameValue)31 TEST_F(ValueTableTest, SameInstructionSameValue) {
32   const std::string text = R"(
33                OpCapability Shader
34           %1 = OpExtInstImport "GLSL.std.450"
35                OpMemoryModel Logical GLSL450
36                OpEntryPoint Fragment %2 "main"
37                OpExecutionMode %2 OriginUpperLeft
38                OpSource GLSL 430
39           %3 = OpTypeVoid
40           %4 = OpTypeFunction %3
41           %5 = OpTypeFloat 32
42           %6 = OpTypePointer Function %5
43           %2 = OpFunction %3 None %4
44           %7 = OpLabel
45           %8 = OpVariable %6 Function
46           %9 = OpLoad %5 %8
47          %10 = OpFAdd %5 %9 %9
48                OpReturn
49                OpFunctionEnd
50   )";
51   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
52   ValueNumberTable vtable(context.get());
53   Instruction* inst = context->get_def_use_mgr()->GetDef(10);
54   EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst));
55 }
56 
TEST_F(ValueTableTest,DifferentInstructionSameValue)57 TEST_F(ValueTableTest, DifferentInstructionSameValue) {
58   const std::string text = R"(
59                OpCapability Shader
60           %1 = OpExtInstImport "GLSL.std.450"
61                OpMemoryModel Logical GLSL450
62                OpEntryPoint Fragment %2 "main"
63                OpExecutionMode %2 OriginUpperLeft
64                OpSource GLSL 430
65           %3 = OpTypeVoid
66           %4 = OpTypeFunction %3
67           %5 = OpTypeFloat 32
68           %6 = OpTypePointer Function %5
69           %2 = OpFunction %3 None %4
70           %7 = OpLabel
71           %8 = OpVariable %6 Function
72           %9 = OpLoad %5 %8
73          %10 = OpFAdd %5 %9 %9
74          %11 = OpFAdd %5 %9 %9
75                OpReturn
76                OpFunctionEnd
77   )";
78   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
79   ValueNumberTable vtable(context.get());
80   Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
81   Instruction* inst2 = context->get_def_use_mgr()->GetDef(11);
82   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
83 }
84 
TEST_F(ValueTableTest,SameValueDifferentBlock)85 TEST_F(ValueTableTest, SameValueDifferentBlock) {
86   const std::string text = R"(
87                OpCapability Shader
88           %1 = OpExtInstImport "GLSL.std.450"
89                OpMemoryModel Logical GLSL450
90                OpEntryPoint Fragment %2 "main"
91                OpExecutionMode %2 OriginUpperLeft
92                OpSource GLSL 430
93           %3 = OpTypeVoid
94           %4 = OpTypeFunction %3
95           %5 = OpTypeFloat 32
96           %6 = OpTypePointer Function %5
97           %2 = OpFunction %3 None %4
98           %7 = OpLabel
99           %8 = OpVariable %6 Function
100           %9 = OpLoad %5 %8
101          %10 = OpFAdd %5 %9 %9
102                OpBranch %11
103          %11 = OpLabel
104          %12 = OpFAdd %5 %9 %9
105                OpReturn
106                OpFunctionEnd
107   )";
108   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
109   ValueNumberTable vtable(context.get());
110   Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
111   Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
112   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
113 }
114 
TEST_F(ValueTableTest,DifferentValue)115 TEST_F(ValueTableTest, DifferentValue) {
116   const std::string text = R"(
117                OpCapability Shader
118           %1 = OpExtInstImport "GLSL.std.450"
119                OpMemoryModel Logical GLSL450
120                OpEntryPoint Fragment %2 "main"
121                OpExecutionMode %2 OriginUpperLeft
122                OpSource GLSL 430
123           %3 = OpTypeVoid
124           %4 = OpTypeFunction %3
125           %5 = OpTypeFloat 32
126           %6 = OpTypePointer Function %5
127           %2 = OpFunction %3 None %4
128           %7 = OpLabel
129           %8 = OpVariable %6 Function
130           %9 = OpLoad %5 %8
131          %10 = OpFAdd %5 %9 %9
132          %11 = OpFAdd %5 %9 %10
133                OpReturn
134                OpFunctionEnd
135   )";
136   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
137   ValueNumberTable vtable(context.get());
138   Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
139   Instruction* inst2 = context->get_def_use_mgr()->GetDef(11);
140   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
141 }
142 
TEST_F(ValueTableTest,DifferentValueDifferentBlock)143 TEST_F(ValueTableTest, DifferentValueDifferentBlock) {
144   const std::string text = R"(
145                OpCapability Shader
146           %1 = OpExtInstImport "GLSL.std.450"
147                OpMemoryModel Logical GLSL450
148                OpEntryPoint Fragment %2 "main"
149                OpExecutionMode %2 OriginUpperLeft
150                OpSource GLSL 430
151           %3 = OpTypeVoid
152           %4 = OpTypeFunction %3
153           %5 = OpTypeFloat 32
154           %6 = OpTypePointer Function %5
155           %2 = OpFunction %3 None %4
156           %7 = OpLabel
157           %8 = OpVariable %6 Function
158           %9 = OpLoad %5 %8
159          %10 = OpFAdd %5 %9 %9
160                OpBranch %11
161          %11 = OpLabel
162          %12 = OpFAdd %5 %9 %10
163                OpReturn
164                OpFunctionEnd
165   )";
166   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
167   ValueNumberTable vtable(context.get());
168   Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
169   Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
170   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
171 }
172 
TEST_F(ValueTableTest,SameLoad)173 TEST_F(ValueTableTest, SameLoad) {
174   const std::string text = R"(
175                OpCapability Shader
176           %1 = OpExtInstImport "GLSL.std.450"
177                OpMemoryModel Logical GLSL450
178                OpEntryPoint Fragment %2 "main"
179                OpExecutionMode %2 OriginUpperLeft
180                OpSource GLSL 430
181           %3 = OpTypeVoid
182           %4 = OpTypeFunction %3
183           %5 = OpTypeFloat 32
184           %6 = OpTypePointer Function %5
185           %2 = OpFunction %3 None %4
186           %7 = OpLabel
187           %8 = OpVariable %6 Function
188           %9 = OpLoad %5 %8
189                OpReturn
190                OpFunctionEnd
191   )";
192   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
193   ValueNumberTable vtable(context.get());
194   Instruction* inst = context->get_def_use_mgr()->GetDef(9);
195   EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst));
196 }
197 
198 // Two different loads, even from the same memory, must given different value
199 // numbers if the memory is not read-only.
TEST_F(ValueTableTest,DifferentFunctionLoad)200 TEST_F(ValueTableTest, DifferentFunctionLoad) {
201   const std::string text = R"(
202                OpCapability Shader
203           %1 = OpExtInstImport "GLSL.std.450"
204                OpMemoryModel Logical GLSL450
205                OpEntryPoint Fragment %2 "main"
206                OpExecutionMode %2 OriginUpperLeft
207                OpSource GLSL 430
208           %3 = OpTypeVoid
209           %4 = OpTypeFunction %3
210           %5 = OpTypeFloat 32
211           %6 = OpTypePointer Function %5
212           %2 = OpFunction %3 None %4
213           %7 = OpLabel
214           %8 = OpVariable %6 Function
215           %9 = OpLoad %5 %8
216           %10 = OpLoad %5 %8
217                OpReturn
218                OpFunctionEnd
219   )";
220   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
221   ValueNumberTable vtable(context.get());
222   Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
223   Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
224   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
225 }
226 
TEST_F(ValueTableTest,DifferentUniformLoad)227 TEST_F(ValueTableTest, DifferentUniformLoad) {
228   const std::string text = R"(
229                OpCapability Shader
230           %1 = OpExtInstImport "GLSL.std.450"
231                OpMemoryModel Logical GLSL450
232                OpEntryPoint Fragment %2 "main"
233                OpExecutionMode %2 OriginUpperLeft
234                OpSource GLSL 430
235           %3 = OpTypeVoid
236           %4 = OpTypeFunction %3
237           %5 = OpTypeFloat 32
238           %6 = OpTypePointer Uniform %5
239           %8 = OpVariable %6 Uniform
240           %2 = OpFunction %3 None %4
241           %7 = OpLabel
242           %9 = OpLoad %5 %8
243           %10 = OpLoad %5 %8
244                OpReturn
245                OpFunctionEnd
246   )";
247   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
248   ValueNumberTable vtable(context.get());
249   Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
250   Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
251   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
252 }
253 
TEST_F(ValueTableTest,DifferentInputLoad)254 TEST_F(ValueTableTest, DifferentInputLoad) {
255   const std::string text = R"(
256                OpCapability Shader
257           %1 = OpExtInstImport "GLSL.std.450"
258                OpMemoryModel Logical GLSL450
259                OpEntryPoint Fragment %2 "main"
260                OpExecutionMode %2 OriginUpperLeft
261                OpSource GLSL 430
262           %3 = OpTypeVoid
263           %4 = OpTypeFunction %3
264           %5 = OpTypeFloat 32
265           %6 = OpTypePointer Input %5
266           %8 = OpVariable %6 Input
267           %2 = OpFunction %3 None %4
268           %7 = OpLabel
269           %9 = OpLoad %5 %8
270           %10 = OpLoad %5 %8
271                OpReturn
272                OpFunctionEnd
273   )";
274   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
275   ValueNumberTable vtable(context.get());
276   Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
277   Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
278   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
279 }
280 
TEST_F(ValueTableTest,DifferentUniformConstantLoad)281 TEST_F(ValueTableTest, DifferentUniformConstantLoad) {
282   const std::string text = R"(
283                OpCapability Shader
284           %1 = OpExtInstImport "GLSL.std.450"
285                OpMemoryModel Logical GLSL450
286                OpEntryPoint Fragment %2 "main"
287                OpExecutionMode %2 OriginUpperLeft
288                OpSource GLSL 430
289           %3 = OpTypeVoid
290           %4 = OpTypeFunction %3
291           %5 = OpTypeFloat 32
292           %6 = OpTypePointer UniformConstant %5
293           %8 = OpVariable %6 UniformConstant
294           %2 = OpFunction %3 None %4
295           %7 = OpLabel
296           %9 = OpLoad %5 %8
297           %10 = OpLoad %5 %8
298                OpReturn
299                OpFunctionEnd
300   )";
301   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
302   ValueNumberTable vtable(context.get());
303   Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
304   Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
305   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
306 }
307 
TEST_F(ValueTableTest,DifferentPushConstantLoad)308 TEST_F(ValueTableTest, DifferentPushConstantLoad) {
309   const std::string text = R"(
310                OpCapability Shader
311           %1 = OpExtInstImport "GLSL.std.450"
312                OpMemoryModel Logical GLSL450
313                OpEntryPoint Fragment %2 "main"
314                OpExecutionMode %2 OriginUpperLeft
315                OpSource GLSL 430
316           %3 = OpTypeVoid
317           %4 = OpTypeFunction %3
318           %5 = OpTypeFloat 32
319           %6 = OpTypePointer PushConstant %5
320           %8 = OpVariable %6 PushConstant
321           %2 = OpFunction %3 None %4
322           %7 = OpLabel
323           %9 = OpLoad %5 %8
324           %10 = OpLoad %5 %8
325                OpReturn
326                OpFunctionEnd
327   )";
328   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
329   ValueNumberTable vtable(context.get());
330   Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
331   Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
332   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
333 }
334 
TEST_F(ValueTableTest,SameCall)335 TEST_F(ValueTableTest, SameCall) {
336   const std::string text = R"(
337                OpCapability Shader
338           %1 = OpExtInstImport "GLSL.std.450"
339                OpMemoryModel Logical GLSL450
340                OpEntryPoint Fragment %2 "main"
341                OpExecutionMode %2 OriginUpperLeft
342                OpSource GLSL 430
343           %3 = OpTypeVoid
344           %4 = OpTypeFunction %3
345           %5 = OpTypeFloat 32
346           %6 = OpTypeFunction %5
347           %7 = OpTypePointer Function %5
348           %8 = OpVariable %7 Private
349           %2 = OpFunction %3 None %4
350           %9 = OpLabel
351          %10 = OpFunctionCall %5 %11
352                OpReturn
353                OpFunctionEnd
354          %11 = OpFunction %5 None %6
355          %12 = OpLabel
356          %13 = OpLoad %5 %8
357                OpReturnValue %13
358                OpFunctionEnd
359   )";
360   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
361   ValueNumberTable vtable(context.get());
362   Instruction* inst = context->get_def_use_mgr()->GetDef(10);
363   EXPECT_EQ(vtable.GetValueNumber(inst), vtable.GetValueNumber(inst));
364 }
365 
366 // Function calls should be given a new value number, even if they are the same.
TEST_F(ValueTableTest,DifferentCall)367 TEST_F(ValueTableTest, DifferentCall) {
368   const std::string text = R"(
369                OpCapability Shader
370           %1 = OpExtInstImport "GLSL.std.450"
371                OpMemoryModel Logical GLSL450
372                OpEntryPoint Fragment %2 "main"
373                OpExecutionMode %2 OriginUpperLeft
374                OpSource GLSL 430
375           %3 = OpTypeVoid
376           %4 = OpTypeFunction %3
377           %5 = OpTypeFloat 32
378           %6 = OpTypeFunction %5
379           %7 = OpTypePointer Function %5
380           %8 = OpVariable %7 Private
381           %2 = OpFunction %3 None %4
382           %9 = OpLabel
383          %10 = OpFunctionCall %5 %11
384          %12 = OpFunctionCall %5 %11
385                OpReturn
386                OpFunctionEnd
387          %11 = OpFunction %5 None %6
388          %13 = OpLabel
389          %14 = OpLoad %5 %8
390                OpReturnValue %14
391                OpFunctionEnd
392   )";
393   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
394   ValueNumberTable vtable(context.get());
395   Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
396   Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
397   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
398 }
399 
400 // It is possible to have two instruction that compute the same numerical value,
401 // but with different types.  They should have different value numbers.
TEST_F(ValueTableTest,DifferentTypes)402 TEST_F(ValueTableTest, DifferentTypes) {
403   const std::string text = R"(
404                OpCapability Shader
405           %1 = OpExtInstImport "GLSL.std.450"
406                OpMemoryModel Logical GLSL450
407                OpEntryPoint Fragment %2 "main"
408                OpExecutionMode %2 OriginUpperLeft
409                OpSource GLSL 430
410           %3 = OpTypeVoid
411           %4 = OpTypeFunction %3
412           %5 = OpTypeInt 32 0
413           %6 = OpTypeInt 32 1
414           %7 = OpTypePointer Function %5
415           %2 = OpFunction %3 None %4
416           %8 = OpLabel
417           %9 = OpVariable %7 Function
418          %10 = OpLoad %5 %9
419          %11 = OpIAdd %5 %10 %10
420          %12 = OpIAdd %6 %10 %10
421                OpReturn
422                OpFunctionEnd
423   )";
424   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
425   ValueNumberTable vtable(context.get());
426   Instruction* inst1 = context->get_def_use_mgr()->GetDef(11);
427   Instruction* inst2 = context->get_def_use_mgr()->GetDef(12);
428   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
429 }
430 
TEST_F(ValueTableTest,CopyObject)431 TEST_F(ValueTableTest, CopyObject) {
432   const std::string text = R"(
433                OpCapability Shader
434           %1 = OpExtInstImport "GLSL.std.450"
435                OpMemoryModel Logical GLSL450
436                OpEntryPoint Fragment %2 "main"
437                OpExecutionMode %2 OriginUpperLeft
438                OpSource GLSL 430
439           %3 = OpTypeVoid
440           %4 = OpTypeFunction %3
441           %5 = OpTypeFloat 32
442           %6 = OpTypePointer Function %5
443           %2 = OpFunction %3 None %4
444           %7 = OpLabel
445           %8 = OpVariable %6 Function
446           %9 = OpLoad %5 %8
447          %10 = OpCopyObject %5 %9
448                OpReturn
449                OpFunctionEnd
450   )";
451   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
452   ValueNumberTable vtable(context.get());
453   Instruction* inst1 = context->get_def_use_mgr()->GetDef(9);
454   Instruction* inst2 = context->get_def_use_mgr()->GetDef(10);
455   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
456 }
457 
TEST_F(ValueTableTest,CopyObjectWitDecoration)458 TEST_F(ValueTableTest, CopyObjectWitDecoration) {
459   const std::string text = R"(
460                OpCapability Shader
461           %1 = OpExtInstImport "GLSL.std.450"
462                OpMemoryModel Logical GLSL450
463                OpEntryPoint Fragment %2 "main"
464                OpExecutionMode %2 OriginUpperLeft
465                OpSource GLSL 430
466                OpDecorate %3 NonUniformEXT
467           %4 = OpTypeVoid
468           %5 = OpTypeFunction %4
469           %6 = OpTypeFloat 32
470           %7 = OpTypePointer Function %6
471           %2 = OpFunction %4 None %5
472           %8 = OpLabel
473           %9 = OpVariable %7 Function
474          %10 = OpLoad %6 %9
475           %3 = OpCopyObject %6 %10
476                OpReturn
477                OpFunctionEnd
478   )";
479   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
480   ValueNumberTable vtable(context.get());
481   Instruction* inst1 = context->get_def_use_mgr()->GetDef(10);
482   Instruction* inst2 = context->get_def_use_mgr()->GetDef(3);
483   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
484 }
485 
486 // Test that a phi where the operands have the same value assigned that value
487 // to the result of the phi.
TEST_F(ValueTableTest,PhiTest1)488 TEST_F(ValueTableTest, PhiTest1) {
489   const std::string text = R"(
490                OpCapability Shader
491           %1 = OpExtInstImport "GLSL.std.450"
492                OpMemoryModel Logical GLSL450
493                OpEntryPoint Fragment %2 "main"
494                OpExecutionMode %2 OriginUpperLeft
495                OpSource GLSL 430
496           %3 = OpTypeVoid
497           %4 = OpTypeFunction %3
498           %5 = OpTypeFloat 32
499           %6 = OpTypePointer Uniform %5
500           %7 = OpTypeBool
501           %8 = OpConstantTrue %7
502           %9 = OpVariable %6 Uniform
503           %2 = OpFunction %3 None %4
504          %10 = OpLabel
505                OpBranchConditional %8 %11 %12
506          %11 = OpLabel
507          %13 = OpLoad %5 %9
508                OpBranch %14
509          %12 = OpLabel
510          %15 = OpLoad %5 %9
511                OpBranch %14
512          %14 = OpLabel
513          %16 = OpPhi %5 %13 %11 %15 %12
514                OpReturn
515                OpFunctionEnd
516   )";
517   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
518   ValueNumberTable vtable(context.get());
519   Instruction* inst1 = context->get_def_use_mgr()->GetDef(13);
520   Instruction* inst2 = context->get_def_use_mgr()->GetDef(15);
521   Instruction* phi = context->get_def_use_mgr()->GetDef(16);
522   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
523   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi));
524 }
525 
TEST_F(ValueTableTest,PhiTest1WithDecoration)526 TEST_F(ValueTableTest, PhiTest1WithDecoration) {
527   const std::string text = R"(
528                OpCapability Shader
529           %1 = OpExtInstImport "GLSL.std.450"
530                OpMemoryModel Logical GLSL450
531                OpEntryPoint Fragment %2 "main"
532                OpExecutionMode %2 OriginUpperLeft
533                OpSource GLSL 430
534                OpDecorate %3 NonUniformEXT
535           %4 = OpTypeVoid
536           %5 = OpTypeFunction %5
537           %6 = OpTypeFloat 32
538           %7 = OpTypePointer Uniform %6
539           %8 = OpTypeBool
540           %9 = OpConstantTrue %8
541           %10 = OpVariable %7 Uniform
542           %2 = OpFunction %4 None %5
543          %11 = OpLabel
544                OpBranchConditional %9 %12 %13
545          %12 = OpLabel
546          %14 = OpLoad %6 %10
547                OpBranch %15
548          %13 = OpLabel
549          %16 = OpLoad %6 %10
550                OpBranch %15
551          %15 = OpLabel
552          %3 = OpPhi %6 %14 %12 %16 %13
553                OpReturn
554                OpFunctionEnd
555   )";
556   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
557   ValueNumberTable vtable(context.get());
558   Instruction* inst1 = context->get_def_use_mgr()->GetDef(14);
559   Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
560   Instruction* phi = context->get_def_use_mgr()->GetDef(3);
561   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
562   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi));
563 }
564 
565 // When the values for the inputs to a phi do not match, then the phi should
566 // have its own value number.
TEST_F(ValueTableTest,PhiTest2)567 TEST_F(ValueTableTest, PhiTest2) {
568   const std::string text = R"(
569                OpCapability Shader
570           %1 = OpExtInstImport "GLSL.std.450"
571                OpMemoryModel Logical GLSL450
572                OpEntryPoint Fragment %2 "main"
573                OpExecutionMode %2 OriginUpperLeft
574                OpSource GLSL 430
575           %3 = OpTypeVoid
576           %4 = OpTypeFunction %3
577           %5 = OpTypeFloat 32
578           %6 = OpTypePointer Uniform %5
579           %7 = OpTypeBool
580           %8 = OpConstantTrue %7
581           %9 = OpVariable %6 Uniform
582          %10 = OpVariable %6 Uniform
583           %2 = OpFunction %3 None %4
584          %11 = OpLabel
585                OpBranchConditional %8 %12 %13
586          %12 = OpLabel
587          %14 = OpLoad %5 %9
588                OpBranch %15
589          %13 = OpLabel
590          %16 = OpLoad %5 %10
591                OpBranch %15
592          %15 = OpLabel
593          %17 = OpPhi %14 %12 %16 %13
594                OpReturn
595                OpFunctionEnd
596   )";
597   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
598   ValueNumberTable vtable(context.get());
599   Instruction* inst1 = context->get_def_use_mgr()->GetDef(14);
600   Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
601   Instruction* phi = context->get_def_use_mgr()->GetDef(17);
602   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
603   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi));
604   EXPECT_NE(vtable.GetValueNumber(inst2), vtable.GetValueNumber(phi));
605 }
606 
607 // Test that a phi node in a loop header gets a new value because one of its
608 // inputs comes from later in the loop.
TEST_F(ValueTableTest,PhiLoopTest)609 TEST_F(ValueTableTest, PhiLoopTest) {
610   const std::string text = R"(
611                OpCapability Shader
612           %1 = OpExtInstImport "GLSL.std.450"
613                OpMemoryModel Logical GLSL450
614                OpEntryPoint Fragment %2 "main"
615                OpExecutionMode %2 OriginUpperLeft
616                OpSource GLSL 430
617           %3 = OpTypeVoid
618           %4 = OpTypeFunction %3
619           %5 = OpTypeFloat 32
620           %6 = OpTypePointer Uniform %5
621           %7 = OpTypeBool
622           %8 = OpConstantTrue %7
623           %9 = OpVariable %6 Uniform
624          %10 = OpVariable %6 Uniform
625           %2 = OpFunction %3 None %4
626          %11 = OpLabel
627          %12 = OpLoad %5 %9
628                OpSelectionMerge %13 None
629                OpBranchConditional %8 %14 %13
630          %14 = OpLabel
631          %15 = OpPhi %5 %12 %11 %16 %14
632          %16 = OpLoad %5 %9
633                OpLoopMerge %17 %14 None
634                OpBranchConditional %8 %14 %17
635          %17 = OpLabel
636                OpBranch %13
637          %13 = OpLabel
638          %18 = OpPhi %5 %12 %11 %16 %17
639                OpReturn
640                OpFunctionEnd
641   )";
642   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
643   ValueNumberTable vtable(context.get());
644   Instruction* inst1 = context->get_def_use_mgr()->GetDef(12);
645   Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
646   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
647 
648   Instruction* phi1 = context->get_def_use_mgr()->GetDef(15);
649   EXPECT_NE(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi1));
650 
651   Instruction* phi2 = context->get_def_use_mgr()->GetDef(18);
652   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(phi2));
653   EXPECT_NE(vtable.GetValueNumber(phi1), vtable.GetValueNumber(phi2));
654 }
655 
656 // Test to make sure that OpPhi instructions with no in operands are handled
657 // correctly.
TEST_F(ValueTableTest,EmptyPhiTest)658 TEST_F(ValueTableTest, EmptyPhiTest) {
659   const std::string text = R"(
660                OpCapability Shader
661           %1 = OpExtInstImport "GLSL.std.450"
662                OpMemoryModel Logical GLSL450
663                OpEntryPoint Fragment %2 "main"
664                OpExecutionMode %2 OriginUpperLeft
665                OpSource GLSL 430
666        %void = OpTypeVoid
667           %4 = OpTypeFunction %void
668        %bool = OpTypeBool
669        %true = OpConstantTrue %bool
670           %2 = OpFunction %void None %4
671           %7 = OpLabel
672                OpSelectionMerge %8 None
673                OpBranchConditional %true %9 %8
674           %9 = OpLabel
675                OpKill
676           %8 = OpLabel
677          %10 = OpPhi %bool
678                OpReturn
679                OpFunctionEnd
680   )";
681   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
682   ValueNumberTable vtable(context.get());
683   Instruction* inst = context->get_def_use_mgr()->GetDef(10);
684   vtable.GetValueNumber(inst);
685 }
686 
TEST_F(ValueTableTest,RedundantSampledImageLoad)687 TEST_F(ValueTableTest, RedundantSampledImageLoad) {
688   const std::string text = R"(
689                OpCapability Shader
690           %1 = OpExtInstImport "GLSL.std.450"
691                OpMemoryModel Logical GLSL450
692                OpEntryPoint Fragment %main "main" %gl_FragColor
693                OpExecutionMode %main OriginLowerLeft
694                OpSource GLSL 330
695                OpName %main "main"
696                OpName %tex0 "tex0"
697                OpName %gl_FragColor "gl_FragColor"
698                OpDecorate %tex0 Location 0
699                OpDecorate %tex0 DescriptorSet 0
700                OpDecorate %tex0 Binding 0
701                OpDecorate %gl_FragColor Location 0
702        %void = OpTypeVoid
703           %6 = OpTypeFunction %void
704       %float = OpTypeFloat 32
705     %v4float = OpTypeVector %float 4
706           %9 = OpTypeImage %float 2D 0 0 0 1 Unknown
707          %10 = OpTypeSampledImage %9
708 %_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
709        %tex0 = OpVariable %_ptr_UniformConstant_10 UniformConstant
710 %_ptr_Output_v4float = OpTypePointer Output %v4float
711          %13 = OpConstantNull %v4float
712 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
713          %14 = OpUndef %v4float
714        %main = OpFunction %void None %6
715          %15 = OpLabel
716          %16 = OpLoad %10 %tex0
717          %17 = OpImageSampleProjImplicitLod %v4float %16 %13
718          %18 = OpImageSampleProjImplicitLod %v4float %16 %13
719          %19 = OpFAdd %v4float %18 %17
720                OpStore %gl_FragColor %19
721                OpReturn
722                OpFunctionEnd
723   )";
724   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
725   ValueNumberTable vtable(context.get());
726   Instruction* load1 = context->get_def_use_mgr()->GetDef(17);
727   Instruction* load2 = context->get_def_use_mgr()->GetDef(18);
728   EXPECT_EQ(vtable.GetValueNumber(load1), vtable.GetValueNumber(load2));
729 }
730 
TEST_F(ValueTableTest,DifferentDebugLocalVariableSameValue)731 TEST_F(ValueTableTest, DifferentDebugLocalVariableSameValue) {
732   const std::string text = R"(
733                OpCapability Shader
734           %1 = OpExtInstImport "GLSL.std.450"
735           %2 = OpExtInstImport "OpenCL.DebugInfo.100"
736                OpMemoryModel Logical GLSL450
737                OpEntryPoint Fragment %3 "main"
738                OpExecutionMode %3 OriginUpperLeft
739                OpSource GLSL 430
740           %4 = OpString "test"
741           %5 = OpTypeVoid
742           %6 = OpTypeFunction %5
743           %7 = OpTypeInt 32 0
744           %8 = OpConstant %7 32
745           %9 = OpExtInst %5 %2 DebugSource %4
746          %10 = OpExtInst %5 %2 DebugCompilationUnit 1 4 %9 HLSL
747          %11 = OpExtInst %5 %2 DebugTypeBasic %4 %8 Float
748          %12 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
749          %13 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
750           %3 = OpFunction %5 None %6
751          %14 = OpLabel
752                OpReturn
753                OpFunctionEnd
754   )";
755   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
756   ValueNumberTable vtable(context.get());
757   Instruction* inst1 = context->get_def_use_mgr()->GetDef(12);
758   Instruction* inst2 = context->get_def_use_mgr()->GetDef(13);
759   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
760 }
761 
TEST_F(ValueTableTest,DifferentDebugValueSameValue)762 TEST_F(ValueTableTest, DifferentDebugValueSameValue) {
763   const std::string text = R"(
764                OpCapability Shader
765           %1 = OpExtInstImport "GLSL.std.450"
766           %2 = OpExtInstImport "OpenCL.DebugInfo.100"
767                OpMemoryModel Logical GLSL450
768                OpEntryPoint Fragment %3 "main"
769                OpExecutionMode %3 OriginUpperLeft
770                OpSource GLSL 430
771           %4 = OpString "test"
772           %5 = OpTypeVoid
773           %6 = OpTypeFunction %5
774           %7 = OpTypeInt 32 0
775           %8 = OpConstant %7 32
776           %9 = OpExtInst %5 %2 DebugSource %4
777          %10 = OpExtInst %5 %2 DebugCompilationUnit 1 4 %9 HLSL
778          %11 = OpExtInst %5 %2 DebugTypeBasic %4 %8 Float
779          %12 = OpExtInst %5 %2 DebugLocalVariable %4 %11 %9 0 0 %10 FlagIsLocal
780          %13 = OpExtInst %5 %2 DebugExpression
781           %3 = OpFunction %5 None %6
782          %14 = OpLabel
783          %15 = OpExtInst %5 %2 DebugValue %12 %8 %13
784          %16 = OpExtInst %5 %2 DebugValue %12 %8 %13
785                OpReturn
786                OpFunctionEnd
787   )";
788   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
789   ValueNumberTable vtable(context.get());
790   Instruction* inst1 = context->get_def_use_mgr()->GetDef(15);
791   Instruction* inst2 = context->get_def_use_mgr()->GetDef(16);
792   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
793 }
794 
TEST_F(ValueTableTest,DifferentDebugDeclareSameValue)795 TEST_F(ValueTableTest, DifferentDebugDeclareSameValue) {
796   const std::string text = R"(
797                OpCapability Shader
798           %1 = OpExtInstImport "GLSL.std.450"
799           %2 = OpExtInstImport "OpenCL.DebugInfo.100"
800                OpMemoryModel Logical GLSL450
801                OpEntryPoint Fragment %3 "main"
802                OpExecutionMode %3 OriginUpperLeft
803                OpSource GLSL 430
804           %4 = OpString "test"
805        %void = OpTypeVoid
806           %6 = OpTypeFunction %void
807        %uint = OpTypeInt 32 0
808 %_ptr_Function_uint = OpTypePointer Function %uint
809     %uint_32 = OpConstant %uint 32
810          %10 = OpExtInst %void %2 DebugSource %4
811          %11 = OpExtInst %void %2 DebugCompilationUnit 1 4 %10 HLSL
812          %12 = OpExtInst %void %2 DebugTypeBasic %4 %uint_32 Float
813          %13 = OpExtInst %void %2 DebugLocalVariable %4 %12 %10 0 0 %11 FlagIsLocal
814          %14 = OpExtInst %void %2 DebugExpression
815           %3 = OpFunction %void None %6
816          %15 = OpLabel
817          %16 = OpVariable %_ptr_Function_uint Function
818          %17 = OpExtInst %void %2 DebugDeclare %13 %16 %14
819          %18 = OpExtInst %void %2 DebugDeclare %13 %16 %14
820                OpReturn
821                OpFunctionEnd
822   )";
823   auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
824   ValueNumberTable vtable(context.get());
825   Instruction* inst1 = context->get_def_use_mgr()->GetDef(17);
826   Instruction* inst2 = context->get_def_use_mgr()->GetDef(18);
827   EXPECT_EQ(vtable.GetValueNumber(inst1), vtable.GetValueNumber(inst2));
828 }
829 
830 }  // namespace
831 }  // namespace opt
832 }  // namespace spvtools
833