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