blob: 1ded2ee9b3dfa6a5df9ef0bb94d065b92aa95c89 [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())
Sean Risserd2283f82020-11-05 14:17:31 -0500164 .RegisterPass(CreateEliminateDeadFunctionsPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800165 .RegisterPass(CreateAggressiveDCEPass())
166 .RegisterPass(CreatePrivateToLocalPass())
167 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
168 .RegisterPass(CreateLocalSingleStoreElimPass())
169 .RegisterPass(CreateAggressiveDCEPass())
170 .RegisterPass(CreateScalarReplacementPass())
171 .RegisterPass(CreateLocalAccessChainConvertPass())
172 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
173 .RegisterPass(CreateLocalSingleStoreElimPass())
174 .RegisterPass(CreateAggressiveDCEPass())
175 .RegisterPass(CreateLocalMultiStoreElimPass())
176 .RegisterPass(CreateAggressiveDCEPass())
177 .RegisterPass(CreateCCPPass())
178 .RegisterPass(CreateAggressiveDCEPass())
Ben Clayton38e46912020-05-26 15:56:15 +0100179 .RegisterPass(CreateLoopUnrollPass(true))
180 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800181 .RegisterPass(CreateRedundancyEliminationPass())
182 .RegisterPass(CreateCombineAccessChainsPass())
183 .RegisterPass(CreateSimplificationPass())
Ben Clayton38e46912020-05-26 15:56:15 +0100184 .RegisterPass(CreateScalarReplacementPass())
185 .RegisterPass(CreateLocalAccessChainConvertPass())
186 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
187 .RegisterPass(CreateLocalSingleStoreElimPass())
188 .RegisterPass(CreateAggressiveDCEPass())
189 .RegisterPass(CreateSSARewritePass())
190 .RegisterPass(CreateAggressiveDCEPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800191 .RegisterPass(CreateVectorDCEPass())
192 .RegisterPass(CreateDeadInsertElimPass())
193 .RegisterPass(CreateDeadBranchElimPass())
194 .RegisterPass(CreateSimplificationPass())
195 .RegisterPass(CreateIfConversionPass())
196 .RegisterPass(CreateCopyPropagateArraysPass())
197 .RegisterPass(CreateReduceLoadSizePass())
198 .RegisterPass(CreateAggressiveDCEPass())
199 .RegisterPass(CreateBlockMergePass())
200 .RegisterPass(CreateRedundancyEliminationPass())
201 .RegisterPass(CreateDeadBranchElimPass())
202 .RegisterPass(CreateBlockMergePass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100203 .RegisterPass(CreateSimplificationPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800204}
205
206Optimizer& Optimizer::RegisterSizePasses() {
Ben Claytond0f684e2019-08-30 22:36:08 +0100207 return RegisterPass(CreateWrapOpKillPass())
208 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800209 .RegisterPass(CreateMergeReturnPass())
210 .RegisterPass(CreateInlineExhaustivePass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000211 .RegisterPass(CreateEliminateDeadFunctionsPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800212 .RegisterPass(CreatePrivateToLocalPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000213 .RegisterPass(CreateScalarReplacementPass(0))
Chris Forbescc5697f2019-01-30 11:54:08 -0800214 .RegisterPass(CreateLocalMultiStoreElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800215 .RegisterPass(CreateCCPPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000216 .RegisterPass(CreateLoopUnrollPass(true))
217 .RegisterPass(CreateDeadBranchElimPass())
218 .RegisterPass(CreateSimplificationPass())
219 .RegisterPass(CreateScalarReplacementPass(0))
220 .RegisterPass(CreateLocalSingleStoreElimPass())
221 .RegisterPass(CreateIfConversionPass())
222 .RegisterPass(CreateSimplificationPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800223 .RegisterPass(CreateAggressiveDCEPass())
224 .RegisterPass(CreateDeadBranchElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800225 .RegisterPass(CreateBlockMergePass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000226 .RegisterPass(CreateLocalAccessChainConvertPass())
227 .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
228 .RegisterPass(CreateAggressiveDCEPass())
229 .RegisterPass(CreateCopyPropagateArraysPass())
230 .RegisterPass(CreateVectorDCEPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800231 .RegisterPass(CreateDeadInsertElimPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000232 .RegisterPass(CreateEliminateDeadMembersPass())
233 .RegisterPass(CreateLocalSingleStoreElimPass())
234 .RegisterPass(CreateBlockMergePass())
235 .RegisterPass(CreateLocalMultiStoreElimPass())
Chris Forbescc5697f2019-01-30 11:54:08 -0800236 .RegisterPass(CreateRedundancyEliminationPass())
Ben Clayton0b54f132020-01-06 13:38:54 +0000237 .RegisterPass(CreateSimplificationPass())
238 .RegisterPass(CreateAggressiveDCEPass())
239 .RegisterPass(CreateCFGCleanupPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800240}
241
Ben Claytonb73b7602019-07-29 13:56:13 +0100242Optimizer& Optimizer::RegisterVulkanToWebGPUPasses() {
Ben Clayton0b54f132020-01-06 13:38:54 +0000243 return RegisterPass(CreateStripAtomicCounterMemoryPass())
Ben Claytonb73b7602019-07-29 13:56:13 +0100244 .RegisterPass(CreateGenerateWebGPUInitializersPass())
245 .RegisterPass(CreateLegalizeVectorShufflePass())
246 .RegisterPass(CreateSplitInvalidUnreachablePass())
247 .RegisterPass(CreateEliminateDeadConstantPass())
248 .RegisterPass(CreateFlattenDecorationPass())
249 .RegisterPass(CreateAggressiveDCEPass())
250 .RegisterPass(CreateDeadBranchElimPass())
251 .RegisterPass(CreateCompactIdsPass());
252}
253
254Optimizer& Optimizer::RegisterWebGPUToVulkanPasses() {
255 return RegisterPass(CreateDecomposeInitializedVariablesPass())
256 .RegisterPass(CreateCompactIdsPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800257}
258
259bool Optimizer::RegisterPassesFromFlags(const std::vector<std::string>& flags) {
260 for (const auto& flag : flags) {
261 if (!RegisterPassFromFlag(flag)) {
262 return false;
263 }
264 }
265
266 return true;
267}
268
269bool Optimizer::FlagHasValidForm(const std::string& flag) const {
270 if (flag == "-O" || flag == "-Os") {
271 return true;
272 } else if (flag.size() > 2 && flag.substr(0, 2) == "--") {
273 return true;
274 }
275
276 Errorf(consumer(), nullptr, {},
277 "%s is not a valid flag. Flag passes should have the form "
278 "'--pass_name[=pass_args]'. Special flag names also accepted: -O "
279 "and -Os.",
280 flag.c_str());
281 return false;
282}
283
284bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
285 if (!FlagHasValidForm(flag)) {
286 return false;
287 }
288
289 // Split flags of the form --pass_name=pass_args.
290 auto p = utils::SplitFlagArgs(flag);
291 std::string pass_name = p.first;
292 std::string pass_args = p.second;
293
294 // FIXME(dnovillo): This should be re-factored so that pass names can be
295 // automatically checked against Pass::name() and PassToken instances created
296 // via a template function. Additionally, class Pass should have a desc()
297 // method that describes the pass (so it can be used in --help).
298 //
299 // Both Pass::name() and Pass::desc() should be static class members so they
300 // can be invoked without creating a pass instance.
Ben Claytonb73b7602019-07-29 13:56:13 +0100301 if (pass_name == "strip-atomic-counter-memory") {
302 RegisterPass(CreateStripAtomicCounterMemoryPass());
303 } else if (pass_name == "strip-debug") {
Chris Forbescc5697f2019-01-30 11:54:08 -0800304 RegisterPass(CreateStripDebugInfoPass());
305 } else if (pass_name == "strip-reflect") {
306 RegisterPass(CreateStripReflectInfoPass());
307 } else if (pass_name == "set-spec-const-default-value") {
308 if (pass_args.size() > 0) {
309 auto spec_ids_vals =
310 opt::SetSpecConstantDefaultValuePass::ParseDefaultValuesString(
311 pass_args.c_str());
312 if (!spec_ids_vals) {
313 Errorf(consumer(), nullptr, {},
314 "Invalid argument for --set-spec-const-default-value: %s",
315 pass_args.c_str());
316 return false;
317 }
318 RegisterPass(
319 CreateSetSpecConstantDefaultValuePass(std::move(*spec_ids_vals)));
320 } else {
321 Errorf(consumer(), nullptr, {},
322 "Invalid spec constant value string '%s'. Expected a string of "
323 "<spec id>:<default value> pairs.",
324 pass_args.c_str());
325 return false;
326 }
327 } else if (pass_name == "if-conversion") {
328 RegisterPass(CreateIfConversionPass());
329 } else if (pass_name == "freeze-spec-const") {
330 RegisterPass(CreateFreezeSpecConstantValuePass());
331 } else if (pass_name == "inline-entry-points-exhaustive") {
332 RegisterPass(CreateInlineExhaustivePass());
333 } else if (pass_name == "inline-entry-points-opaque") {
334 RegisterPass(CreateInlineOpaquePass());
335 } else if (pass_name == "combine-access-chains") {
336 RegisterPass(CreateCombineAccessChainsPass());
337 } else if (pass_name == "convert-local-access-chains") {
338 RegisterPass(CreateLocalAccessChainConvertPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100339 } else if (pass_name == "descriptor-scalar-replacement") {
340 RegisterPass(CreateDescriptorScalarReplacementPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800341 } else if (pass_name == "eliminate-dead-code-aggressive") {
342 RegisterPass(CreateAggressiveDCEPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800343 } else if (pass_name == "eliminate-insert-extract") {
344 RegisterPass(CreateInsertExtractElimPass());
345 } else if (pass_name == "eliminate-local-single-block") {
346 RegisterPass(CreateLocalSingleBlockLoadStoreElimPass());
347 } else if (pass_name == "eliminate-local-single-store") {
348 RegisterPass(CreateLocalSingleStoreElimPass());
349 } else if (pass_name == "merge-blocks") {
350 RegisterPass(CreateBlockMergePass());
351 } else if (pass_name == "merge-return") {
352 RegisterPass(CreateMergeReturnPass());
353 } else if (pass_name == "eliminate-dead-branches") {
354 RegisterPass(CreateDeadBranchElimPass());
355 } else if (pass_name == "eliminate-dead-functions") {
356 RegisterPass(CreateEliminateDeadFunctionsPass());
357 } else if (pass_name == "eliminate-local-multi-store") {
358 RegisterPass(CreateLocalMultiStoreElimPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800359 } else if (pass_name == "eliminate-dead-const") {
360 RegisterPass(CreateEliminateDeadConstantPass());
361 } else if (pass_name == "eliminate-dead-inserts") {
362 RegisterPass(CreateDeadInsertElimPass());
363 } else if (pass_name == "eliminate-dead-variables") {
364 RegisterPass(CreateDeadVariableEliminationPass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100365 } else if (pass_name == "eliminate-dead-members") {
366 RegisterPass(CreateEliminateDeadMembersPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800367 } else if (pass_name == "fold-spec-const-op-composite") {
368 RegisterPass(CreateFoldSpecConstantOpAndCompositePass());
369 } else if (pass_name == "loop-unswitch") {
370 RegisterPass(CreateLoopUnswitchPass());
371 } else if (pass_name == "scalar-replacement") {
372 if (pass_args.size() == 0) {
373 RegisterPass(CreateScalarReplacementPass());
374 } else {
375 int limit = -1;
376 if (pass_args.find_first_not_of("0123456789") == std::string::npos) {
377 limit = atoi(pass_args.c_str());
378 }
379
380 if (limit >= 0) {
381 RegisterPass(CreateScalarReplacementPass(limit));
382 } else {
383 Error(consumer(), nullptr, {},
384 "--scalar-replacement must have no arguments or a non-negative "
385 "integer argument");
386 return false;
387 }
388 }
389 } else if (pass_name == "strength-reduction") {
390 RegisterPass(CreateStrengthReductionPass());
391 } else if (pass_name == "unify-const") {
392 RegisterPass(CreateUnifyConstantPass());
393 } else if (pass_name == "flatten-decorations") {
394 RegisterPass(CreateFlattenDecorationPass());
395 } else if (pass_name == "compact-ids") {
396 RegisterPass(CreateCompactIdsPass());
397 } else if (pass_name == "cfg-cleanup") {
398 RegisterPass(CreateCFGCleanupPass());
399 } else if (pass_name == "local-redundancy-elimination") {
400 RegisterPass(CreateLocalRedundancyEliminationPass());
401 } else if (pass_name == "loop-invariant-code-motion") {
402 RegisterPass(CreateLoopInvariantCodeMotionPass());
403 } else if (pass_name == "reduce-load-size") {
404 RegisterPass(CreateReduceLoadSizePass());
405 } else if (pass_name == "redundancy-elimination") {
406 RegisterPass(CreateRedundancyEliminationPass());
407 } else if (pass_name == "private-to-local") {
408 RegisterPass(CreatePrivateToLocalPass());
409 } else if (pass_name == "remove-duplicates") {
410 RegisterPass(CreateRemoveDuplicatesPass());
411 } else if (pass_name == "workaround-1209") {
412 RegisterPass(CreateWorkaround1209Pass());
413 } else if (pass_name == "replace-invalid-opcode") {
414 RegisterPass(CreateReplaceInvalidOpcodePass());
415 } else if (pass_name == "inst-bindless-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100416 RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false));
Chris Forbescc5697f2019-01-30 11:54:08 -0800417 RegisterPass(CreateSimplificationPass());
418 RegisterPass(CreateDeadBranchElimPass());
419 RegisterPass(CreateBlockMergePass());
420 RegisterPass(CreateAggressiveDCEPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100421 } else if (pass_name == "inst-desc-idx-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100422 RegisterPass(CreateInstBindlessCheckPass(7, 23, true, true));
Ben Claytond0f684e2019-08-30 22:36:08 +0100423 RegisterPass(CreateSimplificationPass());
424 RegisterPass(CreateDeadBranchElimPass());
425 RegisterPass(CreateBlockMergePass());
426 RegisterPass(CreateAggressiveDCEPass());
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400427 } else if (pass_name == "inst-buff-oob-check") {
428 RegisterPass(CreateInstBindlessCheckPass(7, 23, false, false, true));
429 RegisterPass(CreateSimplificationPass());
430 RegisterPass(CreateDeadBranchElimPass());
431 RegisterPass(CreateBlockMergePass());
432 RegisterPass(CreateAggressiveDCEPass());
Ben Claytond0f684e2019-08-30 22:36:08 +0100433 } else if (pass_name == "inst-buff-addr-check") {
Ben Clayton38e46912020-05-26 15:56:15 +0100434 RegisterPass(CreateInstBuffAddrCheckPass(7, 23));
Ben Claytond0f684e2019-08-30 22:36:08 +0100435 RegisterPass(CreateAggressiveDCEPass());
Ben Claytond552f632019-11-18 11:18:41 +0000436 } else if (pass_name == "convert-relaxed-to-half") {
437 RegisterPass(CreateConvertRelaxedToHalfPass());
438 } else if (pass_name == "relax-float-ops") {
439 RegisterPass(CreateRelaxFloatOpsPass());
Alexis Hetub8a77462020-03-27 07:59:09 -0400440 } else if (pass_name == "inst-debug-printf") {
441 RegisterPass(CreateInstDebugPrintfPass(7, 23));
Chris Forbescc5697f2019-01-30 11:54:08 -0800442 } else if (pass_name == "simplify-instructions") {
443 RegisterPass(CreateSimplificationPass());
444 } else if (pass_name == "ssa-rewrite") {
445 RegisterPass(CreateSSARewritePass());
446 } else if (pass_name == "copy-propagate-arrays") {
447 RegisterPass(CreateCopyPropagateArraysPass());
448 } else if (pass_name == "loop-fission") {
449 int register_threshold_to_split =
450 (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
451 if (register_threshold_to_split > 0) {
452 RegisterPass(CreateLoopFissionPass(
453 static_cast<size_t>(register_threshold_to_split)));
454 } else {
455 Error(consumer(), nullptr, {},
456 "--loop-fission must have a positive integer argument");
457 return false;
458 }
459 } else if (pass_name == "loop-fusion") {
460 int max_registers_per_loop =
461 (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
462 if (max_registers_per_loop > 0) {
463 RegisterPass(
464 CreateLoopFusionPass(static_cast<size_t>(max_registers_per_loop)));
465 } else {
466 Error(consumer(), nullptr, {},
467 "--loop-fusion must have a positive integer argument");
468 return false;
469 }
470 } else if (pass_name == "loop-unroll") {
471 RegisterPass(CreateLoopUnrollPass(true));
472 } else if (pass_name == "upgrade-memory-model") {
473 RegisterPass(CreateUpgradeMemoryModelPass());
474 } else if (pass_name == "vector-dce") {
475 RegisterPass(CreateVectorDCEPass());
476 } else if (pass_name == "loop-unroll-partial") {
477 int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
478 if (factor > 0) {
479 RegisterPass(CreateLoopUnrollPass(false, factor));
480 } else {
481 Error(consumer(), nullptr, {},
482 "--loop-unroll-partial must have a positive integer argument");
483 return false;
484 }
485 } else if (pass_name == "loop-peeling") {
486 RegisterPass(CreateLoopPeelingPass());
487 } else if (pass_name == "loop-peeling-threshold") {
488 int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
489 if (factor > 0) {
490 opt::LoopPeelingPass::SetLoopPeelingThreshold(factor);
491 } else {
492 Error(consumer(), nullptr, {},
493 "--loop-peeling-threshold must have a positive integer argument");
494 return false;
495 }
496 } else if (pass_name == "ccp") {
497 RegisterPass(CreateCCPPass());
498 } else if (pass_name == "code-sink") {
499 RegisterPass(CreateCodeSinkingPass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100500 } else if (pass_name == "fix-storage-class") {
501 RegisterPass(CreateFixStorageClassPass());
Chris Forbescc5697f2019-01-30 11:54:08 -0800502 } else if (pass_name == "O") {
503 RegisterPerformancePasses();
504 } else if (pass_name == "Os") {
505 RegisterSizePasses();
506 } else if (pass_name == "legalize-hlsl") {
507 RegisterLegalizationPasses();
Ben Claytonb73b7602019-07-29 13:56:13 +0100508 } else if (pass_name == "generate-webgpu-initializers") {
509 RegisterPass(CreateGenerateWebGPUInitializersPass());
510 } else if (pass_name == "legalize-vector-shuffle") {
511 RegisterPass(CreateLegalizeVectorShufflePass());
512 } else if (pass_name == "split-invalid-unreachable") {
Ben Clayton38e46912020-05-26 15:56:15 +0100513 RegisterPass(CreateSplitInvalidUnreachablePass());
Ben Claytonb73b7602019-07-29 13:56:13 +0100514 } else if (pass_name == "decompose-initialized-variables") {
515 RegisterPass(CreateDecomposeInitializedVariablesPass());
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());
Chris Forbescc5697f2019-01-30 11:54:08 -0800522 } else {
523 Errorf(consumer(), nullptr, {},
524 "Unknown flag '--%s'. Use --help for a list of valid flags",
525 pass_name.c_str());
526 return false;
527 }
528
529 return true;
530}
531
532void Optimizer::SetTargetEnv(const spv_target_env env) {
533 impl_->target_env = env;
534}
535
536bool Optimizer::Run(const uint32_t* original_binary,
537 const size_t original_binary_size,
538 std::vector<uint32_t>* optimized_binary) const {
539 return Run(original_binary, original_binary_size, optimized_binary,
540 OptimizerOptions());
541}
542
543bool Optimizer::Run(const uint32_t* original_binary,
544 const size_t original_binary_size,
545 std::vector<uint32_t>* optimized_binary,
546 const ValidatorOptions& validator_options,
547 bool skip_validation) const {
548 OptimizerOptions opt_options;
549 opt_options.set_run_validator(!skip_validation);
550 opt_options.set_validator_options(validator_options);
551 return Run(original_binary, original_binary_size, optimized_binary,
552 opt_options);
553}
554
555bool Optimizer::Run(const uint32_t* original_binary,
556 const size_t original_binary_size,
557 std::vector<uint32_t>* optimized_binary,
558 const spv_optimizer_options opt_options) const {
559 spvtools::SpirvTools tools(impl_->target_env);
560 tools.SetMessageConsumer(impl_->pass_manager.consumer());
561 if (opt_options->run_validator_ &&
562 !tools.Validate(original_binary, original_binary_size,
563 &opt_options->val_options_)) {
564 return false;
565 }
566
567 std::unique_ptr<opt::IRContext> context = BuildModule(
568 impl_->target_env, consumer(), original_binary, original_binary_size);
569 if (context == nullptr) return false;
570
571 context->set_max_id_bound(opt_options->max_id_bound_);
Ben Claytonb73b7602019-07-29 13:56:13 +0100572 context->set_preserve_bindings(opt_options->preserve_bindings_);
573 context->set_preserve_spec_constants(opt_options->preserve_spec_constants_);
Chris Forbescc5697f2019-01-30 11:54:08 -0800574
Ben Claytonb73b7602019-07-29 13:56:13 +0100575 impl_->pass_manager.SetValidatorOptions(&opt_options->val_options_);
576 impl_->pass_manager.SetTargetEnv(impl_->target_env);
Chris Forbescc5697f2019-01-30 11:54:08 -0800577 auto status = impl_->pass_manager.Run(context.get());
Ben Claytonb73b7602019-07-29 13:56:13 +0100578
Ben Claytond0f684e2019-08-30 22:36:08 +0100579 if (status == opt::Pass::Status::Failure) {
580 return false;
Ben Claytonb73b7602019-07-29 13:56:13 +0100581 }
582
Ben Claytond0f684e2019-08-30 22:36:08 +0100583#ifndef NDEBUG
Alexis Hetub8a77462020-03-27 07:59:09 -0400584 // We do not keep the result id of DebugScope in struct DebugScope.
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400585 // Instead, we assign random ids for them, which results in integrity
586 // check failures. We want to skip the integrity check when the module
Alexis Hetub8a77462020-03-27 07:59:09 -0400587 // contains DebugScope instructions.
588 if (status == opt::Pass::Status::SuccessWithoutChange &&
589 !context->module()->ContainsDebugScope()) {
Ben Claytond552f632019-11-18 11:18:41 +0000590 std::vector<uint32_t> optimized_binary_with_nop;
591 context->module()->ToBinary(&optimized_binary_with_nop,
592 /* skip_nop = */ false);
593 assert(optimized_binary_with_nop.size() == original_binary_size &&
594 "Binary size unexpectedly changed despite the optimizer saying "
595 "there was no change");
596 assert(memcmp(optimized_binary_with_nop.data(), original_binary,
597 original_binary_size) == 0 &&
598 "Binary content unexpectedly changed despite the optimizer saying "
599 "there was no change");
Ben Claytond0f684e2019-08-30 22:36:08 +0100600 }
601#endif // !NDEBUG
602
Ben Claytond552f632019-11-18 11:18:41 +0000603 // Note that |original_binary| and |optimized_binary| may share the same
604 // buffer and the below will invalidate |original_binary|.
605 optimized_binary->clear();
606 context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
607
Ben Claytond0f684e2019-08-30 22:36:08 +0100608 return true;
Chris Forbescc5697f2019-01-30 11:54:08 -0800609}
610
611Optimizer& Optimizer::SetPrintAll(std::ostream* out) {
612 impl_->pass_manager.SetPrintAll(out);
613 return *this;
614}
615
616Optimizer& Optimizer::SetTimeReport(std::ostream* out) {
617 impl_->pass_manager.SetTimeReport(out);
618 return *this;
619}
620
Ben Claytonb73b7602019-07-29 13:56:13 +0100621Optimizer& Optimizer::SetValidateAfterAll(bool validate) {
622 impl_->pass_manager.SetValidateAfterAll(validate);
623 return *this;
624}
625
Chris Forbescc5697f2019-01-30 11:54:08 -0800626Optimizer::PassToken CreateNullPass() {
627 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
628}
629
Ben Claytonb73b7602019-07-29 13:56:13 +0100630Optimizer::PassToken CreateStripAtomicCounterMemoryPass() {
631 return MakeUnique<Optimizer::PassToken::Impl>(
632 MakeUnique<opt::StripAtomicCounterMemoryPass>());
633}
634
Chris Forbescc5697f2019-01-30 11:54:08 -0800635Optimizer::PassToken CreateStripDebugInfoPass() {
636 return MakeUnique<Optimizer::PassToken::Impl>(
637 MakeUnique<opt::StripDebugInfoPass>());
638}
639
640Optimizer::PassToken CreateStripReflectInfoPass() {
641 return MakeUnique<Optimizer::PassToken::Impl>(
642 MakeUnique<opt::StripReflectInfoPass>());
643}
644
645Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
646 return MakeUnique<Optimizer::PassToken::Impl>(
647 MakeUnique<opt::EliminateDeadFunctionsPass>());
648}
649
Ben Claytonb73b7602019-07-29 13:56:13 +0100650Optimizer::PassToken CreateEliminateDeadMembersPass() {
651 return MakeUnique<Optimizer::PassToken::Impl>(
652 MakeUnique<opt::EliminateDeadMembersPass>());
653}
654
Chris Forbescc5697f2019-01-30 11:54:08 -0800655Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
656 const std::unordered_map<uint32_t, std::string>& id_value_map) {
657 return MakeUnique<Optimizer::PassToken::Impl>(
658 MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
659}
660
661Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
662 const std::unordered_map<uint32_t, std::vector<uint32_t>>& id_value_map) {
663 return MakeUnique<Optimizer::PassToken::Impl>(
664 MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
665}
666
667Optimizer::PassToken CreateFlattenDecorationPass() {
668 return MakeUnique<Optimizer::PassToken::Impl>(
669 MakeUnique<opt::FlattenDecorationPass>());
670}
671
672Optimizer::PassToken CreateFreezeSpecConstantValuePass() {
673 return MakeUnique<Optimizer::PassToken::Impl>(
674 MakeUnique<opt::FreezeSpecConstantValuePass>());
675}
676
677Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass() {
678 return MakeUnique<Optimizer::PassToken::Impl>(
679 MakeUnique<opt::FoldSpecConstantOpAndCompositePass>());
680}
681
682Optimizer::PassToken CreateUnifyConstantPass() {
683 return MakeUnique<Optimizer::PassToken::Impl>(
684 MakeUnique<opt::UnifyConstantPass>());
685}
686
687Optimizer::PassToken CreateEliminateDeadConstantPass() {
688 return MakeUnique<Optimizer::PassToken::Impl>(
689 MakeUnique<opt::EliminateDeadConstantPass>());
690}
691
692Optimizer::PassToken CreateDeadVariableEliminationPass() {
693 return MakeUnique<Optimizer::PassToken::Impl>(
694 MakeUnique<opt::DeadVariableElimination>());
695}
696
697Optimizer::PassToken CreateStrengthReductionPass() {
698 return MakeUnique<Optimizer::PassToken::Impl>(
699 MakeUnique<opt::StrengthReductionPass>());
700}
701
702Optimizer::PassToken CreateBlockMergePass() {
703 return MakeUnique<Optimizer::PassToken::Impl>(
704 MakeUnique<opt::BlockMergePass>());
705}
706
707Optimizer::PassToken CreateInlineExhaustivePass() {
708 return MakeUnique<Optimizer::PassToken::Impl>(
709 MakeUnique<opt::InlineExhaustivePass>());
710}
711
712Optimizer::PassToken CreateInlineOpaquePass() {
713 return MakeUnique<Optimizer::PassToken::Impl>(
714 MakeUnique<opt::InlineOpaquePass>());
715}
716
717Optimizer::PassToken CreateLocalAccessChainConvertPass() {
718 return MakeUnique<Optimizer::PassToken::Impl>(
719 MakeUnique<opt::LocalAccessChainConvertPass>());
720}
721
722Optimizer::PassToken CreateLocalSingleBlockLoadStoreElimPass() {
723 return MakeUnique<Optimizer::PassToken::Impl>(
724 MakeUnique<opt::LocalSingleBlockLoadStoreElimPass>());
725}
726
727Optimizer::PassToken CreateLocalSingleStoreElimPass() {
728 return MakeUnique<Optimizer::PassToken::Impl>(
729 MakeUnique<opt::LocalSingleStoreElimPass>());
730}
731
732Optimizer::PassToken CreateInsertExtractElimPass() {
733 return MakeUnique<Optimizer::PassToken::Impl>(
734 MakeUnique<opt::SimplificationPass>());
735}
736
737Optimizer::PassToken CreateDeadInsertElimPass() {
738 return MakeUnique<Optimizer::PassToken::Impl>(
739 MakeUnique<opt::DeadInsertElimPass>());
740}
741
742Optimizer::PassToken CreateDeadBranchElimPass() {
743 return MakeUnique<Optimizer::PassToken::Impl>(
744 MakeUnique<opt::DeadBranchElimPass>());
745}
746
747Optimizer::PassToken CreateLocalMultiStoreElimPass() {
748 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Claytond552f632019-11-18 11:18:41 +0000749 MakeUnique<opt::SSARewritePass>());
Chris Forbescc5697f2019-01-30 11:54:08 -0800750}
751
752Optimizer::PassToken CreateAggressiveDCEPass() {
753 return MakeUnique<Optimizer::PassToken::Impl>(
754 MakeUnique<opt::AggressiveDCEPass>());
755}
756
Alexis Hetu7975f152020-11-02 11:08:33 -0500757Optimizer::PassToken CreatePropagateLineInfoPass() {
758 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
759}
760
761Optimizer::PassToken CreateRedundantLineInfoElimPass() {
762 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
763}
764
Chris Forbescc5697f2019-01-30 11:54:08 -0800765Optimizer::PassToken CreateCompactIdsPass() {
766 return MakeUnique<Optimizer::PassToken::Impl>(
767 MakeUnique<opt::CompactIdsPass>());
768}
769
770Optimizer::PassToken CreateMergeReturnPass() {
771 return MakeUnique<Optimizer::PassToken::Impl>(
772 MakeUnique<opt::MergeReturnPass>());
773}
774
775std::vector<const char*> Optimizer::GetPassNames() const {
776 std::vector<const char*> v;
777 for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); i++) {
778 v.push_back(impl_->pass_manager.GetPass(i)->name());
779 }
780 return v;
781}
782
783Optimizer::PassToken CreateCFGCleanupPass() {
784 return MakeUnique<Optimizer::PassToken::Impl>(
785 MakeUnique<opt::CFGCleanupPass>());
786}
787
788Optimizer::PassToken CreateLocalRedundancyEliminationPass() {
789 return MakeUnique<Optimizer::PassToken::Impl>(
790 MakeUnique<opt::LocalRedundancyEliminationPass>());
791}
792
793Optimizer::PassToken CreateLoopFissionPass(size_t threshold) {
794 return MakeUnique<Optimizer::PassToken::Impl>(
795 MakeUnique<opt::LoopFissionPass>(threshold));
796}
797
798Optimizer::PassToken CreateLoopFusionPass(size_t max_registers_per_loop) {
799 return MakeUnique<Optimizer::PassToken::Impl>(
800 MakeUnique<opt::LoopFusionPass>(max_registers_per_loop));
801}
802
803Optimizer::PassToken CreateLoopInvariantCodeMotionPass() {
804 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::LICMPass>());
805}
806
807Optimizer::PassToken CreateLoopPeelingPass() {
808 return MakeUnique<Optimizer::PassToken::Impl>(
809 MakeUnique<opt::LoopPeelingPass>());
810}
811
812Optimizer::PassToken CreateLoopUnswitchPass() {
813 return MakeUnique<Optimizer::PassToken::Impl>(
814 MakeUnique<opt::LoopUnswitchPass>());
815}
816
817Optimizer::PassToken CreateRedundancyEliminationPass() {
818 return MakeUnique<Optimizer::PassToken::Impl>(
819 MakeUnique<opt::RedundancyEliminationPass>());
820}
821
822Optimizer::PassToken CreateRemoveDuplicatesPass() {
823 return MakeUnique<Optimizer::PassToken::Impl>(
824 MakeUnique<opt::RemoveDuplicatesPass>());
825}
826
827Optimizer::PassToken CreateScalarReplacementPass(uint32_t size_limit) {
828 return MakeUnique<Optimizer::PassToken::Impl>(
829 MakeUnique<opt::ScalarReplacementPass>(size_limit));
830}
831
832Optimizer::PassToken CreatePrivateToLocalPass() {
833 return MakeUnique<Optimizer::PassToken::Impl>(
834 MakeUnique<opt::PrivateToLocalPass>());
835}
836
837Optimizer::PassToken CreateCCPPass() {
838 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::CCPPass>());
839}
840
841Optimizer::PassToken CreateWorkaround1209Pass() {
842 return MakeUnique<Optimizer::PassToken::Impl>(
843 MakeUnique<opt::Workaround1209>());
844}
845
846Optimizer::PassToken CreateIfConversionPass() {
847 return MakeUnique<Optimizer::PassToken::Impl>(
848 MakeUnique<opt::IfConversion>());
849}
850
851Optimizer::PassToken CreateReplaceInvalidOpcodePass() {
852 return MakeUnique<Optimizer::PassToken::Impl>(
853 MakeUnique<opt::ReplaceInvalidOpcodePass>());
854}
855
856Optimizer::PassToken CreateSimplificationPass() {
857 return MakeUnique<Optimizer::PassToken::Impl>(
858 MakeUnique<opt::SimplificationPass>());
859}
860
861Optimizer::PassToken CreateLoopUnrollPass(bool fully_unroll, int factor) {
862 return MakeUnique<Optimizer::PassToken::Impl>(
863 MakeUnique<opt::LoopUnroller>(fully_unroll, factor));
864}
865
866Optimizer::PassToken CreateSSARewritePass() {
867 return MakeUnique<Optimizer::PassToken::Impl>(
868 MakeUnique<opt::SSARewritePass>());
869}
870
871Optimizer::PassToken CreateCopyPropagateArraysPass() {
872 return MakeUnique<Optimizer::PassToken::Impl>(
873 MakeUnique<opt::CopyPropagateArrays>());
874}
875
876Optimizer::PassToken CreateVectorDCEPass() {
877 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::VectorDCE>());
878}
879
880Optimizer::PassToken CreateReduceLoadSizePass() {
881 return MakeUnique<Optimizer::PassToken::Impl>(
882 MakeUnique<opt::ReduceLoadSize>());
883}
884
885Optimizer::PassToken CreateCombineAccessChainsPass() {
886 return MakeUnique<Optimizer::PassToken::Impl>(
887 MakeUnique<opt::CombineAccessChains>());
888}
889
890Optimizer::PassToken CreateUpgradeMemoryModelPass() {
891 return MakeUnique<Optimizer::PassToken::Impl>(
892 MakeUnique<opt::UpgradeMemoryModel>());
893}
894
895Optimizer::PassToken CreateInstBindlessCheckPass(uint32_t desc_set,
Ben Claytonb73b7602019-07-29 13:56:13 +0100896 uint32_t shader_id,
897 bool input_length_enable,
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400898 bool input_init_enable,
899 bool input_buff_oob_enable) {
Chris Forbescc5697f2019-01-30 11:54:08 -0800900 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Clayton38e46912020-05-26 15:56:15 +0100901 MakeUnique<opt::InstBindlessCheckPass>(
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400902 desc_set, shader_id, input_length_enable, input_init_enable,
903 input_buff_oob_enable));
Chris Forbescc5697f2019-01-30 11:54:08 -0800904}
905
Alexis Hetub8a77462020-03-27 07:59:09 -0400906Optimizer::PassToken CreateInstDebugPrintfPass(uint32_t desc_set,
907 uint32_t shader_id) {
908 return MakeUnique<Optimizer::PassToken::Impl>(
909 MakeUnique<opt::InstDebugPrintfPass>(desc_set, shader_id));
910}
911
Ben Claytond0f684e2019-08-30 22:36:08 +0100912Optimizer::PassToken CreateInstBuffAddrCheckPass(uint32_t desc_set,
Ben Clayton38e46912020-05-26 15:56:15 +0100913 uint32_t shader_id) {
Ben Claytond0f684e2019-08-30 22:36:08 +0100914 return MakeUnique<Optimizer::PassToken::Impl>(
Ben Clayton38e46912020-05-26 15:56:15 +0100915 MakeUnique<opt::InstBuffAddrCheckPass>(desc_set, shader_id));
Ben Claytond0f684e2019-08-30 22:36:08 +0100916}
917
Ben Claytond552f632019-11-18 11:18:41 +0000918Optimizer::PassToken CreateConvertRelaxedToHalfPass() {
919 return MakeUnique<Optimizer::PassToken::Impl>(
920 MakeUnique<opt::ConvertToHalfPass>());
921}
922
923Optimizer::PassToken CreateRelaxFloatOpsPass() {
924 return MakeUnique<Optimizer::PassToken::Impl>(
925 MakeUnique<opt::RelaxFloatOpsPass>());
926}
927
Chris Forbescc5697f2019-01-30 11:54:08 -0800928Optimizer::PassToken CreateCodeSinkingPass() {
929 return MakeUnique<Optimizer::PassToken::Impl>(
930 MakeUnique<opt::CodeSinkingPass>());
931}
932
Ben Claytonb73b7602019-07-29 13:56:13 +0100933Optimizer::PassToken CreateGenerateWebGPUInitializersPass() {
934 return MakeUnique<Optimizer::PassToken::Impl>(
935 MakeUnique<opt::GenerateWebGPUInitializersPass>());
936}
937
938Optimizer::PassToken CreateFixStorageClassPass() {
939 return MakeUnique<Optimizer::PassToken::Impl>(
940 MakeUnique<opt::FixStorageClass>());
941}
942
943Optimizer::PassToken CreateLegalizeVectorShufflePass() {
944 return MakeUnique<Optimizer::PassToken::Impl>(
945 MakeUnique<opt::LegalizeVectorShufflePass>());
946}
947
948Optimizer::PassToken CreateDecomposeInitializedVariablesPass() {
949 return MakeUnique<Optimizer::PassToken::Impl>(
950 MakeUnique<opt::DecomposeInitializedVariablesPass>());
951}
952
953Optimizer::PassToken CreateSplitInvalidUnreachablePass() {
954 return MakeUnique<Optimizer::PassToken::Impl>(
955 MakeUnique<opt::SplitInvalidUnreachablePass>());
956}
957
Ben Claytond0f684e2019-08-30 22:36:08 +0100958Optimizer::PassToken CreateGraphicsRobustAccessPass() {
959 return MakeUnique<Optimizer::PassToken::Impl>(
960 MakeUnique<opt::GraphicsRobustAccessPass>());
961}
962
963Optimizer::PassToken CreateDescriptorScalarReplacementPass() {
964 return MakeUnique<Optimizer::PassToken::Impl>(
965 MakeUnique<opt::DescriptorScalarReplacement>());
966}
967
968Optimizer::PassToken CreateWrapOpKillPass() {
969 return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::WrapOpKill>());
970}
971
972Optimizer::PassToken CreateAmdExtToKhrPass() {
973 return MakeUnique<Optimizer::PassToken::Impl>(
974 MakeUnique<opt::AmdExtensionToKhrPass>());
975}
976
Chris Forbescc5697f2019-01-30 11:54:08 -0800977} // namespace spvtools