1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC
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 "source/reduce/operand_to_undef_reduction_opportunity_finder.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h"
18fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_opportunity.h"
19fd4e5da5Sopenharmony_ci#include "test/reduce/reduce_test_util.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace reduce {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciTEST(OperandToUndefReductionPassTest, BasicCheck) {
26fd4e5da5Sopenharmony_ci  // The following shader has 10 opportunities for replacing with undef.
27fd4e5da5Sopenharmony_ci
28fd4e5da5Sopenharmony_ci  //    #version 310 es
29fd4e5da5Sopenharmony_ci  //
30fd4e5da5Sopenharmony_ci  //    precision highp float;
31fd4e5da5Sopenharmony_ci  //
32fd4e5da5Sopenharmony_ci  //    layout(location=0) out vec4 _GLF_color;
33fd4e5da5Sopenharmony_ci  //
34fd4e5da5Sopenharmony_ci  //    layout(set = 0, binding = 0) uniform buf0 {
35fd4e5da5Sopenharmony_ci  //        vec2 uniform1;
36fd4e5da5Sopenharmony_ci  //    };
37fd4e5da5Sopenharmony_ci  //
38fd4e5da5Sopenharmony_ci  //    void main()
39fd4e5da5Sopenharmony_ci  //    {
40fd4e5da5Sopenharmony_ci  //        _GLF_color =
41fd4e5da5Sopenharmony_ci  //            vec4(                          // opportunity
42fd4e5da5Sopenharmony_ci  //                uniform1.x / 2.0,          // opportunity x2 (2.0 is const)
43fd4e5da5Sopenharmony_ci  //                uniform1.y / uniform1.x,   // opportunity x3
44fd4e5da5Sopenharmony_ci  //                uniform1.x + uniform1.x,   // opportunity x3
45fd4e5da5Sopenharmony_ci  //                uniform1.y);               // opportunity
46fd4e5da5Sopenharmony_ci  //    }
47fd4e5da5Sopenharmony_ci
48fd4e5da5Sopenharmony_ci  std::string original = R"(
49fd4e5da5Sopenharmony_ci               OpCapability Shader
50fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
51fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
52fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %9
53fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
54fd4e5da5Sopenharmony_ci               OpSource ESSL 310
55fd4e5da5Sopenharmony_ci               OpName %4 "main"
56fd4e5da5Sopenharmony_ci               OpName %9 "_GLF_color"
57fd4e5da5Sopenharmony_ci               OpName %11 "buf0"
58fd4e5da5Sopenharmony_ci               OpMemberName %11 0 "uniform1"
59fd4e5da5Sopenharmony_ci               OpName %13 ""
60fd4e5da5Sopenharmony_ci               OpDecorate %9 Location 0
61fd4e5da5Sopenharmony_ci               OpMemberDecorate %11 0 Offset 0
62fd4e5da5Sopenharmony_ci               OpDecorate %11 Block
63fd4e5da5Sopenharmony_ci               OpDecorate %13 DescriptorSet 0
64fd4e5da5Sopenharmony_ci               OpDecorate %13 Binding 0
65fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
66fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
67fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
68fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
69fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Output %7
70fd4e5da5Sopenharmony_ci          %9 = OpVariable %8 Output
71fd4e5da5Sopenharmony_ci         %10 = OpTypeVector %6 2
72fd4e5da5Sopenharmony_ci         %11 = OpTypeStruct %10
73fd4e5da5Sopenharmony_ci         %12 = OpTypePointer Uniform %11
74fd4e5da5Sopenharmony_ci         %13 = OpVariable %12 Uniform
75fd4e5da5Sopenharmony_ci         %14 = OpTypeInt 32 1
76fd4e5da5Sopenharmony_ci         %15 = OpConstant %14 0
77fd4e5da5Sopenharmony_ci         %16 = OpTypeInt 32 0
78fd4e5da5Sopenharmony_ci         %17 = OpConstant %16 0
79fd4e5da5Sopenharmony_ci         %18 = OpTypePointer Uniform %6
80fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 2
81fd4e5da5Sopenharmony_ci         %23 = OpConstant %16 1
82fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
83fd4e5da5Sopenharmony_ci          %5 = OpLabel
84fd4e5da5Sopenharmony_ci         %19 = OpAccessChain %18 %13 %15 %17
85fd4e5da5Sopenharmony_ci         %20 = OpLoad %6 %19
86fd4e5da5Sopenharmony_ci         %22 = OpFDiv %6 %20 %21                         ; opportunity %20 (%21 is const)
87fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %18 %13 %15 %23
88fd4e5da5Sopenharmony_ci         %25 = OpLoad %6 %24
89fd4e5da5Sopenharmony_ci         %26 = OpAccessChain %18 %13 %15 %17
90fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %26
91fd4e5da5Sopenharmony_ci         %28 = OpFDiv %6 %25 %27                         ; opportunity %25 %27
92fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %18 %13 %15 %17
93fd4e5da5Sopenharmony_ci         %30 = OpLoad %6 %29
94fd4e5da5Sopenharmony_ci         %31 = OpAccessChain %18 %13 %15 %17
95fd4e5da5Sopenharmony_ci         %32 = OpLoad %6 %31
96fd4e5da5Sopenharmony_ci         %33 = OpFAdd %6 %30 %32                         ; opportunity %30 %32
97fd4e5da5Sopenharmony_ci         %34 = OpAccessChain %18 %13 %15 %23
98fd4e5da5Sopenharmony_ci         %35 = OpLoad %6 %34
99fd4e5da5Sopenharmony_ci         %36 = OpCompositeConstruct %7 %22 %28 %33 %35   ; opportunity %22 %28 %33 %35
100fd4e5da5Sopenharmony_ci               OpStore %9 %36                            ; opportunity %36
101fd4e5da5Sopenharmony_ci               OpReturn
102fd4e5da5Sopenharmony_ci               OpFunctionEnd
103fd4e5da5Sopenharmony_ci  )";
104fd4e5da5Sopenharmony_ci
105fd4e5da5Sopenharmony_ci  // This is the same as original, except where noted.
106fd4e5da5Sopenharmony_ci  std::string expected = R"(
107fd4e5da5Sopenharmony_ci               OpCapability Shader
108fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
109fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
110fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %9
111fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
112fd4e5da5Sopenharmony_ci               OpSource ESSL 310
113fd4e5da5Sopenharmony_ci               OpName %4 "main"
114fd4e5da5Sopenharmony_ci               OpName %9 "_GLF_color"
115fd4e5da5Sopenharmony_ci               OpName %11 "buf0"
116fd4e5da5Sopenharmony_ci               OpMemberName %11 0 "uniform1"
117fd4e5da5Sopenharmony_ci               OpName %13 ""
118fd4e5da5Sopenharmony_ci               OpDecorate %9 Location 0
119fd4e5da5Sopenharmony_ci               OpMemberDecorate %11 0 Offset 0
120fd4e5da5Sopenharmony_ci               OpDecorate %11 Block
121fd4e5da5Sopenharmony_ci               OpDecorate %13 DescriptorSet 0
122fd4e5da5Sopenharmony_ci               OpDecorate %13 Binding 0
123fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
124fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
125fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
126fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
127fd4e5da5Sopenharmony_ci          %8 = OpTypePointer Output %7
128fd4e5da5Sopenharmony_ci          %9 = OpVariable %8 Output
129fd4e5da5Sopenharmony_ci         %10 = OpTypeVector %6 2
130fd4e5da5Sopenharmony_ci         %11 = OpTypeStruct %10
131fd4e5da5Sopenharmony_ci         %12 = OpTypePointer Uniform %11
132fd4e5da5Sopenharmony_ci         %13 = OpVariable %12 Uniform
133fd4e5da5Sopenharmony_ci         %14 = OpTypeInt 32 1
134fd4e5da5Sopenharmony_ci         %15 = OpConstant %14 0
135fd4e5da5Sopenharmony_ci         %16 = OpTypeInt 32 0
136fd4e5da5Sopenharmony_ci         %17 = OpConstant %16 0
137fd4e5da5Sopenharmony_ci         %18 = OpTypePointer Uniform %6
138fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 2
139fd4e5da5Sopenharmony_ci         %23 = OpConstant %16 1
140fd4e5da5Sopenharmony_ci         %37 = OpUndef %6                            ; Added undef float as %37
141fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
142fd4e5da5Sopenharmony_ci          %5 = OpLabel
143fd4e5da5Sopenharmony_ci         %19 = OpAccessChain %18 %13 %15 %17
144fd4e5da5Sopenharmony_ci         %20 = OpLoad %6 %19
145fd4e5da5Sopenharmony_ci         %22 = OpFDiv %6 %37 %21                     ; Replaced with %37
146fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %18 %13 %15 %23
147fd4e5da5Sopenharmony_ci         %25 = OpLoad %6 %24
148fd4e5da5Sopenharmony_ci         %26 = OpAccessChain %18 %13 %15 %17
149fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %26
150fd4e5da5Sopenharmony_ci         %28 = OpFDiv %6 %37 %37                     ; Replaced with %37 twice
151fd4e5da5Sopenharmony_ci         %29 = OpAccessChain %18 %13 %15 %17
152fd4e5da5Sopenharmony_ci         %30 = OpLoad %6 %29
153fd4e5da5Sopenharmony_ci         %31 = OpAccessChain %18 %13 %15 %17
154fd4e5da5Sopenharmony_ci         %32 = OpLoad %6 %31
155fd4e5da5Sopenharmony_ci         %33 = OpFAdd %6 %30 %32
156fd4e5da5Sopenharmony_ci         %34 = OpAccessChain %18 %13 %15 %23
157fd4e5da5Sopenharmony_ci         %35 = OpLoad %6 %34
158fd4e5da5Sopenharmony_ci         %36 = OpCompositeConstruct %7 %22 %28 %33 %35
159fd4e5da5Sopenharmony_ci               OpStore %9 %36
160fd4e5da5Sopenharmony_ci               OpReturn
161fd4e5da5Sopenharmony_ci               OpFunctionEnd
162fd4e5da5Sopenharmony_ci  )";
163fd4e5da5Sopenharmony_ci
164fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
165fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
166fd4e5da5Sopenharmony_ci  const auto context =
167fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, original, kReduceAssembleOption);
168fd4e5da5Sopenharmony_ci  const auto ops =
169fd4e5da5Sopenharmony_ci      OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities(
170fd4e5da5Sopenharmony_ci          context.get(), 0);
171fd4e5da5Sopenharmony_ci
172fd4e5da5Sopenharmony_ci  ASSERT_EQ(10, ops.size());
173fd4e5da5Sopenharmony_ci
174fd4e5da5Sopenharmony_ci  // Apply first three opportunities.
175fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[0]->PreconditionHolds());
176fd4e5da5Sopenharmony_ci  ops[0]->TryToApply();
177fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[1]->PreconditionHolds());
178fd4e5da5Sopenharmony_ci  ops[1]->TryToApply();
179fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ops[2]->PreconditionHolds());
180fd4e5da5Sopenharmony_ci  ops[2]->TryToApply();
181fd4e5da5Sopenharmony_ci
182fd4e5da5Sopenharmony_ci  CheckEqual(env, expected, context.get());
183fd4e5da5Sopenharmony_ci}
184fd4e5da5Sopenharmony_ci
185fd4e5da5Sopenharmony_ciTEST(OperandToUndefReductionPassTest, WithCalledFunction) {
186fd4e5da5Sopenharmony_ci  // The following shader has no opportunities.
187fd4e5da5Sopenharmony_ci  // Most importantly, the noted function operand is not changed.
188fd4e5da5Sopenharmony_ci
189fd4e5da5Sopenharmony_ci  std::string shader = R"(
190fd4e5da5Sopenharmony_ci               OpCapability Shader
191fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
192fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
193fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %10 %12
194fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
195fd4e5da5Sopenharmony_ci               OpSource ESSL 310
196fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
197fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
198fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
199fd4e5da5Sopenharmony_ci          %7 = OpTypeVector %6 4
200fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %7
201fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Output %7
202fd4e5da5Sopenharmony_ci         %10 = OpVariable %9 Output
203fd4e5da5Sopenharmony_ci         %11 = OpTypePointer Input %7
204fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 Input
205fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 0
206fd4e5da5Sopenharmony_ci         %14 = OpConstantComposite %7 %13 %13 %13 %13
207fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
208fd4e5da5Sopenharmony_ci          %5 = OpLabel
209fd4e5da5Sopenharmony_ci         %15 = OpFunctionCall %7 %16            ; do not replace %16 with undef
210fd4e5da5Sopenharmony_ci               OpReturn
211fd4e5da5Sopenharmony_ci               OpFunctionEnd
212fd4e5da5Sopenharmony_ci         %16 = OpFunction %7 None %8
213fd4e5da5Sopenharmony_ci         %17 = OpLabel
214fd4e5da5Sopenharmony_ci               OpReturnValue %14
215fd4e5da5Sopenharmony_ci               OpFunctionEnd
216fd4e5da5Sopenharmony_ci  )";
217fd4e5da5Sopenharmony_ci
218fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
219fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
220fd4e5da5Sopenharmony_ci  const auto context =
221fd4e5da5Sopenharmony_ci      BuildModule(env, consumer, shader, kReduceAssembleOption);
222fd4e5da5Sopenharmony_ci  const auto ops =
223fd4e5da5Sopenharmony_ci      OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities(
224fd4e5da5Sopenharmony_ci          context.get(), 0);
225fd4e5da5Sopenharmony_ci  ASSERT_EQ(0, ops.size());
226fd4e5da5Sopenharmony_ci}
227fd4e5da5Sopenharmony_ci
228fd4e5da5Sopenharmony_ci}  // namespace
229fd4e5da5Sopenharmony_ci}  // namespace reduce
230fd4e5da5Sopenharmony_ci}  // namespace spvtools
231