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