blob: 381589b53d021946459ac4e1a1d5f01ed43ba92a [file] [log] [blame]
Chris Forbescc5697f2019-01-30 11:54:08 -08001// Copyright (c) 2016 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 "spirv-tools/optimizer.hpp"
16
Ben Claytond0f684e2019-08-30 22:36:08 +010017#include <cassert>
Chris Forbescc5697f2019-01-30 11:54:08 -080018#include <memory>
19#include <string>
20#include <unordered_map>
21#include <utility>
22#include <vector>
23
Chris Forbescc5697f2019-01-30 11:54:08 -080024#include "source/opt/build_module.h"
Ben Claytond0f684e2019-08-30 22:36:08 +010025#include "source/opt/graphics_robust_access_pass.h"
Chris Forbescc5697f2019-01-30 11:54:08 -080026#include "source/opt/log.h"
27#include "source/opt/pass_manager.h"
28#include "source/opt/passes.h"
Ben Claytond552f632019-11-18 11:18:41 +000029#include "source/spirv_optimizer_options.h"
Chris Forbescc5697f2019-01-30 11:54:08 -080030#include "source/util/make_unique.h"
31#include "source/util/string_utils.h"
32
33namespace spvtools {
34
35struct Optimizer::PassToken::Impl {
36 Impl(std::unique_ptr<opt::Pass> p) : pass(std::move(p)) {}
37
38 std::unique_ptr<opt::Pass> pass; // Internal implementation pass.
39};
40
41Optimizer::PassToken::PassToken(
42 std::unique_ptr<Optimizer::PassToken::Impl> impl)
43 : impl_(std::move(impl)) {}
44
45Optimizer::PassToken::PassToken(std::unique_ptr<opt::Pass>&& pass)
46 : impl_(MakeUnique<Optimizer::PassToken::Impl>(std::move(pass))) {}
47
48Optimizer::PassToken::PassToken(PassToken&& that)
49 : impl_(std::move(that.impl_)) {}
50
51Optimizer::PassToken& Optimizer::PassToken::operator=(PassToken&& that) {
52 impl_ = std::move(that.impl_);
53 return *this;
54}
55
56Optimizer::PassToken::~PassToken() {}
57
58struct Optimizer::Impl {
59 explicit Impl(spv_target_env env) : target_env(env), pass_manager() {}
60
Ben Claytonb73b7602019-07-29 13:56:13 +010061 spv_target_env target_env; // Target environment.
62 opt::PassManager pass_manager; // Internal implementation pass manager.
Chris Forbescc5697f2019-01-30 11:54:08 -080063};
64
Ben Clayton745997b2021-01-21 22:51:51 +000065Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {
66 assert(env != SPV_ENV_WEBGPU_0);
67}
Chris Forbescc5697f2019-01-30 11:54:08 -080068
69Optimizer::~Optimizer() {}
70
71void Optimizer::SetMessageConsumer(MessageConsumer c) {
72 // All passes' message consumer needs to be updated.
73 for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); ++i) {
74 impl_->pass_manager.GetPass(i)->SetMessageConsumer(c);
75 }
76 impl_->pass_manager.SetMessageConsumer(std::move(c));
77}
78
79const MessageConsumer& Optimizer::consumer() const {
80 return impl_->pass_manager.consumer();
81}
82
83Optimizer& Optimizer::RegisterPass(PassToken&& p) {
84 // Change to use the pass manager's consumer.
85 p.impl_->pass->SetMessageConsumer(consumer());
86 impl_->pass_manager.AddPass(std::move(p.impl_->pass));
87 return *this;
88}
89
90// The legalization passes take a spir-v shader generated by an HLSL front-end
91// and turn it into a valid vulkan spir-v shader. There are two ways in which
92// the code will be invalid at the start:
93//
94// 1) There will be opaque objects, like images, which will be passed around
95// in intermediate objects. Valid spir-v will have to replace the use of
96// the opaque object with an intermediate object that is the result of the
97// load of the global opaque object.
98//
99// 2) There will be variables that contain pointers to structured or uniform
100// buffers. It be legal, the variables must be eliminated, and the
101// references to the structured buffers must use the result of OpVariable
102// in the Uniform storage class.
103//
104// Optimization in this list must accept shaders with these relaxation of the
105// rules. There is not guarantee that this list of optimizations is able to
106// legalize all inputs, but it is on a best effort basis.
107//
108// The legalization problem is essentially a very general copy propagation
109// problem. The optimization we use are all used to either do copy propagation
110// or enable more copy propagation.
111Optimizer& Optimizer::RegisterLegalizationPasses() {
112 return
Ben Claytond0f684e2019-08-30 22:36:08 +0100113 // Wrap OpKill instructions so all other code can be inlined.
114 RegisterPass(CreateWrapOpKillPass())
115 // Remove unreachable block so that merge return works.
116 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800117 // Merge the returns so we can inline.
118 .RegisterPass(CreateMergeReturnPass())
119 // Make sure uses and definitions are in the same function.
120 .RegisterPass(CreateInlineExhaustivePass())
121 // Make private variable function scope
122 .RegisterPass(CreateEliminateDeadFunctionsPass())
123 .RegisterPass(CreatePrivateToLocalPass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100124 // Fix up the storage classes that DXC may have purposely generated
125 // incorrectly. All functions are inlined, and a lot of dead code has
126 // been removed.
127 .RegisterPass(CreateFixStorageClassPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800128 // Propagate the value stored to the loads in very simple cases.
129 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
130 .RegisterPass(CreateLocalSingleStoreElimPass())
131 .RegisterPass(CreateAggressiveDCEPass())
132 // Split up aggregates so they are easier to deal with.
133 .RegisterPass(CreateScalarReplacementPass(0))
134 // Remove loads and stores so everything is in intermediate values.
135 // Takes care of copy propagation of non-members.
136 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
137 .RegisterPass(CreateLocalSingleStoreElimPass())
138 .RegisterPass(CreateAggressiveDCEPass())
139 .RegisterPass(CreateLocalMultiStoreElimPass())
140 .RegisterPass(CreateAggressiveDCEPass())
141 // Propagate constants to get as many constant conditions on branches
142 // as possible.
143 .RegisterPass(CreateCCPPass())
144 .RegisterPass(CreateLoopUnrollPass(true))
145 .RegisterPass(CreateDeadBranchElimPass())
146 // Copy propagate members. Cleans up code sequences generated by
147 // scalar replacement. Also important for removing OpPhi nodes.
148 .RegisterPass(CreateSimplificationPass())
149 .RegisterPass(CreateAggressiveDCEPass())
150 .RegisterPass(CreateCopyPropagateArraysPass())
151 // May need loop unrolling here see
152 // https://github.com/Microsoft/DirectXShaderCompiler/pull/930
153 // Get rid of unused code that contain traces of illegal code
154 // or unused references to unbound external objects
155 .RegisterPass(CreateVectorDCEPass())
156 .RegisterPass(CreateDeadInsertElimPass())
157 .RegisterPass(CreateReduceLoadSizePass())
Alexis Hetu00e0af12021-11-08 08:57:46 -0500158 .RegisterPass(CreateAggressiveDCEPass())
159 .RegisterPass(CreateInterpolateFixupPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800160}
161
162Optimizer& Optimizer::RegisterPerformancePasses() {
Ben Claytond0f684e2019-08-30 22:36:08 +0100163 return RegisterPass(CreateWrapOpKillPass())
164 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800165 .RegisterPass(CreateMergeReturnPass())
166 .RegisterPass(CreateInlineExhaustivePass())
Sean Risserd2283f82020-11-05 14:17:31 -0500167 .RegisterPass(CreateEliminateDeadFunctionsPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800168 .RegisterPass(CreateAggressiveDCEPass())
169 .RegisterPass(CreatePrivateToLocalPass())
170 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
171 .RegisterPass(CreateLocalSingleStoreElimPass())
172 .RegisterPass(CreateAggressiveDCEPass())
173 .RegisterPass(CreateScalarReplacementPass())
174 .RegisterPass(CreateLocalAccessChainConvertPass())
175 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
176 .RegisterPass(CreateLocalSingleStoreElimPass())
177 .RegisterPass(CreateAggressiveDCEPass())
178 .RegisterPass(CreateLocalMultiStoreElimPass())
179 .RegisterPass(CreateAggressiveDCEPass())
180 .RegisterPass(CreateCCPPass())
181 .RegisterPass(CreateAggressiveDCEPass())
Ben Clayton38e46912020-05-26 15:56:15 +0100182 .RegisterPass(CreateLoopUnrollPass(true))
183 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800184 .RegisterPass(CreateRedundancyEliminationPass())
185 .RegisterPass(CreateCombineAccessChainsPass())
186 .RegisterPass(CreateSimplificationPass())
Ben Clayton38e46912020-05-26 15:56:15 +0100187 .RegisterPass(CreateScalarReplacementPass())
188 .RegisterPass(CreateLocalAccessChainConvertPass())
189 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
190 .RegisterPass(CreateLocalSingleStoreElimPass())
191 .RegisterPass(CreateAggressiveDCEPass())
192 .RegisterPass(CreateSSARewritePass())
193 .RegisterPass(CreateAggressiveDCEPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800194 .RegisterPass(CreateVectorDCEPass())
195 .RegisterPass(CreateDeadInsertElimPass())
196 .RegisterPass(CreateDeadBranchElimPass())
197 .RegisterPass(CreateSimplificationPass())
198 .RegisterPass(CreateIfConversionPass())
199 .RegisterPass(CreateCopyPropagateArraysPass())
200 .RegisterPass(CreateReduceLoadSizePass())
201 .RegisterPass(CreateAggressiveDCEPass())
202 .RegisterPass(CreateBlockMergePass())
203 .RegisterPass(CreateRedundancyEliminationPass())
204 .RegisterPass(CreateDeadBranchElimPass())
205 .RegisterPass(CreateBlockMergePass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100206 .RegisterPass(CreateSimplificationPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800207}
208
209Optimizer& Optimizer::RegisterSizePasses() {
Ben Claytond0f684e2019-08-30 22:36:08 +0100210 return RegisterPass(CreateWrapOpKillPass())
211 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800212 .RegisterPass(CreateMergeReturnPass())
213 .RegisterPass(CreateInlineExhaustivePass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000214 .RegisterPass(CreateEliminateDeadFunctionsPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800215 .RegisterPass(CreatePrivateToLocalPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000216 .RegisterPass(CreateScalarReplacementPass(0))
Chris Forbescc5697f2019-01-30 11:54:08 -0800217 .RegisterPass(CreateLocalMultiStoreElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800218 .RegisterPass(CreateCCPPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000219 .RegisterPass(CreateLoopUnrollPass(true))
220 .RegisterPass(CreateDeadBranchElimPass())
221 .RegisterPass(CreateSimplificationPass())
222 .RegisterPass(CreateScalarReplacementPass(0))
223 .RegisterPass(CreateLocalSingleStoreElimPass())
224 .RegisterPass(CreateIfConversionPass())
225 .RegisterPass(CreateSimplificationPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800226 .RegisterPass(CreateAggressiveDCEPass())
227 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800228 .RegisterPass(CreateBlockMergePass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000229 .RegisterPass(CreateLocalAccessChainConvertPass())
230 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
231 .RegisterPass(CreateAggressiveDCEPass())
232 .RegisterPass(CreateCopyPropagateArraysPass())
233 .RegisterPass(CreateVectorDCEPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800234 .RegisterPass(CreateDeadInsertElimPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000235 .RegisterPass(CreateEliminateDeadMembersPass())
236 .RegisterPass(CreateLocalSingleStoreElimPass())
237 .RegisterPass(CreateBlockMergePass())
238 .RegisterPass(CreateLocalMultiStoreElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800239 .RegisterPass(CreateRedundancyEliminationPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000240 .RegisterPass(CreateSimplificationPass())
241 .RegisterPass(CreateAggressiveDCEPass())
242 .RegisterPass(CreateCFGCleanupPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800243}
244
Chris Forbescc5697f2019-01-30 11:54:08 -0800245bool Optimizer::RegisterPassesFromFlags(const std::vector<std::string>& flags) {
246 for (const auto& flag : flags) {
247 if (!RegisterPassFromFlag(flag)) {
248 return false;
249 }
250 }
251
252 return true;
253}
254
255bool Optimizer::FlagHasValidForm(const std::string& flag) const {
256 if (flag == "-O" || flag == "-Os") {
257 return true;
258 } else if (flag.size() > 2 && flag.substr(0, 2) == "--") {
259 return true;
260 }
261
262 Errorf(consumer(), nullptr, {},
263 "%s is not a valid flag. Flag passes should have the form "
264 "'--pass_name[=pass_args]'. Special flag names also accepted: -O "
265 "and -Os.",
266 flag.c_str());
267 return false;
268}
269
270bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
271 if (!FlagHasValidForm(flag)) {
272 return false;
273 }
274
275 // Split flags of the form --pass_name=pass_args.
276 auto p = utils::SplitFlagArgs(flag);
277 std::string pass_name = p.first;
278 std::string pass_args = p.second;
279
280 // FIXME(dnovillo): This should be re-factored so that pass names can be
281 // automatically checked against Pass::name() and PassToken instances created
282 // via a template function. Additionally, class Pass should have a desc()
283 // method that describes the pass (so it can be used in --help).
284 //
285 // Both Pass::name() and Pass::desc() should be static class members so they
286 // can be invoked without creating a pass instance.
Ben Clayton745997b2021-01-21 22:51:51 +0000287 if (pass_name == "strip-debug") {
Chris Forbescc5697f2019-01-30 11:54:08 -0800288 RegisterPass(CreateStripDebugInfoPass());
289 } else if (pass_name == "strip-reflect") {
290 RegisterPass(CreateStripReflectInfoPass());
sugoi1b398bf32022-02-18 10:27:28 -0500291 } else if (pass_name == "strip-nonsemantic") {
292 RegisterPass(CreateStripNonSemanticInfoPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800293 } else if (pass_name == "set-spec-const-default-value") {
294 if (pass_args.size() > 0) {
295 auto spec_ids_vals =
296 opt::SetSpecConstantDefaultValuePass::ParseDefaultValuesString(
297 pass_args.c_str());
298 if (!spec_ids_vals) {
299 Errorf(consumer(), nullptr, {},
300 "Invalid argument for --set-spec-const-default-value: %s",
301 pass_args.c_str());
302 return false;
303 }
304 RegisterPass(
305 CreateSetSpecConstantDefaultValuePass(std::move(*spec_ids_vals)));
306 } else {
307 Errorf(consumer(), nullptr, {},
308 "Invalid spec constant value string '%s'. Expected a string of "
309 "<spec id>:<default value> pairs.",
310 pass_args.c_str());
311 return false;
312 }
313 } else if (pass_name == "if-conversion") {
314 RegisterPass(CreateIfConversionPass());
315 } else if (pass_name == "freeze-spec-const") {
316 RegisterPass(CreateFreezeSpecConstantValuePass());
317 } else if (pass_name == "inline-entry-points-exhaustive") {
318 RegisterPass(CreateInlineExhaustivePass());
319 } else if (pass_name == "inline-entry-points-opaque") {
320 RegisterPass(CreateInlineOpaquePass());
321 } else if (pass_name == "combine-access-chains") {
322 RegisterPass(CreateCombineAccessChainsPass());
323 } else if (pass_name == "convert-local-access-chains") {
324 RegisterPass(CreateLocalAccessChainConvertPass());
Alexis Hetu00e0af12021-11-08 08:57:46 -0500325 } else if (pass_name == "replace-desc-array-access-using-var-index") {
326 RegisterPass(CreateReplaceDescArrayAccessUsingVarIndexPass());
sugoi1b398bf32022-02-18 10:27:28 -0500327 } else if (pass_name == "spread-volatile-semantics") {
328 RegisterPass(CreateSpreadVolatileSemanticsPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100329 } else if (pass_name == "descriptor-scalar-replacement") {
330 RegisterPass(CreateDescriptorScalarReplacementPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800331 } else if (pass_name == "eliminate-dead-code-aggressive") {
332 RegisterPass(CreateAggressiveDCEPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800333 } else if (pass_name == "eliminate-insert-extract") {
334 RegisterPass(CreateInsertExtractElimPass());
335 } else if (pass_name == "eliminate-local-single-block") {
336 RegisterPass(CreateLocalSingleBlockLoadStoreElimPass());
337 } else if (pass_name == "eliminate-local-single-store") {
338 RegisterPass(CreateLocalSingleStoreElimPass());
339 } else if (pass_name == "merge-blocks") {
340 RegisterPass(CreateBlockMergePass());
341 } else if (pass_name == "merge-return") {
342 RegisterPass(CreateMergeReturnPass());
343 } else if (pass_name == "eliminate-dead-branches") {
344 RegisterPass(CreateDeadBranchElimPass());
345 } else if (pass_name == "eliminate-dead-functions") {
346 RegisterPass(CreateEliminateDeadFunctionsPass());
347 } else if (pass_name == "eliminate-local-multi-store") {
348 RegisterPass(CreateLocalMultiStoreElimPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800349 } else if (pass_name == "eliminate-dead-const") {
350 RegisterPass(CreateEliminateDeadConstantPass());
351 } else if (pass_name == "eliminate-dead-inserts") {
352 RegisterPass(CreateDeadInsertElimPass());
353 } else if (pass_name == "eliminate-dead-variables") {
354 RegisterPass(CreateDeadVariableEliminationPass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100355 } else if (pass_name == "eliminate-dead-members") {
356 RegisterPass(CreateEliminateDeadMembersPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800357 } else if (pass_name == "fold-spec-const-op-composite") {
358 RegisterPass(CreateFoldSpecConstantOpAndCompositePass());
359 } else if (pass_name == "loop-unswitch") {
360 RegisterPass(CreateLoopUnswitchPass());
361 } else if (pass_name == "scalar-replacement") {
362 if (pass_args.size() == 0) {
363 RegisterPass(CreateScalarReplacementPass());
364 } else {
365 int limit = -1;
366 if (pass_args.find_first_not_of("0123456789") == std::string::npos) {
367 limit = atoi(pass_args.c_str());
368 }
369
370 if (limit >= 0) {
371 RegisterPass(CreateScalarReplacementPass(limit));
372 } else {
373 Error(consumer(), nullptr, {},
374 "--scalar-replacement must have no arguments or a non-negative "
375 "integer argument");
376 return false;
377 }
378 }
379 } else if (pass_name == "strength-reduction") {
380 RegisterPass(CreateStrengthReductionPass());
381 } else if (pass_name == "unify-const") {
382 RegisterPass(CreateUnifyConstantPass());
383 } else if (pass_name == "flatten-decorations") {
384 RegisterPass(CreateFlattenDecorationPass());
385 } else if (pass_name == "compact-ids") {
386 RegisterPass(CreateCompactIdsPass());
387 } else if (pass_name == "cfg-cleanup") {
388 RegisterPass(CreateCFGCleanupPass());
389 } else if (pass_name == "local-redundancy-elimination") {
390 RegisterPass(CreateLocalRedundancyEliminationPass());
391 } else if (pass_name == "loop-invariant-code-motion") {
392 RegisterPass(CreateLoopInvariantCodeMotionPass());
393 } else if (pass_name == "reduce-load-size") {
Alexis Hetu00e0af12021-11-08 08:57:46 -0500394 if (pass_args.size() == 0) {
395 RegisterPass(CreateReduceLoadSizePass());
396 } else {
397 double load_replacement_threshold = 0.9;
398 if (pass_args.find_first_not_of(".0123456789") == std::string::npos) {
399 load_replacement_threshold = atof(pass_args.c_str());
400 }
401
402 if (load_replacement_threshold >= 0) {
403 RegisterPass(CreateReduceLoadSizePass(load_replacement_threshold));
404 } else {
405 Error(consumer(), nullptr, {},
406 "--reduce-load-size must have no arguments or a non-negative "
407 "double argument");
408 return false;
409 }
410 }
Chris Forbescc5697f2019-01-30 11:54:08 -0800411 } else if (pass_name == "redundancy-elimination") {
412 RegisterPass(CreateRedundancyEliminationPass());
413 } else if (pass_name == "private-to-local") {
414 RegisterPass(CreatePrivateToLocalPass());
415 } else if (pass_name == "remove-duplicates") {
416 RegisterPass(CreateRemoveDuplicatesPass());
417 } else if (pass_name == "workaround-1209") {
418 RegisterPass(CreateWorkaround1209Pass());
419 } else if (pass_name == "replace-invalid-opcode") {
420 RegisterPass(CreateReplaceInvalidOpcodePass());
421 } else if (pass_name == "inst-bindless-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100422 RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false));
Chris Forbescc5697f2019-01-30 11:54:08 -0800423 RegisterPass(CreateSimplificationPass());
424 RegisterPass(CreateDeadBranchElimPass());
425 RegisterPass(CreateBlockMergePass());
Alexis Hetu00e0af12021-11-08 08:57:46 -0500426 RegisterPass(CreateAggressiveDCEPass(true));
Ben Claytond0f684e2019-08-30 22:36:08 +0100427 } else if (pass_name == "inst-desc-idx-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100428 RegisterPass(CreateInstBindlessCheckPass(7, 23, true, true));
Ben Claytond0f684e2019-08-30 22:36:08 +0100429 RegisterPass(CreateSimplificationPass());
430 RegisterPass(CreateDeadBranchElimPass());
431 RegisterPass(CreateBlockMergePass());
Alexis Hetu00e0af12021-11-08 08:57:46 -0500432 RegisterPass(CreateAggressiveDCEPass(true));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400433 } else if (pass_name == "inst-buff-oob-check") {
Ben Clayton745997b2021-01-21 22:51:51 +0000434 RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false, true, true));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400435 RegisterPass(CreateSimplificationPass());
436 RegisterPass(CreateDeadBranchElimPass());
437 RegisterPass(CreateBlockMergePass());
Alexis Hetu00e0af12021-11-08 08:57:46 -0500438 RegisterPass(CreateAggressiveDCEPass(true));
Ben Claytond0f684e2019-08-30 22:36:08 +0100439 } else if (pass_name == "inst-buff-addr-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100440 RegisterPass(CreateInstBuffAddrCheckPass(7, 23));
Alexis Hetu00e0af12021-11-08 08:57:46 -0500441 RegisterPass(CreateAggressiveDCEPass(true));
Ben Claytond552f632019-11-18 11:18:41 +0000442 } else if (pass_name == "convert-relaxed-to-half") {
443 RegisterPass(CreateConvertRelaxedToHalfPass());
444 } else if (pass_name == "relax-float-ops") {
445 RegisterPass(CreateRelaxFloatOpsPass());
Alexis Hetub8a77462020-03-27 07:59:09 -0400446 } else if (pass_name == "inst-debug-printf") {
447 RegisterPass(CreateInstDebugPrintfPass(7, 23));
Chris Forbescc5697f2019-01-30 11:54:08 -0800448 } else if (pass_name == "simplify-instructions") {
449 RegisterPass(CreateSimplificationPass());
450 } else if (pass_name == "ssa-rewrite") {
451 RegisterPass(CreateSSARewritePass());
452 } else if (pass_name == "copy-propagate-arrays") {
453 RegisterPass(CreateCopyPropagateArraysPass());
454 } else if (pass_name == "loop-fission") {
455 int register_threshold_to_split =
456 (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
457 if (register_threshold_to_split > 0) {
458 RegisterPass(CreateLoopFissionPass(
459 static_cast<size_t>(register_threshold_to_split)));
460 } else {
461 Error(consumer(), nullptr, {},
462 "--loop-fission must have a positive integer argument");
463 return false;
464 }
465 } else if (pass_name == "loop-fusion") {
466 int max_registers_per_loop =
467 (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
468 if (max_registers_per_loop > 0) {
469 RegisterPass(
470 CreateLoopFusionPass(static_cast<size_t>(max_registers_per_loop)));
471 } else {
472 Error(consumer(), nullptr, {},
473 "--loop-fusion must have a positive integer argument");
474 return false;
475 }
476 } else if (pass_name == "loop-unroll") {
477 RegisterPass(CreateLoopUnrollPass(true));
478 } else if (pass_name == "upgrade-memory-model") {
479 RegisterPass(CreateUpgradeMemoryModelPass());
480 } else if (pass_name == "vector-dce") {
481 RegisterPass(CreateVectorDCEPass());
482 } else if (pass_name == "loop-unroll-partial") {
483 int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
484 if (factor > 0) {
485 RegisterPass(CreateLoopUnrollPass(false, factor));
486 } else {
487 Error(consumer(), nullptr, {},
488 "--loop-unroll-partial must have a positive integer argument");
489 return false;
490 }
491 } else if (pass_name == "loop-peeling") {
492 RegisterPass(CreateLoopPeelingPass());
493 } else if (pass_name == "loop-peeling-threshold") {
494 int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
495 if (factor > 0) {
496 opt::LoopPeelingPass::SetLoopPeelingThreshold(factor);
497 } else {
498 Error(consumer(), nullptr, {},
499 "--loop-peeling-threshold must have a positive integer argument");
500 return false;
501 }
502 } else if (pass_name == "ccp") {
503 RegisterPass(CreateCCPPass());
504 } else if (pass_name == "code-sink") {
505 RegisterPass(CreateCodeSinkingPass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100506 } else if (pass_name == "fix-storage-class") {
507 RegisterPass(CreateFixStorageClassPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800508 } else if (pass_name == "O") {
509 RegisterPerformancePasses();
510 } else if (pass_name == "Os") {
511 RegisterSizePasses();
512 } else if (pass_name == "legalize-hlsl") {
513 RegisterLegalizationPasses();
Alexis Hetu00e0af12021-11-08 08:57:46 -0500514 } else if (pass_name == "remove-unused-interface-variables") {
515 RegisterPass(CreateRemoveUnusedInterfaceVariablesPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100516 } else if (pass_name == "graphics-robust-access") {
517 RegisterPass(CreateGraphicsRobustAccessPass());
518 } else if (pass_name == "wrap-opkill") {
519 RegisterPass(CreateWrapOpKillPass());
520 } else if (pass_name == "amd-ext-to-khr") {
521 RegisterPass(CreateAmdExtToKhrPass());
Alexis Hetu00e0af12021-11-08 08:57:46 -0500522 } else if (pass_name == "interpolate-fixup") {
523 RegisterPass(CreateInterpolateFixupPass());
Nicolas Capens9cbc5e22022-03-08 13:03:25 -0500524 } else if (pass_name == "remove-dont-inline") {
525 RegisterPass(CreateRemoveDontInlinePass());
Nicolas Capens4111ae92022-03-23 12:23:11 -0400526 } else if (pass_name == "eliminate-dead-input-components") {
527 RegisterPass(CreateEliminateDeadInputComponentsPass());
Nicolas Capens9d252072022-05-26 17:20:50 -0400528 } else if (pass_name == "fix-func-call-param") {
529 RegisterPass(CreateFixFuncCallArgumentsPass());
Alexis Hetu00e0af12021-11-08 08:57:46 -0500530 } else if (pass_name == "convert-to-sampled-image") {
531 if (pass_args.size() > 0) {
532 auto descriptor_set_binding_pairs =
533 opt::ConvertToSampledImagePass::ParseDescriptorSetBindingPairsString(
534 pass_args.c_str());
535 if (!descriptor_set_binding_pairs) {
536 Errorf(consumer(), nullptr, {},
537 "Invalid argument for --convert-to-sampled-image: %s",
538 pass_args.c_str());
539 return false;
540 }
541 RegisterPass(CreateConvertToSampledImagePass(
542 std::move(*descriptor_set_binding_pairs)));
543 } else {
544 Errorf(consumer(), nullptr, {},
545 "Invalid pairs of descriptor set and binding '%s'. Expected a "
546 "string of <descriptor set>:<binding> pairs.",
547 pass_args.c_str());
548 return false;
549 }
Chris Forbescc5697f2019-01-30 11:54:08 -0800550 } else {
551 Errorf(consumer(), nullptr, {},
552 "Unknown flag '--%s'. Use --help for a list of valid flags",
553 pass_name.c_str());
554 return false;
555 }
556
557 return true;
558}
559
560void Optimizer::SetTargetEnv(const spv_target_env env) {
561 impl_->target_env = env;
562}
563
564bool Optimizer::Run(const uint32_t* original_binary,
565 const size_t original_binary_size,
566 std::vector<uint32_t>* optimized_binary) const {
567 return Run(original_binary, original_binary_size, optimized_binary,
568 OptimizerOptions());
569}
570
571bool Optimizer::Run(const uint32_t* original_binary,
572 const size_t original_binary_size,
573 std::vector<uint32_t>* optimized_binary,
574 const ValidatorOptions& validator_options,
575 bool skip_validation) const {
576 OptimizerOptions opt_options;
577 opt_options.set_run_validator(!skip_validation);
578 opt_options.set_validator_options(validator_options);
579 return Run(original_binary, original_binary_size, optimized_binary,
580 opt_options);
581}
582
583bool Optimizer::Run(const uint32_t* original_binary,
584 const size_t original_binary_size,
585 std::vector<uint32_t>* optimized_binary,
586 const spv_optimizer_options opt_options) const {
587 spvtools::SpirvTools tools(impl_->target_env);
588 tools.SetMessageConsumer(impl_->pass_manager.consumer());
589 if (opt_options->run_validator_ &&
590 !tools.Validate(original_binary, original_binary_size,
591 &opt_options->val_options_)) {
592 return false;
593 }
594
595 std::unique_ptr<opt::IRContext> context = BuildModule(
596 impl_->target_env, consumer(), original_binary, original_binary_size);
597 if (context == nullptr) return false;
598
599 context->set_max_id_bound(opt_options->max_id_bound_);
Ben Claytonb73b7602019-07-29 13:56:13 +0100600 context->set_preserve_bindings(opt_options->preserve_bindings_);
601 context->set_preserve_spec_constants(opt_options->preserve_spec_constants_);
Chris Forbescc5697f2019-01-30 11:54:08 -0800602
Ben Claytonb73b7602019-07-29 13:56:13 +0100603 impl_->pass_manager.SetValidatorOptions(&opt_options->val_options_);
604 impl_->pass_manager.SetTargetEnv(impl_->target_env);
Chris Forbescc5697f2019-01-30 11:54:08 -0800605 auto status = impl_->pass_manager.Run(context.get());
Ben Claytonb73b7602019-07-29 13:56:13 +0100606
Ben Claytond0f684e2019-08-30 22:36:08 +0100607 if (status == opt::Pass::Status::Failure) {
608 return false;
Ben Claytonb73b7602019-07-29 13:56:13 +0100609 }
610
Ben Claytond0f684e2019-08-30 22:36:08 +0100611#ifndef NDEBUG
Alexis Hetub8a77462020-03-27 07:59:09 -0400612 // We do not keep the result id of DebugScope in struct DebugScope.
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400613 // Instead, we assign random ids for them, which results in integrity
Ben Clayton745997b2021-01-21 22:51:51 +0000614 // check failures. In addition, propagating the OpLine/OpNoLine to preserve
615 // the debug information through transformations results in integrity
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400616 // check failures. We want to skip the integrity check when the module
Ben Clayton745997b2021-01-21 22:51:51 +0000617 // contains DebugScope or OpLine/OpNoLine instructions.
Alexis Hetub8a77462020-03-27 07:59:09 -0400618 if (status == opt::Pass::Status::SuccessWithoutChange &&
Ben Clayton745997b2021-01-21 22:51:51 +0000619 !context->module()->ContainsDebugInfo()) {
Ben Claytond552f632019-11-18 11:18:41 +0000620 std::vector<uint32_t> optimized_binary_with_nop;
621 context->module()->ToBinary(&optimized_binary_with_nop,
622 /* skip_nop = */ false);
623 assert(optimized_binary_with_nop.size() == original_binary_size &&
624 "Binary size unexpectedly changed despite the optimizer saying "
625 "there was no change");
Nicolas Capens00a1bcc2022-07-29 16:49:40 -0400626
627 // Compare the magic number to make sure the binaries were encoded in the
628 // endianness. If not, the contents of the binaries will be different, so
629 // do not check the contents.
630 if (optimized_binary_with_nop[0] == original_binary[0]) {
631 assert(memcmp(optimized_binary_with_nop.data(), original_binary,
632 original_binary_size) == 0 &&
633 "Binary content unexpectedly changed despite the optimizer saying "
634 "there was no change");
635 }
Ben Claytond0f684e2019-08-30 22:36:08 +0100636 }
637#endif // !NDEBUG
638
Ben Claytond552f632019-11-18 11:18:41 +0000639 // Note that |original_binary| and |optimized_binary| may share the same
640 // buffer and the below will invalidate |original_binary|.
641 optimized_binary->clear();
642 context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
643
Ben Claytond0f684e2019-08-30 22:36:08 +0100644 return true;
Chris Forbescc5697f2019-01-30 11:54:08 -0800645}
646
647Optimizer& Optimizer::SetPrintAll(std::ostream* out) {
648 impl_->pass_manager.SetPrintAll(out);
649 return *this;
650}
651
652Optimizer& Optimizer::SetTimeReport(std::ostream* out) {
653 impl_->pass_manager.SetTimeReport(out);
654 return *this;
655}
656
Ben Claytonb73b7602019-07-29 13:56:13 +0100657Optimizer& Optimizer::SetValidateAfterAll(bool validate) {
658 impl_->pass_manager.SetValidateAfterAll(validate);
659 return *this;
660}
661
Chris Forbescc5697f2019-01-30 11:54:08 -0800662Optimizer::PassToken CreateNullPass() {
663 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
664}
665
666Optimizer::PassToken CreateStripDebugInfoPass() {
667 return MakeUnique<Optimizer::PassToken::Impl>(
668 MakeUnique<opt::StripDebugInfoPass>());
669}
670
671Optimizer::PassToken CreateStripReflectInfoPass() {
sugoi1b398bf32022-02-18 10:27:28 -0500672 return CreateStripNonSemanticInfoPass();
673}
674
675Optimizer::PassToken CreateStripNonSemanticInfoPass() {
Chris Forbescc5697f2019-01-30 11:54:08 -0800676 return MakeUnique<Optimizer::PassToken::Impl>(
sugoi1b398bf32022-02-18 10:27:28 -0500677 MakeUnique<opt::StripNonSemanticInfoPass>());
Chris Forbescc5697f2019-01-30 11:54:08 -0800678}
679
680Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
681 return MakeUnique<Optimizer::PassToken::Impl>(
682 MakeUnique<opt::EliminateDeadFunctionsPass>());
683}
684
Ben Claytonb73b7602019-07-29 13:56:13 +0100685Optimizer::PassToken CreateEliminateDeadMembersPass() {
686 return MakeUnique<Optimizer::PassToken::Impl>(
687 MakeUnique<opt::EliminateDeadMembersPass>());
688}
689
Chris Forbescc5697f2019-01-30 11:54:08 -0800690Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
691 const std::unordered_map<uint32_t, std::string>& id_value_map) {
692 return MakeUnique<Optimizer::PassToken::Impl>(
693 MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
694}
695
696Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
697 const std::unordered_map<uint32_t, std::vector<uint32_t>>& id_value_map) {
698 return MakeUnique<Optimizer::PassToken::Impl>(
699 MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
700}
701
702Optimizer::PassToken CreateFlattenDecorationPass() {
703 return MakeUnique<Optimizer::PassToken::Impl>(
704 MakeUnique<opt::FlattenDecorationPass>());
705}
706
707Optimizer::PassToken CreateFreezeSpecConstantValuePass() {
708 return MakeUnique<Optimizer::PassToken::Impl>(
709 MakeUnique<opt::FreezeSpecConstantValuePass>());
710}
711
712Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass() {
713 return MakeUnique<Optimizer::PassToken::Impl>(
714 MakeUnique<opt::FoldSpecConstantOpAndCompositePass>());
715}
716
717Optimizer::PassToken CreateUnifyConstantPass() {
718 return MakeUnique<Optimizer::PassToken::Impl>(
719 MakeUnique<opt::UnifyConstantPass>());
720}
721
722Optimizer::PassToken CreateEliminateDeadConstantPass() {
723 return MakeUnique<Optimizer::PassToken::Impl>(
724 MakeUnique<opt::EliminateDeadConstantPass>());
725}
726
727Optimizer::PassToken CreateDeadVariableEliminationPass() {
728 return MakeUnique<Optimizer::PassToken::Impl>(
729 MakeUnique<opt::DeadVariableElimination>());
730}
731
732Optimizer::PassToken CreateStrengthReductionPass() {
733 return MakeUnique<Optimizer::PassToken::Impl>(
734 MakeUnique<opt::StrengthReductionPass>());
735}
736
737Optimizer::PassToken CreateBlockMergePass() {
738 return MakeUnique<Optimizer::PassToken::Impl>(
739 MakeUnique<opt::BlockMergePass>());
740}
741
742Optimizer::PassToken CreateInlineExhaustivePass() {
743 return MakeUnique<Optimizer::PassToken::Impl>(
744 MakeUnique<opt::InlineExhaustivePass>());
745}
746
747Optimizer::PassToken CreateInlineOpaquePass() {
748 return MakeUnique<Optimizer::PassToken::Impl>(
749 MakeUnique<opt::InlineOpaquePass>());
750}
751
752Optimizer::PassToken CreateLocalAccessChainConvertPass() {
753 return MakeUnique<Optimizer::PassToken::Impl>(
754 MakeUnique<opt::LocalAccessChainConvertPass>());
755}
756
757Optimizer::PassToken CreateLocalSingleBlockLoadStoreElimPass() {
758 return MakeUnique<Optimizer::PassToken::Impl>(
759 MakeUnique<opt::LocalSingleBlockLoadStoreElimPass>());
760}
761
762Optimizer::PassToken CreateLocalSingleStoreElimPass() {
763 return MakeUnique<Optimizer::PassToken::Impl>(
764 MakeUnique<opt::LocalSingleStoreElimPass>());
765}
766
767Optimizer::PassToken CreateInsertExtractElimPass() {
768 return MakeUnique<Optimizer::PassToken::Impl>(
769 MakeUnique<opt::SimplificationPass>());
770}
771
772Optimizer::PassToken CreateDeadInsertElimPass() {
773 return MakeUnique<Optimizer::PassToken::Impl>(
774 MakeUnique<opt::DeadInsertElimPass>());
775}
776
777Optimizer::PassToken CreateDeadBranchElimPass() {
778 return MakeUnique<Optimizer::PassToken::Impl>(
779 MakeUnique<opt::DeadBranchElimPass>());
780}
781
782Optimizer::PassToken CreateLocalMultiStoreElimPass() {
783 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Claytond552f632019-11-18 11:18:41 +0000784 MakeUnique<opt::SSARewritePass>());
Chris Forbescc5697f2019-01-30 11:54:08 -0800785}
786
sugoi1b398bf32022-02-18 10:27:28 -0500787Optimizer::PassToken CreateAggressiveDCEPass() {
788 return MakeUnique<Optimizer::PassToken::Impl>(
789 MakeUnique<opt::AggressiveDCEPass>(false));
790}
791
Alexis Hetu00e0af12021-11-08 08:57:46 -0500792Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface) {
Chris Forbescc5697f2019-01-30 11:54:08 -0800793 return MakeUnique<Optimizer::PassToken::Impl>(
Alexis Hetu00e0af12021-11-08 08:57:46 -0500794 MakeUnique<opt::AggressiveDCEPass>(preserve_interface));
795}
796
797Optimizer::PassToken CreateRemoveUnusedInterfaceVariablesPass() {
798 return MakeUnique<Optimizer::PassToken::Impl>(
799 MakeUnique<opt::RemoveUnusedInterfaceVariablesPass>());
Chris Forbescc5697f2019-01-30 11:54:08 -0800800}
801
Alexis Hetu7975f152020-11-02 11:08:33 -0500802Optimizer::PassToken CreatePropagateLineInfoPass() {
803 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
804}
805
806Optimizer::PassToken CreateRedundantLineInfoElimPass() {
807 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
808}
809
Chris Forbescc5697f2019-01-30 11:54:08 -0800810Optimizer::PassToken CreateCompactIdsPass() {
811 return MakeUnique<Optimizer::PassToken::Impl>(
812 MakeUnique<opt::CompactIdsPass>());
813}
814
815Optimizer::PassToken CreateMergeReturnPass() {
816 return MakeUnique<Optimizer::PassToken::Impl>(
817 MakeUnique<opt::MergeReturnPass>());
818}
819
820std::vector<const char*> Optimizer::GetPassNames() const {
821 std::vector<const char*> v;
822 for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); i++) {
823 v.push_back(impl_->pass_manager.GetPass(i)->name());
824 }
825 return v;
826}
827
828Optimizer::PassToken CreateCFGCleanupPass() {
829 return MakeUnique<Optimizer::PassToken::Impl>(
830 MakeUnique<opt::CFGCleanupPass>());
831}
832
833Optimizer::PassToken CreateLocalRedundancyEliminationPass() {
834 return MakeUnique<Optimizer::PassToken::Impl>(
835 MakeUnique<opt::LocalRedundancyEliminationPass>());
836}
837
838Optimizer::PassToken CreateLoopFissionPass(size_t threshold) {
839 return MakeUnique<Optimizer::PassToken::Impl>(
840 MakeUnique<opt::LoopFissionPass>(threshold));
841}
842
843Optimizer::PassToken CreateLoopFusionPass(size_t max_registers_per_loop) {
844 return MakeUnique<Optimizer::PassToken::Impl>(
845 MakeUnique<opt::LoopFusionPass>(max_registers_per_loop));
846}
847
848Optimizer::PassToken CreateLoopInvariantCodeMotionPass() {
849 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::LICMPass>());
850}
851
852Optimizer::PassToken CreateLoopPeelingPass() {
853 return MakeUnique<Optimizer::PassToken::Impl>(
854 MakeUnique<opt::LoopPeelingPass>());
855}
856
857Optimizer::PassToken CreateLoopUnswitchPass() {
858 return MakeUnique<Optimizer::PassToken::Impl>(
859 MakeUnique<opt::LoopUnswitchPass>());
860}
861
862Optimizer::PassToken CreateRedundancyEliminationPass() {
863 return MakeUnique<Optimizer::PassToken::Impl>(
864 MakeUnique<opt::RedundancyEliminationPass>());
865}
866
867Optimizer::PassToken CreateRemoveDuplicatesPass() {
868 return MakeUnique<Optimizer::PassToken::Impl>(
869 MakeUnique<opt::RemoveDuplicatesPass>());
870}
871
872Optimizer::PassToken CreateScalarReplacementPass(uint32_t size_limit) {
873 return MakeUnique<Optimizer::PassToken::Impl>(
874 MakeUnique<opt::ScalarReplacementPass>(size_limit));
875}
876
877Optimizer::PassToken CreatePrivateToLocalPass() {
878 return MakeUnique<Optimizer::PassToken::Impl>(
879 MakeUnique<opt::PrivateToLocalPass>());
880}
881
882Optimizer::PassToken CreateCCPPass() {
883 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::CCPPass>());
884}
885
886Optimizer::PassToken CreateWorkaround1209Pass() {
887 return MakeUnique<Optimizer::PassToken::Impl>(
888 MakeUnique<opt::Workaround1209>());
889}
890
891Optimizer::PassToken CreateIfConversionPass() {
892 return MakeUnique<Optimizer::PassToken::Impl>(
893 MakeUnique<opt::IfConversion>());
894}
895
896Optimizer::PassToken CreateReplaceInvalidOpcodePass() {
897 return MakeUnique<Optimizer::PassToken::Impl>(
898 MakeUnique<opt::ReplaceInvalidOpcodePass>());
899}
900
901Optimizer::PassToken CreateSimplificationPass() {
902 return MakeUnique<Optimizer::PassToken::Impl>(
903 MakeUnique<opt::SimplificationPass>());
904}
905
906Optimizer::PassToken CreateLoopUnrollPass(bool fully_unroll, int factor) {
907 return MakeUnique<Optimizer::PassToken::Impl>(
908 MakeUnique<opt::LoopUnroller>(fully_unroll, factor));
909}
910
911Optimizer::PassToken CreateSSARewritePass() {
912 return MakeUnique<Optimizer::PassToken::Impl>(
913 MakeUnique<opt::SSARewritePass>());
914}
915
916Optimizer::PassToken CreateCopyPropagateArraysPass() {
917 return MakeUnique<Optimizer::PassToken::Impl>(
918 MakeUnique<opt::CopyPropagateArrays>());
919}
920
921Optimizer::PassToken CreateVectorDCEPass() {
922 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::VectorDCE>());
923}
924
Alexis Hetu00e0af12021-11-08 08:57:46 -0500925Optimizer::PassToken CreateReduceLoadSizePass(
926 double load_replacement_threshold) {
Chris Forbescc5697f2019-01-30 11:54:08 -0800927 return MakeUnique<Optimizer::PassToken::Impl>(
Alexis Hetu00e0af12021-11-08 08:57:46 -0500928 MakeUnique<opt::ReduceLoadSize>(load_replacement_threshold));
Chris Forbescc5697f2019-01-30 11:54:08 -0800929}
930
931Optimizer::PassToken CreateCombineAccessChainsPass() {
932 return MakeUnique<Optimizer::PassToken::Impl>(
933 MakeUnique<opt::CombineAccessChains>());
934}
935
936Optimizer::PassToken CreateUpgradeMemoryModelPass() {
937 return MakeUnique<Optimizer::PassToken::Impl>(
938 MakeUnique<opt::UpgradeMemoryModel>());
939}
940
Ben Clayton745997b2021-01-21 22:51:51 +0000941Optimizer::PassToken CreateInstBindlessCheckPass(
942 uint32_t desc_set, uint32_t shader_id, bool desc_length_enable,
943 bool desc_init_enable, bool buff_oob_enable, bool texbuff_oob_enable) {
Chris Forbescc5697f2019-01-30 11:54:08 -0800944 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Clayton38e46912020-05-26 15:56:15 +0100945 MakeUnique<opt::InstBindlessCheckPass>(
Ben Clayton745997b2021-01-21 22:51:51 +0000946 desc_set, shader_id, desc_length_enable, desc_init_enable,
947 buff_oob_enable, texbuff_oob_enable,
948 desc_length_enable || desc_init_enable || buff_oob_enable));
Chris Forbescc5697f2019-01-30 11:54:08 -0800949}
950
Alexis Hetub8a77462020-03-27 07:59:09 -0400951Optimizer::PassToken CreateInstDebugPrintfPass(uint32_t desc_set,
952 uint32_t shader_id) {
953 return MakeUnique<Optimizer::PassToken::Impl>(
954 MakeUnique<opt::InstDebugPrintfPass>(desc_set, shader_id));
955}
956
Ben Claytond0f684e2019-08-30 22:36:08 +0100957Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t desc_set,
Ben Clayton38e46912020-05-26 15:56:15 +0100958 uint32_t shader_id) {
Ben Claytond0f684e2019-08-30 22:36:08 +0100959 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Clayton38e46912020-05-26 15:56:15 +0100960 MakeUnique<opt::InstBuffAddrCheckPass>(desc_set, shader_id));
Ben Claytond0f684e2019-08-30 22:36:08 +0100961}
962
Ben Claytond552f632019-11-18 11:18:41 +0000963Optimizer::PassToken CreateConvertRelaxedToHalfPass() {
964 return MakeUnique<Optimizer::PassToken::Impl>(
965 MakeUnique<opt::ConvertToHalfPass>());
966}
967
968Optimizer::PassToken CreateRelaxFloatOpsPass() {
969 return MakeUnique<Optimizer::PassToken::Impl>(
970 MakeUnique<opt::RelaxFloatOpsPass>());
971}
972
Chris Forbescc5697f2019-01-30 11:54:08 -0800973Optimizer::PassToken CreateCodeSinkingPass() {
974 return MakeUnique<Optimizer::PassToken::Impl>(
975 MakeUnique<opt::CodeSinkingPass>());
976}
977
Ben Claytonb73b7602019-07-29 13:56:13 +0100978Optimizer::PassToken CreateFixStorageClassPass() {
979 return MakeUnique<Optimizer::PassToken::Impl>(
980 MakeUnique<opt::FixStorageClass>());
981}
982
Ben Claytond0f684e2019-08-30 22:36:08 +0100983Optimizer::PassToken CreateGraphicsRobustAccessPass() {
984 return MakeUnique<Optimizer::PassToken::Impl>(
985 MakeUnique<opt::GraphicsRobustAccessPass>());
986}
987
Alexis Hetu00e0af12021-11-08 08:57:46 -0500988Optimizer::PassToken CreateReplaceDescArrayAccessUsingVarIndexPass() {
989 return MakeUnique<Optimizer::PassToken::Impl>(
990 MakeUnique<opt::ReplaceDescArrayAccessUsingVarIndex>());
991}
992
sugoi1b398bf32022-02-18 10:27:28 -0500993Optimizer::PassToken CreateSpreadVolatileSemanticsPass() {
994 return MakeUnique<Optimizer::PassToken::Impl>(
995 MakeUnique<opt::SpreadVolatileSemantics>());
996}
997
Ben Claytond0f684e2019-08-30 22:36:08 +0100998Optimizer::PassToken CreateDescriptorScalarReplacementPass() {
999 return MakeUnique<Optimizer::PassToken::Impl>(
1000 MakeUnique<opt::DescriptorScalarReplacement>());
1001}
1002
1003Optimizer::PassToken CreateWrapOpKillPass() {
1004 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::WrapOpKill>());
1005}
1006
1007Optimizer::PassToken CreateAmdExtToKhrPass() {
1008 return MakeUnique<Optimizer::PassToken::Impl>(
1009 MakeUnique<opt::AmdExtensionToKhrPass>());
1010}
1011
Alexis Hetu00e0af12021-11-08 08:57:46 -05001012Optimizer::PassToken CreateInterpolateFixupPass() {
1013 return MakeUnique<Optimizer::PassToken::Impl>(
1014 MakeUnique<opt::InterpFixupPass>());
1015}
1016
Nicolas Capens4111ae92022-03-23 12:23:11 -04001017Optimizer::PassToken CreateEliminateDeadInputComponentsPass() {
1018 return MakeUnique<Optimizer::PassToken::Impl>(
1019 MakeUnique<opt::EliminateDeadInputComponentsPass>());
1020}
1021
Alexis Hetu00e0af12021-11-08 08:57:46 -05001022Optimizer::PassToken CreateConvertToSampledImagePass(
1023 const std::vector<opt::DescriptorSetAndBinding>&
1024 descriptor_set_binding_pairs) {
1025 return MakeUnique<Optimizer::PassToken::Impl>(
1026 MakeUnique<opt::ConvertToSampledImagePass>(descriptor_set_binding_pairs));
1027}
1028
Nicolas Capens9d252072022-05-26 17:20:50 -04001029Optimizer::PassToken CreateInterfaceVariableScalarReplacementPass() {
1030 return MakeUnique<Optimizer::PassToken::Impl>(
1031 MakeUnique<opt::InterfaceVariableScalarReplacement>());
1032}
1033
Nicolas Capens9cbc5e22022-03-08 13:03:25 -05001034Optimizer::PassToken CreateRemoveDontInlinePass() {
1035 return MakeUnique<Optimizer::PassToken::Impl>(
1036 MakeUnique<opt::RemoveDontInline>());
1037}
Nicolas Capens9d252072022-05-26 17:20:50 -04001038
1039Optimizer::PassToken CreateFixFuncCallArgumentsPass() {
1040 return MakeUnique<Optimizer::PassToken::Impl>(
1041 MakeUnique<opt::FixFuncCallArgumentsPass>());
1042}
Chris Forbescc5697f2019-01-30 11:54:08 -08001043} // namespace spvtools