• 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 #include "test/opt/pass_utils.h"
23 
24 namespace spvtools {
25 namespace opt {
26 namespace {
27 
28 using ::testing::HasSubstr;
29 using ::testing::MatchesRegex;
30 using LocalRedundancyEliminationTest = PassTest<::testing::Test>;
31 
32 // Remove an instruction when it was already computed.
TEST_F(LocalRedundancyEliminationTest,RemoveRedundantAdd)33 TEST_F(LocalRedundancyEliminationTest, RemoveRedundantAdd) {
34   const std::string text = R"(
35                OpCapability Shader
36           %1 = OpExtInstImport "GLSL.std.450"
37                OpMemoryModel Logical GLSL450
38                OpEntryPoint Fragment %2 "main"
39                OpExecutionMode %2 OriginUpperLeft
40                OpSource GLSL 430
41           %3 = OpTypeVoid
42           %4 = OpTypeFunction %3
43           %5 = OpTypeFloat 32
44           %6 = OpTypePointer Function %5
45           %2 = OpFunction %3 None %4
46           %7 = OpLabel
47           %8 = OpVariable %6 Function
48           %9 = OpLoad %5 %8
49          %10 = OpFAdd %5 %9 %9
50 ; CHECK: OpFAdd
51 ; CHECK-NOT: OpFAdd
52          %11 = OpFAdd %5 %9 %9
53                OpReturn
54                OpFunctionEnd
55   )";
56   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
57 }
58 
59 // Make sure we keep instruction that are different, but look similar.
TEST_F(LocalRedundancyEliminationTest,KeepDifferentAdd)60 TEST_F(LocalRedundancyEliminationTest, KeepDifferentAdd) {
61   const std::string text = R"(
62                OpCapability Shader
63           %1 = OpExtInstImport "GLSL.std.450"
64                OpMemoryModel Logical GLSL450
65                OpEntryPoint Fragment %2 "main"
66                OpExecutionMode %2 OriginUpperLeft
67                OpSource GLSL 430
68           %3 = OpTypeVoid
69           %4 = OpTypeFunction %3
70           %5 = OpTypeFloat 32
71           %6 = OpTypePointer Function %5
72           %2 = OpFunction %3 None %4
73           %7 = OpLabel
74           %8 = OpVariable %6 Function
75           %9 = OpLoad %5 %8
76          %10 = OpFAdd %5 %9 %9
77 ; CHECK: OpFAdd
78                OpStore %8 %10
79          %11 = OpLoad %5 %8
80 ; CHECK: %11 = OpLoad
81          %12 = OpFAdd %5 %11 %11
82 ; CHECK: OpFAdd [[:%\w+]] %11 %11
83                OpReturn
84                OpFunctionEnd
85   )";
86   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
87   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
88 }
89 
90 // This test is check that the values are being propagated properly, and that
91 // we are able to identify sequences of instruction that are not needed.
TEST_F(LocalRedundancyEliminationTest,RemoveMultipleInstructions)92 TEST_F(LocalRedundancyEliminationTest, RemoveMultipleInstructions) {
93   const std::string text = R"(
94                OpCapability Shader
95           %1 = OpExtInstImport "GLSL.std.450"
96                OpMemoryModel Logical GLSL450
97                OpEntryPoint Fragment %2 "main"
98                OpExecutionMode %2 OriginUpperLeft
99                OpSource GLSL 430
100           %3 = OpTypeVoid
101           %4 = OpTypeFunction %3
102           %5 = OpTypeFloat 32
103           %6 = OpTypePointer Uniform %5
104           %8 = OpVariable %6 Uniform
105           %2 = OpFunction %3 None %4
106           %7 = OpLabel
107 ; CHECK: [[r1:%\w+]] = OpLoad
108           %9 = OpLoad %5 %8
109 ; CHECK-NEXT: [[r2:%\w+]] = OpFAdd [[:%\w+]] [[r1]] [[r1]]
110          %10 = OpFAdd %5 %9 %9
111 ; CHECK-NEXT: [[r3:%\w+]] = OpFMul [[:%\w+]] [[r2]] [[r1]]
112          %11 = OpFMul %5 %10 %9
113 ; CHECK-NOT: OpLoad
114          %12 = OpLoad %5 %8
115 ; CHECK-NOT: OpFAdd [[:\w+]] %12 %12
116          %13 = OpFAdd %5 %12 %12
117 ; CHECK-NOT: OpFMul
118          %14 = OpFMul %5 %13 %12
119 ; CHECK-NEXT: [[:%\w+]] = OpFAdd [[:%\w+]] [[r3]] [[r3]]
120          %15 = OpFAdd %5 %14 %11
121                OpReturn
122                OpFunctionEnd
123   )";
124   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
125   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
126 }
127 
128 // Redundant instructions in different blocks should be kept.
TEST_F(LocalRedundancyEliminationTest,KeepInstructionsInDifferentBlocks)129 TEST_F(LocalRedundancyEliminationTest, KeepInstructionsInDifferentBlocks) {
130   const std::string text = R"(
131                OpCapability Shader
132           %1 = OpExtInstImport "GLSL.std.450"
133                OpMemoryModel Logical GLSL450
134                OpEntryPoint Fragment %2 "main"
135                OpExecutionMode %2 OriginUpperLeft
136                OpSource GLSL 430
137           %3 = OpTypeVoid
138           %4 = OpTypeFunction %3
139           %5 = OpTypeFloat 32
140           %6 = OpTypePointer Function %5
141           %2 = OpFunction %3 None %4
142         %bb1 = OpLabel
143           %8 = OpVariable %6 Function
144           %9 = OpLoad %5 %8
145          %10 = OpFAdd %5 %9 %9
146 ; CHECK: OpFAdd
147                OpBranch %bb2
148         %bb2 = OpLabel
149 ; CHECK: OpFAdd
150          %11 = OpFAdd %5 %9 %9
151                OpReturn
152                OpFunctionEnd
153   )";
154   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
155 }
156 
TEST_F(LocalRedundancyEliminationTest,StorageBufferIdentification)157 TEST_F(LocalRedundancyEliminationTest, StorageBufferIdentification) {
158   const std::string text = R"(
159 ; CHECK: [[gep:%\w+]] = OpAccessChain
160 ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[gep]]
161 ; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]]
162 ; CHECK: OpStore [[gep]] [[add]]
163 ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[gep]]
164 ; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]]
165 ; CHECK: OpStore [[gep]] [[add]]
166 
167 OpCapability Shader
168 OpCapability Linkage
169 OpMemoryModel Logical GLSL450
170 OpDecorate %block BufferBlock
171 OpMemberDecorate %block 0 Offset 0
172 %void = OpTypeVoid
173 %int = OpTypeInt 32 0
174 %int_0 = OpConstant %int 0
175 %int_1 = OpConstant %int 1
176 %block = OpTypeStruct %int
177 %array = OpTypeArray %block %int_1
178 %ptr_ssbo_array = OpTypePointer Uniform %array
179 %ptr_ssbo_int = OpTypePointer Uniform %int
180 %var = OpVariable %ptr_ssbo_array Uniform
181 %void_fn = OpTypeFunction %void
182 %fn = OpFunction %void None %void_fn
183 %entry = OpLabel
184 %gep1 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
185 %ld1 = OpLoad %int %gep1
186 %add1 = OpIAdd %int %ld1 %int_1
187 %gep2 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
188 OpStore %gep2 %add1
189 %gep3 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
190 %ld3 = OpLoad %int %gep3
191 %add3 = OpIAdd %int %ld3 %int_1
192 %gep4 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
193 OpStore %gep4 %add3
194 OpReturn
195 OpFunctionEnd
196 )";
197 
198   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, true);
199 }
200 
201 }  // namespace
202 }  // namespace opt
203 }  // namespace spvtools
204