blob: bc1441114eaa88a1d7bd329733dea10703dc7446 [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
65Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {}
66
67Optimizer::~Optimizer() {}
68
69void Optimizer::SetMessageConsumer(MessageConsumer c) {
70 // All passes' message consumer needs to be updated.
71 for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); ++i) {
72 impl_->pass_manager.GetPass(i)->SetMessageConsumer(c);
73 }
74 impl_->pass_manager.SetMessageConsumer(std::move(c));
75}
76
77const MessageConsumer& Optimizer::consumer() const {
78 return impl_->pass_manager.consumer();
79}
80
81Optimizer& Optimizer::RegisterPass(PassToken&& p) {
82 // Change to use the pass manager's consumer.
83 p.impl_->pass->SetMessageConsumer(consumer());
84 impl_->pass_manager.AddPass(std::move(p.impl_->pass));
85 return *this;
86}
87
88// The legalization passes take a spir-v shader generated by an HLSL front-end
89// and turn it into a valid vulkan spir-v shader. There are two ways in which
90// the code will be invalid at the start:
91//
92// 1) There will be opaque objects, like images, which will be passed around
93// in intermediate objects. Valid spir-v will have to replace the use of
94// the opaque object with an intermediate object that is the result of the
95// load of the global opaque object.
96//
97// 2) There will be variables that contain pointers to structured or uniform
98// buffers. It be legal, the variables must be eliminated, and the
99// references to the structured buffers must use the result of OpVariable
100// in the Uniform storage class.
101//
102// Optimization in this list must accept shaders with these relaxation of the
103// rules. There is not guarantee that this list of optimizations is able to
104// legalize all inputs, but it is on a best effort basis.
105//
106// The legalization problem is essentially a very general copy propagation
107// problem. The optimization we use are all used to either do copy propagation
108// or enable more copy propagation.
109Optimizer& Optimizer::RegisterLegalizationPasses() {
110 return
Ben Claytond0f684e2019-08-30 22:36:08 +0100111 // Wrap OpKill instructions so all other code can be inlined.
112 RegisterPass(CreateWrapOpKillPass())
113 // Remove unreachable block so that merge return works.
114 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800115 // Merge the returns so we can inline.
116 .RegisterPass(CreateMergeReturnPass())
117 // Make sure uses and definitions are in the same function.
118 .RegisterPass(CreateInlineExhaustivePass())
119 // Make private variable function scope
120 .RegisterPass(CreateEliminateDeadFunctionsPass())
121 .RegisterPass(CreatePrivateToLocalPass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100122 // Fix up the storage classes that DXC may have purposely generated
123 // incorrectly. All functions are inlined, and a lot of dead code has
124 // been removed.
125 .RegisterPass(CreateFixStorageClassPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800126 // Propagate the value stored to the loads in very simple cases.
127 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
128 .RegisterPass(CreateLocalSingleStoreElimPass())
129 .RegisterPass(CreateAggressiveDCEPass())
130 // Split up aggregates so they are easier to deal with.
131 .RegisterPass(CreateScalarReplacementPass(0))
132 // Remove loads and stores so everything is in intermediate values.
133 // Takes care of copy propagation of non-members.
134 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
135 .RegisterPass(CreateLocalSingleStoreElimPass())
136 .RegisterPass(CreateAggressiveDCEPass())
137 .RegisterPass(CreateLocalMultiStoreElimPass())
138 .RegisterPass(CreateAggressiveDCEPass())
139 // Propagate constants to get as many constant conditions on branches
140 // as possible.
141 .RegisterPass(CreateCCPPass())
142 .RegisterPass(CreateLoopUnrollPass(true))
143 .RegisterPass(CreateDeadBranchElimPass())
144 // Copy propagate members. Cleans up code sequences generated by
145 // scalar replacement. Also important for removing OpPhi nodes.
146 .RegisterPass(CreateSimplificationPass())
147 .RegisterPass(CreateAggressiveDCEPass())
148 .RegisterPass(CreateCopyPropagateArraysPass())
149 // May need loop unrolling here see
150 // https://github.com/Microsoft/DirectXShaderCompiler/pull/930
151 // Get rid of unused code that contain traces of illegal code
152 // or unused references to unbound external objects
153 .RegisterPass(CreateVectorDCEPass())
154 .RegisterPass(CreateDeadInsertElimPass())
155 .RegisterPass(CreateReduceLoadSizePass())
156 .RegisterPass(CreateAggressiveDCEPass());
157}
158
159Optimizer& Optimizer::RegisterPerformancePasses() {
Ben Claytond0f684e2019-08-30 22:36:08 +0100160 return RegisterPass(CreateWrapOpKillPass())
161 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800162 .RegisterPass(CreateMergeReturnPass())
163 .RegisterPass(CreateInlineExhaustivePass())
164 .RegisterPass(CreateAggressiveDCEPass())
165 .RegisterPass(CreatePrivateToLocalPass())
166 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
167 .RegisterPass(CreateLocalSingleStoreElimPass())
168 .RegisterPass(CreateAggressiveDCEPass())
169 .RegisterPass(CreateScalarReplacementPass())
170 .RegisterPass(CreateLocalAccessChainConvertPass())
171 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
172 .RegisterPass(CreateLocalSingleStoreElimPass())
173 .RegisterPass(CreateAggressiveDCEPass())
174 .RegisterPass(CreateLocalMultiStoreElimPass())
175 .RegisterPass(CreateAggressiveDCEPass())
176 .RegisterPass(CreateCCPPass())
177 .RegisterPass(CreateAggressiveDCEPass())
Ben Clayton38e46912020-05-26 15:56:15 +0100178 .RegisterPass(CreateLoopUnrollPass(true))
179 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800180 .RegisterPass(CreateRedundancyEliminationPass())
181 .RegisterPass(CreateCombineAccessChainsPass())
182 .RegisterPass(CreateSimplificationPass())
Ben Clayton38e46912020-05-26 15:56:15 +0100183 .RegisterPass(CreateScalarReplacementPass())
184 .RegisterPass(CreateLocalAccessChainConvertPass())
185 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
186 .RegisterPass(CreateLocalSingleStoreElimPass())
187 .RegisterPass(CreateAggressiveDCEPass())
188 .RegisterPass(CreateSSARewritePass())
189 .RegisterPass(CreateAggressiveDCEPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800190 .RegisterPass(CreateVectorDCEPass())
191 .RegisterPass(CreateDeadInsertElimPass())
192 .RegisterPass(CreateDeadBranchElimPass())
193 .RegisterPass(CreateSimplificationPass())
194 .RegisterPass(CreateIfConversionPass())
195 .RegisterPass(CreateCopyPropagateArraysPass())
196 .RegisterPass(CreateReduceLoadSizePass())
197 .RegisterPass(CreateAggressiveDCEPass())
198 .RegisterPass(CreateBlockMergePass())
199 .RegisterPass(CreateRedundancyEliminationPass())
200 .RegisterPass(CreateDeadBranchElimPass())
201 .RegisterPass(CreateBlockMergePass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100202 .RegisterPass(CreateSimplificationPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800203}
204
205Optimizer& Optimizer::RegisterSizePasses() {
Ben Claytond0f684e2019-08-30 22:36:08 +0100206 return RegisterPass(CreateWrapOpKillPass())
207 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800208 .RegisterPass(CreateMergeReturnPass())
209 .RegisterPass(CreateInlineExhaustivePass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000210 .RegisterPass(CreateEliminateDeadFunctionsPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800211 .RegisterPass(CreatePrivateToLocalPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000212 .RegisterPass(CreateScalarReplacementPass(0))
Chris Forbescc5697f2019-01-30 11:54:08 -0800213 .RegisterPass(CreateLocalMultiStoreElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800214 .RegisterPass(CreateCCPPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000215 .RegisterPass(CreateLoopUnrollPass(true))
216 .RegisterPass(CreateDeadBranchElimPass())
217 .RegisterPass(CreateSimplificationPass())
218 .RegisterPass(CreateScalarReplacementPass(0))
219 .RegisterPass(CreateLocalSingleStoreElimPass())
220 .RegisterPass(CreateIfConversionPass())
221 .RegisterPass(CreateSimplificationPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800222 .RegisterPass(CreateAggressiveDCEPass())
223 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800224 .RegisterPass(CreateBlockMergePass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000225 .RegisterPass(CreateLocalAccessChainConvertPass())
226 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
227 .RegisterPass(CreateAggressiveDCEPass())
228 .RegisterPass(CreateCopyPropagateArraysPass())
229 .RegisterPass(CreateVectorDCEPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800230 .RegisterPass(CreateDeadInsertElimPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000231 .RegisterPass(CreateEliminateDeadMembersPass())
232 .RegisterPass(CreateLocalSingleStoreElimPass())
233 .RegisterPass(CreateBlockMergePass())
234 .RegisterPass(CreateLocalMultiStoreElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800235 .RegisterPass(CreateRedundancyEliminationPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000236 .RegisterPass(CreateSimplificationPass())
237 .RegisterPass(CreateAggressiveDCEPass())
238 .RegisterPass(CreateCFGCleanupPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800239}
240
Ben Claytonb73b7602019-07-29 13:56:13 +0100241Optimizer& Optimizer::RegisterVulkanToWebGPUPasses() {
Ben Clayton0b54f132020-01-06 13:38:54 +0000242 return RegisterPass(CreateStripAtomicCounterMemoryPass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100243 .RegisterPass(CreateGenerateWebGPUInitializersPass())
244 .RegisterPass(CreateLegalizeVectorShufflePass())
245 .RegisterPass(CreateSplitInvalidUnreachablePass())
246 .RegisterPass(CreateEliminateDeadConstantPass())
247 .RegisterPass(CreateFlattenDecorationPass())
248 .RegisterPass(CreateAggressiveDCEPass())
249 .RegisterPass(CreateDeadBranchElimPass())
250 .RegisterPass(CreateCompactIdsPass());
251}
252
253Optimizer& Optimizer::RegisterWebGPUToVulkanPasses() {
254 return RegisterPass(CreateDecomposeInitializedVariablesPass())
255 .RegisterPass(CreateCompactIdsPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800256}
257
258bool Optimizer::RegisterPassesFromFlags(const std::vector<std::string>& flags) {
259 for (const auto& flag : flags) {
260 if (!RegisterPassFromFlag(flag)) {
261 return false;
262 }
263 }
264
265 return true;
266}
267
268bool Optimizer::FlagHasValidForm(const std::string& flag) const {
269 if (flag == "-O" || flag == "-Os") {
270 return true;
271 } else if (flag.size() > 2 && flag.substr(0, 2) == "--") {
272 return true;
273 }
274
275 Errorf(consumer(), nullptr, {},
276 "%s is not a valid flag. Flag passes should have the form "
277 "'--pass_name[=pass_args]'. Special flag names also accepted: -O "
278 "and -Os.",
279 flag.c_str());
280 return false;
281}
282
283bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
284 if (!FlagHasValidForm(flag)) {
285 return false;
286 }
287
288 // Split flags of the form --pass_name=pass_args.
289 auto p = utils::SplitFlagArgs(flag);
290 std::string pass_name = p.first;
291 std::string pass_args = p.second;
292
293 // FIXME(dnovillo): This should be re-factored so that pass names can be
294 // automatically checked against Pass::name() and PassToken instances created
295 // via a template function. Additionally, class Pass should have a desc()
296 // method that describes the pass (so it can be used in --help).
297 //
298 // Both Pass::name() and Pass::desc() should be static class members so they
299 // can be invoked without creating a pass instance.
Ben Claytonb73b7602019-07-29 13:56:13 +0100300 if (pass_name == "strip-atomic-counter-memory") {
301 RegisterPass(CreateStripAtomicCounterMemoryPass());
302 } else if (pass_name == "strip-debug") {
Chris Forbescc5697f2019-01-30 11:54:08 -0800303 RegisterPass(CreateStripDebugInfoPass());
304 } else if (pass_name == "strip-reflect") {
305 RegisterPass(CreateStripReflectInfoPass());
306 } else if (pass_name == "set-spec-const-default-value") {
307 if (pass_args.size() > 0) {
308 auto spec_ids_vals =
309 opt::SetSpecConstantDefaultValuePass::ParseDefaultValuesString(
310 pass_args.c_str());
311 if (!spec_ids_vals) {
312 Errorf(consumer(), nullptr, {},
313 "Invalid argument for --set-spec-const-default-value: %s",
314 pass_args.c_str());
315 return false;
316 }
317 RegisterPass(
318 CreateSetSpecConstantDefaultValuePass(std::move(*spec_ids_vals)));
319 } else {
320 Errorf(consumer(), nullptr, {},
321 "Invalid spec constant value string '%s'. Expected a string of "
322 "<spec id>:<default value> pairs.",
323 pass_args.c_str());
324 return false;
325 }
326 } else if (pass_name == "if-conversion") {
327 RegisterPass(CreateIfConversionPass());
328 } else if (pass_name == "freeze-spec-const") {
329 RegisterPass(CreateFreezeSpecConstantValuePass());
330 } else if (pass_name == "inline-entry-points-exhaustive") {
331 RegisterPass(CreateInlineExhaustivePass());
332 } else if (pass_name == "inline-entry-points-opaque") {
333 RegisterPass(CreateInlineOpaquePass());
334 } else if (pass_name == "combine-access-chains") {
335 RegisterPass(CreateCombineAccessChainsPass());
336 } else if (pass_name == "convert-local-access-chains") {
337 RegisterPass(CreateLocalAccessChainConvertPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100338 } else if (pass_name == "descriptor-scalar-replacement") {
339 RegisterPass(CreateDescriptorScalarReplacementPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800340 } else if (pass_name == "eliminate-dead-code-aggressive") {
341 RegisterPass(CreateAggressiveDCEPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800342 } else if (pass_name == "eliminate-insert-extract") {
343 RegisterPass(CreateInsertExtractElimPass());
344 } else if (pass_name == "eliminate-local-single-block") {
345 RegisterPass(CreateLocalSingleBlockLoadStoreElimPass());
346 } else if (pass_name == "eliminate-local-single-store") {
347 RegisterPass(CreateLocalSingleStoreElimPass());
348 } else if (pass_name == "merge-blocks") {
349 RegisterPass(CreateBlockMergePass());
350 } else if (pass_name == "merge-return") {
351 RegisterPass(CreateMergeReturnPass());
352 } else if (pass_name == "eliminate-dead-branches") {
353 RegisterPass(CreateDeadBranchElimPass());
354 } else if (pass_name == "eliminate-dead-functions") {
355 RegisterPass(CreateEliminateDeadFunctionsPass());
356 } else if (pass_name == "eliminate-local-multi-store") {
357 RegisterPass(CreateLocalMultiStoreElimPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800358 } else if (pass_name == "eliminate-dead-const") {
359 RegisterPass(CreateEliminateDeadConstantPass());
360 } else if (pass_name == "eliminate-dead-inserts") {
361 RegisterPass(CreateDeadInsertElimPass());
362 } else if (pass_name == "eliminate-dead-variables") {
363 RegisterPass(CreateDeadVariableEliminationPass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100364 } else if (pass_name == "eliminate-dead-members") {
365 RegisterPass(CreateEliminateDeadMembersPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800366 } else if (pass_name == "fold-spec-const-op-composite") {
367 RegisterPass(CreateFoldSpecConstantOpAndCompositePass());
368 } else if (pass_name == "loop-unswitch") {
369 RegisterPass(CreateLoopUnswitchPass());
370 } else if (pass_name == "scalar-replacement") {
371 if (pass_args.size() == 0) {
372 RegisterPass(CreateScalarReplacementPass());
373 } else {
374 int limit = -1;
375 if (pass_args.find_first_not_of("0123456789") == std::string::npos) {
376 limit = atoi(pass_args.c_str());
377 }
378
379 if (limit >= 0) {
380 RegisterPass(CreateScalarReplacementPass(limit));
381 } else {
382 Error(consumer(), nullptr, {},
383 "--scalar-replacement must have no arguments or a non-negative "
384 "integer argument");
385 return false;
386 }
387 }
388 } else if (pass_name == "strength-reduction") {
389 RegisterPass(CreateStrengthReductionPass());
390 } else if (pass_name == "unify-const") {
391 RegisterPass(CreateUnifyConstantPass());
392 } else if (pass_name == "flatten-decorations") {
393 RegisterPass(CreateFlattenDecorationPass());
394 } else if (pass_name == "compact-ids") {
395 RegisterPass(CreateCompactIdsPass());
396 } else if (pass_name == "cfg-cleanup") {
397 RegisterPass(CreateCFGCleanupPass());
398 } else if (pass_name == "local-redundancy-elimination") {
399 RegisterPass(CreateLocalRedundancyEliminationPass());
400 } else if (pass_name == "loop-invariant-code-motion") {
401 RegisterPass(CreateLoopInvariantCodeMotionPass());
402 } else if (pass_name == "reduce-load-size") {
403 RegisterPass(CreateReduceLoadSizePass());
404 } else if (pass_name == "redundancy-elimination") {
405 RegisterPass(CreateRedundancyEliminationPass());
406 } else if (pass_name == "private-to-local") {
407 RegisterPass(CreatePrivateToLocalPass());
408 } else if (pass_name == "remove-duplicates") {
409 RegisterPass(CreateRemoveDuplicatesPass());
410 } else if (pass_name == "workaround-1209") {
411 RegisterPass(CreateWorkaround1209Pass());
412 } else if (pass_name == "replace-invalid-opcode") {
413 RegisterPass(CreateReplaceInvalidOpcodePass());
414 } else if (pass_name == "inst-bindless-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100415 RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false));
Chris Forbescc5697f2019-01-30 11:54:08 -0800416 RegisterPass(CreateSimplificationPass());
417 RegisterPass(CreateDeadBranchElimPass());
418 RegisterPass(CreateBlockMergePass());
419 RegisterPass(CreateAggressiveDCEPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100420 } else if (pass_name == "inst-desc-idx-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100421 RegisterPass(CreateInstBindlessCheckPass(7, 23, true, true));
Ben Claytond0f684e2019-08-30 22:36:08 +0100422 RegisterPass(CreateSimplificationPass());
423 RegisterPass(CreateDeadBranchElimPass());
424 RegisterPass(CreateBlockMergePass());
425 RegisterPass(CreateAggressiveDCEPass());
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400426 } else if (pass_name == "inst-buff-oob-check") {
427 RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false, true));
428 RegisterPass(CreateSimplificationPass());
429 RegisterPass(CreateDeadBranchElimPass());
430 RegisterPass(CreateBlockMergePass());
431 RegisterPass(CreateAggressiveDCEPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100432 } else if (pass_name == "inst-buff-addr-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100433 RegisterPass(CreateInstBuffAddrCheckPass(7, 23));
Ben Claytond0f684e2019-08-30 22:36:08 +0100434 RegisterPass(CreateAggressiveDCEPass());
Ben Claytond552f632019-11-18 11:18:41 +0000435 } else if (pass_name == "convert-relaxed-to-half") {
436 RegisterPass(CreateConvertRelaxedToHalfPass());
437 } else if (pass_name == "relax-float-ops") {
438 RegisterPass(CreateRelaxFloatOpsPass());
Alexis Hetub8a77462020-03-27 07:59:09 -0400439 } else if (pass_name == "inst-debug-printf") {
440 RegisterPass(CreateInstDebugPrintfPass(7, 23));
Chris Forbescc5697f2019-01-30 11:54:08 -0800441 } else if (pass_name == "simplify-instructions") {
442 RegisterPass(CreateSimplificationPass());
443 } else if (pass_name == "ssa-rewrite") {
444 RegisterPass(CreateSSARewritePass());
445 } else if (pass_name == "copy-propagate-arrays") {
446 RegisterPass(CreateCopyPropagateArraysPass());
447 } else if (pass_name == "loop-fission") {
448 int register_threshold_to_split =
449 (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
450 if (register_threshold_to_split > 0) {
451 RegisterPass(CreateLoopFissionPass(
452 static_cast<size_t>(register_threshold_to_split)));
453 } else {
454 Error(consumer(), nullptr, {},
455 "--loop-fission must have a positive integer argument");
456 return false;
457 }
458 } else if (pass_name == "loop-fusion") {
459 int max_registers_per_loop =
460 (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
461 if (max_registers_per_loop > 0) {
462 RegisterPass(
463 CreateLoopFusionPass(static_cast<size_t>(max_registers_per_loop)));
464 } else {
465 Error(consumer(), nullptr, {},
466 "--loop-fusion must have a positive integer argument");
467 return false;
468 }
469 } else if (pass_name == "loop-unroll") {
470 RegisterPass(CreateLoopUnrollPass(true));
471 } else if (pass_name == "upgrade-memory-model") {
472 RegisterPass(CreateUpgradeMemoryModelPass());
473 } else if (pass_name == "vector-dce") {
474 RegisterPass(CreateVectorDCEPass());
475 } else if (pass_name == "loop-unroll-partial") {
476 int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
477 if (factor > 0) {
478 RegisterPass(CreateLoopUnrollPass(false, factor));
479 } else {
480 Error(consumer(), nullptr, {},
481 "--loop-unroll-partial must have a positive integer argument");
482 return false;
483 }
484 } else if (pass_name == "loop-peeling") {
485 RegisterPass(CreateLoopPeelingPass());
486 } else if (pass_name == "loop-peeling-threshold") {
487 int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
488 if (factor > 0) {
489 opt::LoopPeelingPass::SetLoopPeelingThreshold(factor);
490 } else {
491 Error(consumer(), nullptr, {},
492 "--loop-peeling-threshold must have a positive integer argument");
493 return false;
494 }
495 } else if (pass_name == "ccp") {
496 RegisterPass(CreateCCPPass());
497 } else if (pass_name == "code-sink") {
498 RegisterPass(CreateCodeSinkingPass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100499 } else if (pass_name == "fix-storage-class") {
500 RegisterPass(CreateFixStorageClassPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800501 } else if (pass_name == "O") {
502 RegisterPerformancePasses();
503 } else if (pass_name == "Os") {
504 RegisterSizePasses();
505 } else if (pass_name == "legalize-hlsl") {
506 RegisterLegalizationPasses();
Ben Claytonb73b7602019-07-29 13:56:13 +0100507 } else if (pass_name == "generate-webgpu-initializers") {
508 RegisterPass(CreateGenerateWebGPUInitializersPass());
509 } else if (pass_name == "legalize-vector-shuffle") {
510 RegisterPass(CreateLegalizeVectorShufflePass());
511 } else if (pass_name == "split-invalid-unreachable") {
Ben Clayton38e46912020-05-26 15:56:15 +0100512 RegisterPass(CreateSplitInvalidUnreachablePass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100513 } else if (pass_name == "decompose-initialized-variables") {
514 RegisterPass(CreateDecomposeInitializedVariablesPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100515 } else if (pass_name == "graphics-robust-access") {
516 RegisterPass(CreateGraphicsRobustAccessPass());
517 } else if (pass_name == "wrap-opkill") {
518 RegisterPass(CreateWrapOpKillPass());
519 } else if (pass_name == "amd-ext-to-khr") {
520 RegisterPass(CreateAmdExtToKhrPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800521 } else {
522 Errorf(consumer(), nullptr, {},
523 "Unknown flag '--%s'. Use --help for a list of valid flags",
524 pass_name.c_str());
525 return false;
526 }
527
528 return true;
529}
530
531void Optimizer::SetTargetEnv(const spv_target_env env) {
532 impl_->target_env = env;
533}
534
535bool Optimizer::Run(const uint32_t* original_binary,
536 const size_t original_binary_size,
537 std::vector<uint32_t>* optimized_binary) const {
538 return Run(original_binary, original_binary_size, optimized_binary,
539 OptimizerOptions());
540}
541
542bool Optimizer::Run(const uint32_t* original_binary,
543 const size_t original_binary_size,
544 std::vector<uint32_t>* optimized_binary,
545 const ValidatorOptions& validator_options,
546 bool skip_validation) const {
547 OptimizerOptions opt_options;
548 opt_options.set_run_validator(!skip_validation);
549 opt_options.set_validator_options(validator_options);
550 return Run(original_binary, original_binary_size, optimized_binary,
551 opt_options);
552}
553
554bool Optimizer::Run(const uint32_t* original_binary,
555 const size_t original_binary_size,
556 std::vector<uint32_t>* optimized_binary,
557 const spv_optimizer_options opt_options) const {
558 spvtools::SpirvTools tools(impl_->target_env);
559 tools.SetMessageConsumer(impl_->pass_manager.consumer());
560 if (opt_options->run_validator_ &&
561 !tools.Validate(original_binary, original_binary_size,
562 &opt_options->val_options_)) {
563 return false;
564 }
565
566 std::unique_ptr<opt::IRContext> context = BuildModule(
567 impl_->target_env, consumer(), original_binary, original_binary_size);
568 if (context == nullptr) return false;
569
570 context->set_max_id_bound(opt_options->max_id_bound_);
Ben Claytonb73b7602019-07-29 13:56:13 +0100571 context->set_preserve_bindings(opt_options->preserve_bindings_);
572 context->set_preserve_spec_constants(opt_options->preserve_spec_constants_);
Chris Forbescc5697f2019-01-30 11:54:08 -0800573
Ben Claytonb73b7602019-07-29 13:56:13 +0100574 impl_->pass_manager.SetValidatorOptions(&opt_options->val_options_);
575 impl_->pass_manager.SetTargetEnv(impl_->target_env);
Chris Forbescc5697f2019-01-30 11:54:08 -0800576 auto status = impl_->pass_manager.Run(context.get());
Ben Claytonb73b7602019-07-29 13:56:13 +0100577
Ben Claytond0f684e2019-08-30 22:36:08 +0100578 if (status == opt::Pass::Status::Failure) {
579 return false;
Ben Claytonb73b7602019-07-29 13:56:13 +0100580 }
581
Ben Claytond0f684e2019-08-30 22:36:08 +0100582#ifndef NDEBUG
Alexis Hetub8a77462020-03-27 07:59:09 -0400583 // We do not keep the result id of DebugScope in struct DebugScope.
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400584 // Instead, we assign random ids for them, which results in integrity
585 // check failures. We want to skip the integrity check when the module
Alexis Hetub8a77462020-03-27 07:59:09 -0400586 // contains DebugScope instructions.
587 if (status == opt::Pass::Status::SuccessWithoutChange &&
588 !context->module()->ContainsDebugScope()) {
Ben Claytond552f632019-11-18 11:18:41 +0000589 std::vector<uint32_t> optimized_binary_with_nop;
590 context->module()->ToBinary(&optimized_binary_with_nop,
591 /* skip_nop = */ false);
592 assert(optimized_binary_with_nop.size() == original_binary_size &&
593 "Binary size unexpectedly changed despite the optimizer saying "
594 "there was no change");
595 assert(memcmp(optimized_binary_with_nop.data(), original_binary,
596 original_binary_size) == 0 &&
597 "Binary content unexpectedly changed despite the optimizer saying "
598 "there was no change");
Ben Claytond0f684e2019-08-30 22:36:08 +0100599 }
600#endif // !NDEBUG
601
Ben Claytond552f632019-11-18 11:18:41 +0000602 // Note that |original_binary| and |optimized_binary| may share the same
603 // buffer and the below will invalidate |original_binary|.
604 optimized_binary->clear();
605 context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
606
Ben Claytond0f684e2019-08-30 22:36:08 +0100607 return true;
Chris Forbescc5697f2019-01-30 11:54:08 -0800608}
609
610Optimizer& Optimizer::SetPrintAll(std::ostream* out) {
611 impl_->pass_manager.SetPrintAll(out);
612 return *this;
613}
614
615Optimizer& Optimizer::SetTimeReport(std::ostream* out) {
616 impl_->pass_manager.SetTimeReport(out);
617 return *this;
618}
619
Ben Claytonb73b7602019-07-29 13:56:13 +0100620Optimizer& Optimizer::SetValidateAfterAll(bool validate) {
621 impl_->pass_manager.SetValidateAfterAll(validate);
622 return *this;
623}
624
Chris Forbescc5697f2019-01-30 11:54:08 -0800625Optimizer::PassToken CreateNullPass() {
626 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
627}
628
Ben Claytonb73b7602019-07-29 13:56:13 +0100629Optimizer::PassToken CreateStripAtomicCounterMemoryPass() {
630 return MakeUnique<Optimizer::PassToken::Impl>(
631 MakeUnique<opt::StripAtomicCounterMemoryPass>());
632}
633
Chris Forbescc5697f2019-01-30 11:54:08 -0800634Optimizer::PassToken CreateStripDebugInfoPass() {
635 return MakeUnique<Optimizer::PassToken::Impl>(
636 MakeUnique<opt::StripDebugInfoPass>());
637}
638
639Optimizer::PassToken CreateStripReflectInfoPass() {
640 return MakeUnique<Optimizer::PassToken::Impl>(
641 MakeUnique<opt::StripReflectInfoPass>());
642}
643
644Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
645 return MakeUnique<Optimizer::PassToken::Impl>(
646 MakeUnique<opt::EliminateDeadFunctionsPass>());
647}
648
Ben Claytonb73b7602019-07-29 13:56:13 +0100649Optimizer::PassToken CreateEliminateDeadMembersPass() {
650 return MakeUnique<Optimizer::PassToken::Impl>(
651 MakeUnique<opt::EliminateDeadMembersPass>());
652}
653
Chris Forbescc5697f2019-01-30 11:54:08 -0800654Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
655 const std::unordered_map<uint32_t, std::string>& id_value_map) {
656 return MakeUnique<Optimizer::PassToken::Impl>(
657 MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
658}
659
660Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
661 const std::unordered_map<uint32_t, std::vector<uint32_t>>& id_value_map) {
662 return MakeUnique<Optimizer::PassToken::Impl>(
663 MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
664}
665
666Optimizer::PassToken CreateFlattenDecorationPass() {
667 return MakeUnique<Optimizer::PassToken::Impl>(
668 MakeUnique<opt::FlattenDecorationPass>());
669}
670
671Optimizer::PassToken CreateFreezeSpecConstantValuePass() {
672 return MakeUnique<Optimizer::PassToken::Impl>(
673 MakeUnique<opt::FreezeSpecConstantValuePass>());
674}
675
676Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass() {
677 return MakeUnique<Optimizer::PassToken::Impl>(
678 MakeUnique<opt::FoldSpecConstantOpAndCompositePass>());
679}
680
681Optimizer::PassToken CreateUnifyConstantPass() {
682 return MakeUnique<Optimizer::PassToken::Impl>(
683 MakeUnique<opt::UnifyConstantPass>());
684}
685
686Optimizer::PassToken CreateEliminateDeadConstantPass() {
687 return MakeUnique<Optimizer::PassToken::Impl>(
688 MakeUnique<opt::EliminateDeadConstantPass>());
689}
690
691Optimizer::PassToken CreateDeadVariableEliminationPass() {
692 return MakeUnique<Optimizer::PassToken::Impl>(
693 MakeUnique<opt::DeadVariableElimination>());
694}
695
696Optimizer::PassToken CreateStrengthReductionPass() {
697 return MakeUnique<Optimizer::PassToken::Impl>(
698 MakeUnique<opt::StrengthReductionPass>());
699}
700
701Optimizer::PassToken CreateBlockMergePass() {
702 return MakeUnique<Optimizer::PassToken::Impl>(
703 MakeUnique<opt::BlockMergePass>());
704}
705
706Optimizer::PassToken CreateInlineExhaustivePass() {
707 return MakeUnique<Optimizer::PassToken::Impl>(
708 MakeUnique<opt::InlineExhaustivePass>());
709}
710
711Optimizer::PassToken CreateInlineOpaquePass() {
712 return MakeUnique<Optimizer::PassToken::Impl>(
713 MakeUnique<opt::InlineOpaquePass>());
714}
715
716Optimizer::PassToken CreateLocalAccessChainConvertPass() {
717 return MakeUnique<Optimizer::PassToken::Impl>(
718 MakeUnique<opt::LocalAccessChainConvertPass>());
719}
720
721Optimizer::PassToken CreateLocalSingleBlockLoadStoreElimPass() {
722 return MakeUnique<Optimizer::PassToken::Impl>(
723 MakeUnique<opt::LocalSingleBlockLoadStoreElimPass>());
724}
725
726Optimizer::PassToken CreateLocalSingleStoreElimPass() {
727 return MakeUnique<Optimizer::PassToken::Impl>(
728 MakeUnique<opt::LocalSingleStoreElimPass>());
729}
730
731Optimizer::PassToken CreateInsertExtractElimPass() {
732 return MakeUnique<Optimizer::PassToken::Impl>(
733 MakeUnique<opt::SimplificationPass>());
734}
735
736Optimizer::PassToken CreateDeadInsertElimPass() {
737 return MakeUnique<Optimizer::PassToken::Impl>(
738 MakeUnique<opt::DeadInsertElimPass>());
739}
740
741Optimizer::PassToken CreateDeadBranchElimPass() {
742 return MakeUnique<Optimizer::PassToken::Impl>(
743 MakeUnique<opt::DeadBranchElimPass>());
744}
745
746Optimizer::PassToken CreateLocalMultiStoreElimPass() {
747 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Claytond552f632019-11-18 11:18:41 +0000748 MakeUnique<opt::SSARewritePass>());
Chris Forbescc5697f2019-01-30 11:54:08 -0800749}
750
751Optimizer::PassToken CreateAggressiveDCEPass() {
752 return MakeUnique<Optimizer::PassToken::Impl>(
753 MakeUnique<opt::AggressiveDCEPass>());
754}
755
Alexis Hetu7975f152020-11-02 11:08:33 -0500756Optimizer::PassToken CreatePropagateLineInfoPass() {
757 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
758}
759
760Optimizer::PassToken CreateRedundantLineInfoElimPass() {
761 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
762}
763
Chris Forbescc5697f2019-01-30 11:54:08 -0800764Optimizer::PassToken CreateCompactIdsPass() {
765 return MakeUnique<Optimizer::PassToken::Impl>(
766 MakeUnique<opt::CompactIdsPass>());
767}
768
769Optimizer::PassToken CreateMergeReturnPass() {
770 return MakeUnique<Optimizer::PassToken::Impl>(
771 MakeUnique<opt::MergeReturnPass>());
772}
773
774std::vector<const char*> Optimizer::GetPassNames() const {
775 std::vector<const char*> v;
776 for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); i++) {
777 v.push_back(impl_->pass_manager.GetPass(i)->name());
778 }
779 return v;
780}
781
782Optimizer::PassToken CreateCFGCleanupPass() {
783 return MakeUnique<Optimizer::PassToken::Impl>(
784 MakeUnique<opt::CFGCleanupPass>());
785}
786
787Optimizer::PassToken CreateLocalRedundancyEliminationPass() {
788 return MakeUnique<Optimizer::PassToken::Impl>(
789 MakeUnique<opt::LocalRedundancyEliminationPass>());
790}
791
792Optimizer::PassToken CreateLoopFissionPass(size_t threshold) {
793 return MakeUnique<Optimizer::PassToken::Impl>(
794 MakeUnique<opt::LoopFissionPass>(threshold));
795}
796
797Optimizer::PassToken CreateLoopFusionPass(size_t max_registers_per_loop) {
798 return MakeUnique<Optimizer::PassToken::Impl>(
799 MakeUnique<opt::LoopFusionPass>(max_registers_per_loop));
800}
801
802Optimizer::PassToken CreateLoopInvariantCodeMotionPass() {
803 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::LICMPass>());
804}
805
806Optimizer::PassToken CreateLoopPeelingPass() {
807 return MakeUnique<Optimizer::PassToken::Impl>(
808 MakeUnique<opt::LoopPeelingPass>());
809}
810
811Optimizer::PassToken CreateLoopUnswitchPass() {
812 return MakeUnique<Optimizer::PassToken::Impl>(
813 MakeUnique<opt::LoopUnswitchPass>());
814}
815
816Optimizer::PassToken CreateRedundancyEliminationPass() {
817 return MakeUnique<Optimizer::PassToken::Impl>(
818 MakeUnique<opt::RedundancyEliminationPass>());
819}
820
821Optimizer::PassToken CreateRemoveDuplicatesPass() {
822 return MakeUnique<Optimizer::PassToken::Impl>(
823 MakeUnique<opt::RemoveDuplicatesPass>());
824}
825
826Optimizer::PassToken CreateScalarReplacementPass(uint32_t size_limit) {
827 return MakeUnique<Optimizer::PassToken::Impl>(
828 MakeUnique<opt::ScalarReplacementPass>(size_limit));
829}
830
831Optimizer::PassToken CreatePrivateToLocalPass() {
832 return MakeUnique<Optimizer::PassToken::Impl>(
833 MakeUnique<opt::PrivateToLocalPass>());
834}
835
836Optimizer::PassToken CreateCCPPass() {
837 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::CCPPass>());
838}
839
840Optimizer::PassToken CreateWorkaround1209Pass() {
841 return MakeUnique<Optimizer::PassToken::Impl>(
842 MakeUnique<opt::Workaround1209>());
843}
844
845Optimizer::PassToken CreateIfConversionPass() {
846 return MakeUnique<Optimizer::PassToken::Impl>(
847 MakeUnique<opt::IfConversion>());
848}
849
850Optimizer::PassToken CreateReplaceInvalidOpcodePass() {
851 return MakeUnique<Optimizer::PassToken::Impl>(
852 MakeUnique<opt::ReplaceInvalidOpcodePass>());
853}
854
855Optimizer::PassToken CreateSimplificationPass() {
856 return MakeUnique<Optimizer::PassToken::Impl>(
857 MakeUnique<opt::SimplificationPass>());
858}
859
860Optimizer::PassToken CreateLoopUnrollPass(bool fully_unroll, int factor) {
861 return MakeUnique<Optimizer::PassToken::Impl>(
862 MakeUnique<opt::LoopUnroller>(fully_unroll, factor));
863}
864
865Optimizer::PassToken CreateSSARewritePass() {
866 return MakeUnique<Optimizer::PassToken::Impl>(
867 MakeUnique<opt::SSARewritePass>());
868}
869
870Optimizer::PassToken CreateCopyPropagateArraysPass() {
871 return MakeUnique<Optimizer::PassToken::Impl>(
872 MakeUnique<opt::CopyPropagateArrays>());
873}
874
875Optimizer::PassToken CreateVectorDCEPass() {
876 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::VectorDCE>());
877}
878
879Optimizer::PassToken CreateReduceLoadSizePass() {
880 return MakeUnique<Optimizer::PassToken::Impl>(
881 MakeUnique<opt::ReduceLoadSize>());
882}
883
884Optimizer::PassToken CreateCombineAccessChainsPass() {
885 return MakeUnique<Optimizer::PassToken::Impl>(
886 MakeUnique<opt::CombineAccessChains>());
887}
888
889Optimizer::PassToken CreateUpgradeMemoryModelPass() {
890 return MakeUnique<Optimizer::PassToken::Impl>(
891 MakeUnique<opt::UpgradeMemoryModel>());
892}
893
894Optimizer::PassToken CreateInstBindlessCheckPass(uint32_t desc_set,
Ben Claytonb73b7602019-07-29 13:56:13 +0100895 uint32_t shader_id,
896 bool input_length_enable,
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400897 bool input_init_enable,
898 bool input_buff_oob_enable) {
Chris Forbescc5697f2019-01-30 11:54:08 -0800899 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Clayton38e46912020-05-26 15:56:15 +0100900 MakeUnique<opt::InstBindlessCheckPass>(
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400901 desc_set, shader_id, input_length_enable, input_init_enable,
902 input_buff_oob_enable));
Chris Forbescc5697f2019-01-30 11:54:08 -0800903}
904
Alexis Hetub8a77462020-03-27 07:59:09 -0400905Optimizer::PassToken CreateInstDebugPrintfPass(uint32_t desc_set,
906 uint32_t shader_id) {
907 return MakeUnique<Optimizer::PassToken::Impl>(
908 MakeUnique<opt::InstDebugPrintfPass>(desc_set, shader_id));
909}
910
Ben Claytond0f684e2019-08-30 22:36:08 +0100911Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t desc_set,
Ben Clayton38e46912020-05-26 15:56:15 +0100912 uint32_t shader_id) {
Ben Claytond0f684e2019-08-30 22:36:08 +0100913 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Clayton38e46912020-05-26 15:56:15 +0100914 MakeUnique<opt::InstBuffAddrCheckPass>(desc_set, shader_id));
Ben Claytond0f684e2019-08-30 22:36:08 +0100915}
916
Ben Claytond552f632019-11-18 11:18:41 +0000917Optimizer::PassToken CreateConvertRelaxedToHalfPass() {
918 return MakeUnique<Optimizer::PassToken::Impl>(
919 MakeUnique<opt::ConvertToHalfPass>());
920}
921
922Optimizer::PassToken CreateRelaxFloatOpsPass() {
923 return MakeUnique<Optimizer::PassToken::Impl>(
924 MakeUnique<opt::RelaxFloatOpsPass>());
925}
926
Chris Forbescc5697f2019-01-30 11:54:08 -0800927Optimizer::PassToken CreateCodeSinkingPass() {
928 return MakeUnique<Optimizer::PassToken::Impl>(
929 MakeUnique<opt::CodeSinkingPass>());
930}
931
Ben Claytonb73b7602019-07-29 13:56:13 +0100932Optimizer::PassToken CreateGenerateWebGPUInitializersPass() {
933 return MakeUnique<Optimizer::PassToken::Impl>(
934 MakeUnique<opt::GenerateWebGPUInitializersPass>());
935}
936
937Optimizer::PassToken CreateFixStorageClassPass() {
938 return MakeUnique<Optimizer::PassToken::Impl>(
939 MakeUnique<opt::FixStorageClass>());
940}
941
942Optimizer::PassToken CreateLegalizeVectorShufflePass() {
943 return MakeUnique<Optimizer::PassToken::Impl>(
944 MakeUnique<opt::LegalizeVectorShufflePass>());
945}
946
947Optimizer::PassToken CreateDecomposeInitializedVariablesPass() {
948 return MakeUnique<Optimizer::PassToken::Impl>(
949 MakeUnique<opt::DecomposeInitializedVariablesPass>());
950}
951
952Optimizer::PassToken CreateSplitInvalidUnreachablePass() {
953 return MakeUnique<Optimizer::PassToken::Impl>(
954 MakeUnique<opt::SplitInvalidUnreachablePass>());
955}
956
Ben Claytond0f684e2019-08-30 22:36:08 +0100957Optimizer::PassToken CreateGraphicsRobustAccessPass() {
958 return MakeUnique<Optimizer::PassToken::Impl>(
959 MakeUnique<opt::GraphicsRobustAccessPass>());
960}
961
962Optimizer::PassToken CreateDescriptorScalarReplacementPass() {
963 return MakeUnique<Optimizer::PassToken::Impl>(
964 MakeUnique<opt::DescriptorScalarReplacement>());
965}
966
967Optimizer::PassToken CreateWrapOpKillPass() {
968 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::WrapOpKill>());
969}
970
971Optimizer::PassToken CreateAmdExtToKhrPass() {
972 return MakeUnique<Optimizer::PassToken::Impl>(
973 MakeUnique<opt::AmdExtensionToKhrPass>());
974}
975
Chris Forbescc5697f2019-01-30 11:54:08 -0800976} // namespace spvtools