| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303 |
- // Copyright (c) 2016 Google Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "spirv-tools/optimizer.hpp"
- #include <cassert>
- #include <charconv>
- #include <memory>
- #include <string>
- #include <system_error>
- #include <unordered_map>
- #include <utility>
- #include <vector>
- #include "source/opt/build_module.h"
- #include "source/opt/graphics_robust_access_pass.h"
- #include "source/opt/log.h"
- #include "source/opt/pass_manager.h"
- #include "source/opt/passes.h"
- #include "source/spirv_optimizer_options.h"
- #include "source/util/make_unique.h"
- #include "source/util/string_utils.h"
- namespace spvtools {
- std::vector<std::string> GetVectorOfStrings(const char** strings,
- const size_t string_count) {
- std::vector<std::string> result;
- for (uint32_t i = 0; i < string_count; i++) {
- result.emplace_back(strings[i]);
- }
- return result;
- }
- struct Optimizer::PassToken::Impl {
- Impl(std::unique_ptr<opt::Pass> p) : pass(std::move(p)) {}
- std::unique_ptr<opt::Pass> pass; // Internal implementation pass.
- };
- Optimizer::PassToken::PassToken(
- std::unique_ptr<Optimizer::PassToken::Impl> impl)
- : impl_(std::move(impl)) {}
- Optimizer::PassToken::PassToken(std::unique_ptr<opt::Pass>&& pass)
- : impl_(MakeUnique<Optimizer::PassToken::Impl>(std::move(pass))) {}
- Optimizer::PassToken::PassToken(PassToken&& that)
- : impl_(std::move(that.impl_)) {}
- Optimizer::PassToken& Optimizer::PassToken::operator=(PassToken&& that) {
- impl_ = std::move(that.impl_);
- return *this;
- }
- Optimizer::PassToken::~PassToken() {}
- struct Optimizer::Impl {
- explicit Impl(spv_target_env env) : target_env(env), pass_manager() {}
- spv_target_env target_env; // Target environment.
- opt::PassManager pass_manager; // Internal implementation pass manager.
- std::unordered_set<uint32_t> live_locs; // Arg to debug dead output passes
- };
- Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {
- assert(env != SPV_ENV_WEBGPU_0);
- }
- Optimizer::~Optimizer() {}
- void Optimizer::SetMessageConsumer(MessageConsumer c) {
- // All passes' message consumer needs to be updated.
- for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); ++i) {
- impl_->pass_manager.GetPass(i)->SetMessageConsumer(c);
- }
- impl_->pass_manager.SetMessageConsumer(std::move(c));
- }
- const MessageConsumer& Optimizer::consumer() const {
- return impl_->pass_manager.consumer();
- }
- Optimizer& Optimizer::RegisterPass(PassToken&& p) {
- // Change to use the pass manager's consumer.
- p.impl_->pass->SetMessageConsumer(consumer());
- impl_->pass_manager.AddPass(std::move(p.impl_->pass));
- return *this;
- }
- // The legalization passes take a spir-v shader generated by an HLSL front-end
- // and turn it into a valid vulkan spir-v shader. There are two ways in which
- // the code will be invalid at the start:
- //
- // 1) There will be opaque objects, like images, which will be passed around
- // in intermediate objects. Valid spir-v will have to replace the use of
- // the opaque object with an intermediate object that is the result of the
- // load of the global opaque object.
- //
- // 2) There will be variables that contain pointers to structured or uniform
- // buffers. It be legal, the variables must be eliminated, and the
- // references to the structured buffers must use the result of OpVariable
- // in the Uniform storage class.
- //
- // Optimization in this list must accept shaders with these relaxation of the
- // rules. There is not guarantee that this list of optimizations is able to
- // legalize all inputs, but it is on a best effort basis.
- //
- // The legalization problem is essentially a very general copy propagation
- // problem. The optimization we use are all used to either do copy propagation
- // or enable more copy propagation.
- Optimizer& Optimizer::RegisterLegalizationPasses(bool preserve_interface) {
- return
- // Wrap OpKill instructions so all other code can be inlined.
- RegisterPass(CreateWrapOpKillPass())
- // Remove unreachable block so that merge return works.
- .RegisterPass(CreateDeadBranchElimPass())
- // Merge the returns so we can inline.
- .RegisterPass(CreateMergeReturnPass())
- // Make sure uses and definitions are in the same function.
- .RegisterPass(CreateInlineExhaustivePass())
- // Make private variable function scope
- .RegisterPass(CreateEliminateDeadFunctionsPass())
- .RegisterPass(CreatePrivateToLocalPass())
- // Fix up the storage classes that DXC may have purposely generated
- // incorrectly. All functions are inlined, and a lot of dead code has
- // been removed.
- .RegisterPass(CreateFixStorageClassPass())
- // Propagate the value stored to the loads in very simple cases.
- .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- // Split up aggregates so they are easier to deal with.
- .RegisterPass(CreateScalarReplacementPass(0))
- // Remove loads and stores so everything is in intermediate values.
- // Takes care of copy propagation of non-members.
- .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateLocalMultiStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- // Propagate constants to get as many constant conditions on branches
- // as possible.
- .RegisterPass(CreateCCPPass())
- .RegisterPass(CreateLoopUnrollPass(true))
- .RegisterPass(CreateDeadBranchElimPass())
- // Copy propagate members. Cleans up code sequences generated by
- // scalar replacement. Also important for removing OpPhi nodes.
- .RegisterPass(CreateSimplificationPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateCopyPropagateArraysPass())
- // May need loop unrolling here see
- // https://github.com/Microsoft/DirectXShaderCompiler/pull/930
- // Get rid of unused code that contain traces of illegal code
- // or unused references to unbound external objects
- .RegisterPass(CreateVectorDCEPass())
- .RegisterPass(CreateDeadInsertElimPass())
- .RegisterPass(CreateReduceLoadSizePass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateRemoveUnusedInterfaceVariablesPass())
- .RegisterPass(CreateInterpolateFixupPass())
- .RegisterPass(CreateInvocationInterlockPlacementPass())
- .RegisterPass(CreateOpExtInstWithForwardReferenceFixupPass());
- }
- Optimizer& Optimizer::RegisterLegalizationPasses() {
- return RegisterLegalizationPasses(false);
- }
- Optimizer& Optimizer::RegisterPerformancePasses(bool preserve_interface) {
- return RegisterPass(CreateWrapOpKillPass())
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateMergeReturnPass())
- .RegisterPass(CreateInlineExhaustivePass())
- .RegisterPass(CreateEliminateDeadFunctionsPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreatePrivateToLocalPass())
- .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateScalarReplacementPass(0))
- .RegisterPass(CreateLocalAccessChainConvertPass())
- .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateLocalMultiStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateCCPPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateLoopUnrollPass(true))
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateRedundancyEliminationPass())
- .RegisterPass(CreateCombineAccessChainsPass())
- .RegisterPass(CreateSimplificationPass())
- .RegisterPass(CreateScalarReplacementPass(0))
- .RegisterPass(CreateLocalAccessChainConvertPass())
- .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateSSARewritePass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateVectorDCEPass())
- .RegisterPass(CreateDeadInsertElimPass())
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateSimplificationPass())
- .RegisterPass(CreateIfConversionPass())
- .RegisterPass(CreateCopyPropagateArraysPass())
- .RegisterPass(CreateReduceLoadSizePass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateBlockMergePass())
- .RegisterPass(CreateRedundancyEliminationPass())
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateBlockMergePass())
- .RegisterPass(CreateSimplificationPass());
- }
- Optimizer& Optimizer::RegisterPerformancePasses() {
- return RegisterPerformancePasses(false);
- }
- Optimizer& Optimizer::RegisterSizePasses(bool preserve_interface) {
- return RegisterPass(CreateWrapOpKillPass())
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateMergeReturnPass())
- .RegisterPass(CreateInlineExhaustivePass())
- .RegisterPass(CreateEliminateDeadFunctionsPass())
- .RegisterPass(CreatePrivateToLocalPass())
- .RegisterPass(CreateScalarReplacementPass(0))
- .RegisterPass(CreateLocalMultiStoreElimPass())
- .RegisterPass(CreateCCPPass())
- .RegisterPass(CreateLoopUnrollPass(true))
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateSimplificationPass())
- .RegisterPass(CreateScalarReplacementPass(0))
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateIfConversionPass())
- .RegisterPass(CreateSimplificationPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateDeadBranchElimPass())
- .RegisterPass(CreateBlockMergePass())
- .RegisterPass(CreateLocalAccessChainConvertPass())
- .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateCopyPropagateArraysPass())
- .RegisterPass(CreateVectorDCEPass())
- .RegisterPass(CreateDeadInsertElimPass())
- .RegisterPass(CreateEliminateDeadMembersPass())
- .RegisterPass(CreateLocalSingleStoreElimPass())
- .RegisterPass(CreateBlockMergePass())
- .RegisterPass(CreateLocalMultiStoreElimPass())
- .RegisterPass(CreateRedundancyEliminationPass())
- .RegisterPass(CreateSimplificationPass())
- .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
- .RegisterPass(CreateCFGCleanupPass());
- }
- Optimizer& Optimizer::RegisterSizePasses() { return RegisterSizePasses(false); }
- bool Optimizer::RegisterPassesFromFlags(const std::vector<std::string>& flags) {
- return RegisterPassesFromFlags(flags, false);
- }
- bool Optimizer::RegisterPassesFromFlags(const std::vector<std::string>& flags,
- bool preserve_interface) {
- for (const auto& flag : flags) {
- if (!RegisterPassFromFlag(flag, preserve_interface)) {
- return false;
- }
- }
- return true;
- }
- bool Optimizer::FlagHasValidForm(const std::string& flag) const {
- if (flag == "-O" || flag == "-Os") {
- return true;
- } else if (flag.size() > 2 && flag.substr(0, 2) == "--") {
- return true;
- }
- Errorf(consumer(), nullptr, {},
- "%s is not a valid flag. Flag passes should have the form "
- "'--pass_name[=pass_args]'. Special flag names also accepted: -O "
- "and -Os.",
- flag.c_str());
- return false;
- }
- bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
- return RegisterPassFromFlag(flag, false);
- }
- bool Optimizer::RegisterPassFromFlag(const std::string& flag,
- bool preserve_interface) {
- if (!FlagHasValidForm(flag)) {
- return false;
- }
- // Split flags of the form --pass_name=pass_args.
- auto p = utils::SplitFlagArgs(flag);
- std::string pass_name = p.first;
- std::string pass_args = p.second;
- // FIXME(dnovillo): This should be re-factored so that pass names can be
- // automatically checked against Pass::name() and PassToken instances created
- // via a template function. Additionally, class Pass should have a desc()
- // method that describes the pass (so it can be used in --help).
- //
- // Both Pass::name() and Pass::desc() should be static class members so they
- // can be invoked without creating a pass instance.
- if (pass_name == "strip-debug") {
- RegisterPass(CreateStripDebugInfoPass());
- } else if (pass_name == "strip-reflect") {
- RegisterPass(CreateStripReflectInfoPass());
- } else if (pass_name == "strip-nonsemantic") {
- RegisterPass(CreateStripNonSemanticInfoPass());
- } else if (pass_name == "fix-opextinst-opcodes") {
- RegisterPass(CreateOpExtInstWithForwardReferenceFixupPass());
- } else if (pass_name == "set-spec-const-default-value") {
- if (pass_args.size() > 0) {
- auto spec_ids_vals =
- opt::SetSpecConstantDefaultValuePass::ParseDefaultValuesString(
- pass_args.c_str());
- if (!spec_ids_vals) {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --set-spec-const-default-value: %s",
- pass_args.c_str());
- return false;
- }
- RegisterPass(
- CreateSetSpecConstantDefaultValuePass(std::move(*spec_ids_vals)));
- } else {
- Errorf(consumer(), nullptr, {},
- "Invalid spec constant value string '%s'. Expected a string of "
- "<spec id>:<default value> pairs.",
- pass_args.c_str());
- return false;
- }
- } else if (pass_name == "if-conversion") {
- RegisterPass(CreateIfConversionPass());
- } else if (pass_name == "freeze-spec-const") {
- RegisterPass(CreateFreezeSpecConstantValuePass());
- } else if (pass_name == "inline-entry-points-exhaustive") {
- RegisterPass(CreateInlineExhaustivePass());
- } else if (pass_name == "inline-entry-points-opaque") {
- RegisterPass(CreateInlineOpaquePass());
- } else if (pass_name == "combine-access-chains") {
- RegisterPass(CreateCombineAccessChainsPass());
- } else if (pass_name == "convert-local-access-chains") {
- RegisterPass(CreateLocalAccessChainConvertPass());
- } else if (pass_name == "replace-desc-array-access-using-var-index") {
- RegisterPass(CreateReplaceDescArrayAccessUsingVarIndexPass());
- } else if (pass_name == "spread-volatile-semantics") {
- RegisterPass(CreateSpreadVolatileSemanticsPass());
- } else if (pass_name == "descriptor-scalar-replacement") {
- RegisterPass(CreateDescriptorScalarReplacementPass());
- } else if (pass_name == "descriptor-composite-scalar-replacement") {
- RegisterPass(CreateDescriptorCompositeScalarReplacementPass());
- } else if (pass_name == "descriptor-array-scalar-replacement") {
- RegisterPass(CreateDescriptorArrayScalarReplacementPass());
- } else if (pass_name == "eliminate-dead-code-aggressive") {
- RegisterPass(CreateAggressiveDCEPass(preserve_interface));
- } else if (pass_name == "eliminate-insert-extract") {
- RegisterPass(CreateInsertExtractElimPass());
- } else if (pass_name == "eliminate-local-single-block") {
- RegisterPass(CreateLocalSingleBlockLoadStoreElimPass());
- } else if (pass_name == "eliminate-local-single-store") {
- RegisterPass(CreateLocalSingleStoreElimPass());
- } else if (pass_name == "merge-blocks") {
- RegisterPass(CreateBlockMergePass());
- } else if (pass_name == "merge-return") {
- RegisterPass(CreateMergeReturnPass());
- } else if (pass_name == "eliminate-dead-branches") {
- RegisterPass(CreateDeadBranchElimPass());
- } else if (pass_name == "eliminate-dead-functions") {
- RegisterPass(CreateEliminateDeadFunctionsPass());
- } else if (pass_name == "eliminate-local-multi-store") {
- RegisterPass(CreateLocalMultiStoreElimPass());
- } else if (pass_name == "eliminate-dead-const") {
- RegisterPass(CreateEliminateDeadConstantPass());
- } else if (pass_name == "eliminate-dead-inserts") {
- RegisterPass(CreateDeadInsertElimPass());
- } else if (pass_name == "eliminate-dead-variables") {
- RegisterPass(CreateDeadVariableEliminationPass());
- } else if (pass_name == "eliminate-dead-members") {
- RegisterPass(CreateEliminateDeadMembersPass());
- } else if (pass_name == "fold-spec-const-op-composite") {
- RegisterPass(CreateFoldSpecConstantOpAndCompositePass());
- } else if (pass_name == "loop-unswitch") {
- RegisterPass(CreateLoopUnswitchPass());
- } else if (pass_name == "scalar-replacement") {
- if (pass_args.size() == 0) {
- RegisterPass(CreateScalarReplacementPass(0));
- } else {
- int limit = -1;
- if (pass_args.find_first_not_of("0123456789") == std::string::npos) {
- limit = atoi(pass_args.c_str());
- }
- if (limit >= 0) {
- RegisterPass(CreateScalarReplacementPass(limit));
- } else {
- Error(consumer(), nullptr, {},
- "--scalar-replacement must have no arguments or a non-negative "
- "integer argument");
- return false;
- }
- }
- } else if (pass_name == "strength-reduction") {
- RegisterPass(CreateStrengthReductionPass());
- } else if (pass_name == "unify-const") {
- RegisterPass(CreateUnifyConstantPass());
- } else if (pass_name == "flatten-decorations") {
- RegisterPass(CreateFlattenDecorationPass());
- } else if (pass_name == "compact-ids") {
- RegisterPass(CreateCompactIdsPass());
- } else if (pass_name == "cfg-cleanup") {
- RegisterPass(CreateCFGCleanupPass());
- } else if (pass_name == "local-redundancy-elimination") {
- RegisterPass(CreateLocalRedundancyEliminationPass());
- } else if (pass_name == "loop-invariant-code-motion") {
- RegisterPass(CreateLoopInvariantCodeMotionPass());
- } else if (pass_name == "reduce-load-size") {
- if (pass_args.size() == 0) {
- RegisterPass(CreateReduceLoadSizePass());
- } else {
- double load_replacement_threshold = 0.9;
- if (pass_args.find_first_not_of(".0123456789") == std::string::npos) {
- load_replacement_threshold = atof(pass_args.c_str());
- }
- if (load_replacement_threshold >= 0) {
- RegisterPass(CreateReduceLoadSizePass(load_replacement_threshold));
- } else {
- Error(consumer(), nullptr, {},
- "--reduce-load-size must have no arguments or a non-negative "
- "double argument");
- return false;
- }
- }
- } else if (pass_name == "redundancy-elimination") {
- RegisterPass(CreateRedundancyEliminationPass());
- } else if (pass_name == "private-to-local") {
- RegisterPass(CreatePrivateToLocalPass());
- } else if (pass_name == "remove-duplicates") {
- RegisterPass(CreateRemoveDuplicatesPass());
- } else if (pass_name == "workaround-1209") {
- RegisterPass(CreateWorkaround1209Pass());
- } else if (pass_name == "replace-invalid-opcode") {
- RegisterPass(CreateReplaceInvalidOpcodePass());
- } else if (pass_name == "convert-relaxed-to-half") {
- RegisterPass(CreateConvertRelaxedToHalfPass());
- } else if (pass_name == "relax-float-ops") {
- RegisterPass(CreateRelaxFloatOpsPass());
- } else if (pass_name == "simplify-instructions") {
- RegisterPass(CreateSimplificationPass());
- } else if (pass_name == "ssa-rewrite") {
- RegisterPass(CreateSSARewritePass());
- } else if (pass_name == "copy-propagate-arrays") {
- RegisterPass(CreateCopyPropagateArraysPass());
- } else if (pass_name == "loop-fission") {
- int register_threshold_to_split =
- (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
- if (register_threshold_to_split > 0) {
- RegisterPass(CreateLoopFissionPass(
- static_cast<size_t>(register_threshold_to_split)));
- } else {
- Error(consumer(), nullptr, {},
- "--loop-fission must have a positive integer argument");
- return false;
- }
- } else if (pass_name == "loop-fusion") {
- int max_registers_per_loop =
- (pass_args.size() > 0) ? atoi(pass_args.c_str()) : -1;
- if (max_registers_per_loop > 0) {
- RegisterPass(
- CreateLoopFusionPass(static_cast<size_t>(max_registers_per_loop)));
- } else {
- Error(consumer(), nullptr, {},
- "--loop-fusion must have a positive integer argument");
- return false;
- }
- } else if (pass_name == "loop-unroll") {
- RegisterPass(CreateLoopUnrollPass(true));
- } else if (pass_name == "upgrade-memory-model") {
- RegisterPass(CreateUpgradeMemoryModelPass());
- } else if (pass_name == "vector-dce") {
- RegisterPass(CreateVectorDCEPass());
- } else if (pass_name == "loop-unroll-partial") {
- int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
- if (factor > 0) {
- RegisterPass(CreateLoopUnrollPass(false, factor));
- } else {
- Error(consumer(), nullptr, {},
- "--loop-unroll-partial must have a positive integer argument");
- return false;
- }
- } else if (pass_name == "loop-peeling") {
- RegisterPass(CreateLoopPeelingPass());
- } else if (pass_name == "loop-peeling-threshold") {
- int factor = (pass_args.size() > 0) ? atoi(pass_args.c_str()) : 0;
- if (factor > 0) {
- opt::LoopPeelingPass::SetLoopPeelingThreshold(factor);
- } else {
- Error(consumer(), nullptr, {},
- "--loop-peeling-threshold must have a positive integer argument");
- return false;
- }
- } else if (pass_name == "ccp") {
- RegisterPass(CreateCCPPass());
- } else if (pass_name == "code-sink") {
- RegisterPass(CreateCodeSinkingPass());
- } else if (pass_name == "fix-storage-class") {
- RegisterPass(CreateFixStorageClassPass());
- } else if (pass_name == "O") {
- RegisterPerformancePasses(preserve_interface);
- } else if (pass_name == "Os") {
- RegisterSizePasses(preserve_interface);
- } else if (pass_name == "legalize-hlsl") {
- RegisterLegalizationPasses(preserve_interface);
- } else if (pass_name == "remove-unused-interface-variables") {
- RegisterPass(CreateRemoveUnusedInterfaceVariablesPass());
- } else if (pass_name == "graphics-robust-access") {
- RegisterPass(CreateGraphicsRobustAccessPass());
- } else if (pass_name == "wrap-opkill") {
- RegisterPass(CreateWrapOpKillPass());
- } else if (pass_name == "amd-ext-to-khr") {
- RegisterPass(CreateAmdExtToKhrPass());
- } else if (pass_name == "interpolate-fixup") {
- RegisterPass(CreateInterpolateFixupPass());
- } else if (pass_name == "remove-dont-inline") {
- RegisterPass(CreateRemoveDontInlinePass());
- } else if (pass_name == "eliminate-dead-input-components") {
- RegisterPass(CreateEliminateDeadInputComponentsSafePass());
- } else if (pass_name == "fix-func-call-param") {
- RegisterPass(CreateFixFuncCallArgumentsPass());
- } else if (pass_name == "convert-to-sampled-image") {
- if (pass_args.size() > 0) {
- auto descriptor_set_binding_pairs =
- opt::ConvertToSampledImagePass::ParseDescriptorSetBindingPairsString(
- pass_args.c_str());
- if (!descriptor_set_binding_pairs) {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --convert-to-sampled-image: %s",
- pass_args.c_str());
- return false;
- }
- RegisterPass(CreateConvertToSampledImagePass(
- std::move(*descriptor_set_binding_pairs)));
- } else {
- Errorf(consumer(), nullptr, {},
- "Invalid pairs of descriptor set and binding '%s'. Expected a "
- "string of <descriptor set>:<binding> pairs.",
- pass_args.c_str());
- return false;
- }
- } else if (pass_name == "struct-packing") {
- if (pass_args.size() == 0) {
- Error(consumer(), nullptr, {},
- "--struct-packing requires a name:rule argument.");
- return false;
- }
- auto separator_pos = pass_args.find(':');
- if (separator_pos == std::string::npos || separator_pos == 0 ||
- separator_pos + 1 == pass_args.size()) {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --struct-packing: %s", pass_args.c_str());
- return false;
- }
- const std::string struct_name = pass_args.substr(0, separator_pos);
- const std::string rule_name = pass_args.substr(separator_pos + 1);
- RegisterPass(
- CreateStructPackingPass(struct_name.c_str(), rule_name.c_str()));
- } else if (pass_name == "switch-descriptorset") {
- if (pass_args.size() == 0) {
- Error(consumer(), nullptr, {},
- "--switch-descriptorset requires a from:to argument.");
- return false;
- }
- uint32_t from_set = 0, to_set = 0;
- const char* start = pass_args.data();
- const char* end = pass_args.data() + pass_args.size();
- auto result = std::from_chars(start, end, from_set);
- if (result.ec != std::errc()) {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --switch-descriptorset: %s",
- pass_args.c_str());
- return false;
- }
- start = result.ptr;
- if (start[0] != ':') {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --switch-descriptorset: %s",
- pass_args.c_str());
- return false;
- }
- start++;
- result = std::from_chars(start, end, to_set);
- if (result.ec != std::errc() || result.ptr != end) {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --switch-descriptorset: %s",
- pass_args.c_str());
- return false;
- }
- RegisterPass(CreateSwitchDescriptorSetPass(from_set, to_set));
- } else if (pass_name == "modify-maximal-reconvergence") {
- if (pass_args.size() == 0) {
- Error(consumer(), nullptr, {},
- "--modify-maximal-reconvergence requires an argument");
- return false;
- }
- if (pass_args == "add") {
- RegisterPass(CreateModifyMaximalReconvergencePass(true));
- } else if (pass_args == "remove") {
- RegisterPass(CreateModifyMaximalReconvergencePass(false));
- } else {
- Errorf(consumer(), nullptr, {},
- "Invalid argument for --modify-maximal-reconvergence: %s (must be "
- "'add' or 'remove')",
- pass_args.c_str());
- return false;
- }
- } else if (pass_name == "trim-capabilities") {
- RegisterPass(CreateTrimCapabilitiesPass());
- } else if (pass_name == "split-combined-image-sampler") {
- RegisterPass(CreateSplitCombinedImageSamplerPass());
- } else if (pass_name == "resolve-binding-conflicts") {
- RegisterPass(CreateResolveBindingConflictsPass());
- } else {
- Errorf(consumer(), nullptr, {},
- "Unknown flag '--%s'. Use --help for a list of valid flags",
- pass_name.c_str());
- return false;
- }
- return true;
- }
- void Optimizer::SetTargetEnv(const spv_target_env env) {
- impl_->target_env = env;
- }
- bool Optimizer::Run(const uint32_t* original_binary,
- const size_t original_binary_size,
- std::vector<uint32_t>* optimized_binary) const {
- return Run(original_binary, original_binary_size, optimized_binary,
- OptimizerOptions());
- }
- bool Optimizer::Run(const uint32_t* original_binary,
- const size_t original_binary_size,
- std::vector<uint32_t>* optimized_binary,
- const ValidatorOptions& validator_options,
- bool skip_validation) const {
- OptimizerOptions opt_options;
- opt_options.set_run_validator(!skip_validation);
- opt_options.set_validator_options(validator_options);
- return Run(original_binary, original_binary_size, optimized_binary,
- opt_options);
- }
- bool Optimizer::Run(const uint32_t* original_binary,
- const size_t original_binary_size,
- std::vector<uint32_t>* optimized_binary,
- const spv_optimizer_options opt_options) const {
- spvtools::SpirvTools tools(impl_->target_env);
- tools.SetMessageConsumer(impl_->pass_manager.consumer());
- if (opt_options->run_validator_ &&
- !tools.Validate(original_binary, original_binary_size,
- &opt_options->val_options_)) {
- return false;
- }
- std::unique_ptr<opt::IRContext> context = BuildModule(
- impl_->target_env, consumer(), original_binary, original_binary_size);
- if (context == nullptr) return false;
- context->set_max_id_bound(opt_options->max_id_bound_);
- context->set_preserve_bindings(opt_options->preserve_bindings_);
- context->set_preserve_spec_constants(opt_options->preserve_spec_constants_);
- impl_->pass_manager.SetValidatorOptions(&opt_options->val_options_);
- impl_->pass_manager.SetTargetEnv(impl_->target_env);
- auto status = impl_->pass_manager.Run(context.get());
- if (status == opt::Pass::Status::Failure) {
- return false;
- }
- #ifndef NDEBUG
- // We do not keep the result id of DebugScope in struct DebugScope.
- // Instead, we assign random ids for them, which results in integrity
- // check failures. In addition, propagating the OpLine/OpNoLine to preserve
- // the debug information through transformations results in integrity
- // check failures. We want to skip the integrity check when the module
- // contains DebugScope or OpLine/OpNoLine instructions.
- if (status == opt::Pass::Status::SuccessWithoutChange &&
- !context->module()->ContainsDebugInfo()) {
- std::vector<uint32_t> optimized_binary_with_nop;
- context->module()->ToBinary(&optimized_binary_with_nop,
- /* skip_nop = */ false);
- assert(optimized_binary_with_nop.size() == original_binary_size &&
- "Binary size unexpectedly changed despite the optimizer saying "
- "there was no change");
- // Compare the magic number to make sure the binaries were encoded in the
- // endianness. If not, the contents of the binaries will be different, so
- // do not check the contents.
- if (optimized_binary_with_nop[0] == original_binary[0]) {
- assert(memcmp(optimized_binary_with_nop.data(), original_binary,
- original_binary_size) == 0 &&
- "Binary content unexpectedly changed despite the optimizer saying "
- "there was no change");
- }
- }
- #endif // !NDEBUG
- // Note that |original_binary| and |optimized_binary| may share the same
- // buffer and the below will invalidate |original_binary|.
- optimized_binary->clear();
- context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
- return true;
- }
- Optimizer& Optimizer::SetPrintAll(std::ostream* out) {
- impl_->pass_manager.SetPrintAll(out);
- return *this;
- }
- Optimizer& Optimizer::SetTimeReport(std::ostream* out) {
- impl_->pass_manager.SetTimeReport(out);
- return *this;
- }
- Optimizer& Optimizer::SetValidateAfterAll(bool validate) {
- impl_->pass_manager.SetValidateAfterAll(validate);
- return *this;
- }
- Optimizer::PassToken CreateNullPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
- }
- Optimizer::PassToken CreateStripDebugInfoPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::StripDebugInfoPass>());
- }
- Optimizer::PassToken CreateStripReflectInfoPass() {
- return CreateStripNonSemanticInfoPass();
- }
- Optimizer::PassToken CreateStripNonSemanticInfoPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::StripNonSemanticInfoPass>());
- }
- Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadFunctionsPass>());
- }
- Optimizer::PassToken CreateEliminateDeadMembersPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadMembersPass>());
- }
- Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
- const std::unordered_map<uint32_t, std::string>& id_value_map) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
- }
- Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
- const std::unordered_map<uint32_t, std::vector<uint32_t>>& id_value_map) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
- }
- Optimizer::PassToken CreateFlattenDecorationPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::FlattenDecorationPass>());
- }
- Optimizer::PassToken CreateFreezeSpecConstantValuePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::FreezeSpecConstantValuePass>());
- }
- Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::FoldSpecConstantOpAndCompositePass>());
- }
- Optimizer::PassToken CreateUnifyConstantPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::UnifyConstantPass>());
- }
- Optimizer::PassToken CreateEliminateDeadConstantPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadConstantPass>());
- }
- Optimizer::PassToken CreateDeadVariableEliminationPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::DeadVariableElimination>());
- }
- Optimizer::PassToken CreateStrengthReductionPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::StrengthReductionPass>());
- }
- Optimizer::PassToken CreateBlockMergePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::BlockMergePass>());
- }
- Optimizer::PassToken CreateInlineExhaustivePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::InlineExhaustivePass>());
- }
- Optimizer::PassToken CreateInlineOpaquePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::InlineOpaquePass>());
- }
- Optimizer::PassToken CreateLocalAccessChainConvertPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LocalAccessChainConvertPass>());
- }
- Optimizer::PassToken CreateLocalSingleBlockLoadStoreElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LocalSingleBlockLoadStoreElimPass>());
- }
- Optimizer::PassToken CreateLocalSingleStoreElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LocalSingleStoreElimPass>());
- }
- Optimizer::PassToken CreateInsertExtractElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SimplificationPass>());
- }
- Optimizer::PassToken CreateDeadInsertElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::DeadInsertElimPass>());
- }
- Optimizer::PassToken CreateDeadBranchElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::DeadBranchElimPass>());
- }
- Optimizer::PassToken CreateLocalMultiStoreElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SSARewritePass>());
- }
- Optimizer::PassToken CreateAggressiveDCEPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::AggressiveDCEPass>(false, false));
- }
- Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::AggressiveDCEPass>(preserve_interface, false));
- }
- Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface,
- bool remove_outputs) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::AggressiveDCEPass>(preserve_interface, remove_outputs));
- }
- Optimizer::PassToken CreateRemoveUnusedInterfaceVariablesPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::RemoveUnusedInterfaceVariablesPass>());
- }
- Optimizer::PassToken CreatePropagateLineInfoPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
- }
- Optimizer::PassToken CreateRedundantLineInfoElimPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
- }
- Optimizer::PassToken CreateCompactIdsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::CompactIdsPass>());
- }
- Optimizer::PassToken CreateMergeReturnPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::MergeReturnPass>());
- }
- std::vector<const char*> Optimizer::GetPassNames() const {
- std::vector<const char*> v;
- for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); i++) {
- v.push_back(impl_->pass_manager.GetPass(i)->name());
- }
- return v;
- }
- Optimizer::PassToken CreateCFGCleanupPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::CFGCleanupPass>());
- }
- Optimizer::PassToken CreateLocalRedundancyEliminationPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LocalRedundancyEliminationPass>());
- }
- Optimizer::PassToken CreateLoopFissionPass(size_t threshold) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LoopFissionPass>(threshold));
- }
- Optimizer::PassToken CreateLoopFusionPass(size_t max_registers_per_loop) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LoopFusionPass>(max_registers_per_loop));
- }
- Optimizer::PassToken CreateLoopInvariantCodeMotionPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::LICMPass>());
- }
- Optimizer::PassToken CreateLoopPeelingPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LoopPeelingPass>());
- }
- Optimizer::PassToken CreateLoopUnswitchPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LoopUnswitchPass>());
- }
- Optimizer::PassToken CreateRedundancyEliminationPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::RedundancyEliminationPass>());
- }
- Optimizer::PassToken CreateRemoveDuplicatesPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::RemoveDuplicatesPass>());
- }
- Optimizer::PassToken CreateScalarReplacementPass(uint32_t size_limit) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ScalarReplacementPass>(size_limit));
- }
- Optimizer::PassToken CreatePrivateToLocalPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::PrivateToLocalPass>());
- }
- Optimizer::PassToken CreateCCPPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::CCPPass>());
- }
- Optimizer::PassToken CreateWorkaround1209Pass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::Workaround1209>());
- }
- Optimizer::PassToken CreateIfConversionPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::IfConversion>());
- }
- Optimizer::PassToken CreateReplaceInvalidOpcodePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ReplaceInvalidOpcodePass>());
- }
- Optimizer::PassToken CreateSimplificationPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SimplificationPass>());
- }
- Optimizer::PassToken CreateLoopUnrollPass(bool fully_unroll, int factor) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::LoopUnroller>(fully_unroll, factor));
- }
- Optimizer::PassToken CreateSSARewritePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SSARewritePass>());
- }
- Optimizer::PassToken CreateCopyPropagateArraysPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::CopyPropagateArrays>());
- }
- Optimizer::PassToken CreateVectorDCEPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::VectorDCE>());
- }
- Optimizer::PassToken CreateReduceLoadSizePass(
- double load_replacement_threshold) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ReduceLoadSize>(load_replacement_threshold));
- }
- Optimizer::PassToken CreateCombineAccessChainsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::CombineAccessChains>());
- }
- Optimizer::PassToken CreateUpgradeMemoryModelPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::UpgradeMemoryModel>());
- }
- Optimizer::PassToken CreateConvertRelaxedToHalfPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ConvertToHalfPass>());
- }
- Optimizer::PassToken CreateRelaxFloatOpsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::RelaxFloatOpsPass>());
- }
- Optimizer::PassToken CreateCodeSinkingPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::CodeSinkingPass>());
- }
- Optimizer::PassToken CreateFixStorageClassPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::FixStorageClass>());
- }
- Optimizer::PassToken CreateGraphicsRobustAccessPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::GraphicsRobustAccessPass>());
- }
- Optimizer::PassToken CreateReplaceDescArrayAccessUsingVarIndexPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ReplaceDescArrayAccessUsingVarIndex>());
- }
- Optimizer::PassToken CreateSpreadVolatileSemanticsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SpreadVolatileSemantics>());
- }
- Optimizer::PassToken CreateDescriptorScalarReplacementPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::DescriptorScalarReplacement>(
- /* flatten_composites= */ true, /* flatten_arrays= */ true));
- }
- Optimizer::PassToken CreateDescriptorCompositeScalarReplacementPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::DescriptorScalarReplacement>(
- /* flatten_composites= */ true, /* flatten_arrays= */ false));
- }
- Optimizer::PassToken CreateDescriptorArrayScalarReplacementPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::DescriptorScalarReplacement>(
- /* flatten_composites= */ false, /* flatten_arrays= */ true));
- }
- Optimizer::PassToken CreateWrapOpKillPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::WrapOpKill>());
- }
- Optimizer::PassToken CreateAmdExtToKhrPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::AmdExtensionToKhrPass>());
- }
- Optimizer::PassToken CreateInterpolateFixupPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::InterpFixupPass>());
- }
- Optimizer::PassToken CreateEliminateDeadInputComponentsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadIOComponentsPass>(spv::StorageClass::Input,
- /* safe_mode */ false));
- }
- Optimizer::PassToken CreateEliminateDeadOutputComponentsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadIOComponentsPass>(spv::StorageClass::Output,
- /* safe_mode */ false));
- }
- Optimizer::PassToken CreateEliminateDeadInputComponentsSafePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadIOComponentsPass>(spv::StorageClass::Input,
- /* safe_mode */ true));
- }
- Optimizer::PassToken CreateAnalyzeLiveInputPass(
- std::unordered_set<uint32_t>* live_locs,
- std::unordered_set<uint32_t>* live_builtins) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::AnalyzeLiveInputPass>(live_locs, live_builtins));
- }
- Optimizer::PassToken CreateEliminateDeadOutputStoresPass(
- std::unordered_set<uint32_t>* live_locs,
- std::unordered_set<uint32_t>* live_builtins) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::EliminateDeadOutputStoresPass>(live_locs, live_builtins));
- }
- Optimizer::PassToken CreateConvertToSampledImagePass(
- const std::vector<opt::DescriptorSetAndBinding>&
- descriptor_set_binding_pairs) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ConvertToSampledImagePass>(descriptor_set_binding_pairs));
- }
- Optimizer::PassToken CreateInterfaceVariableScalarReplacementPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::InterfaceVariableScalarReplacement>());
- }
- Optimizer::PassToken CreateRemoveDontInlinePass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::RemoveDontInline>());
- }
- Optimizer::PassToken CreateFixFuncCallArgumentsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::FixFuncCallArgumentsPass>());
- }
- Optimizer::PassToken CreateTrimCapabilitiesPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::TrimCapabilitiesPass>());
- }
- Optimizer::PassToken CreateStructPackingPass(const char* structToPack,
- const char* packingRule) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::StructPackingPass>(
- structToPack,
- opt::StructPackingPass::ParsePackingRuleFromString(packingRule)));
- }
- Optimizer::PassToken CreateSwitchDescriptorSetPass(uint32_t from, uint32_t to) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SwitchDescriptorSetPass>(from, to));
- }
- Optimizer::PassToken CreateInvocationInterlockPlacementPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::InvocationInterlockPlacementPass>());
- }
- Optimizer::PassToken CreateModifyMaximalReconvergencePass(bool add) {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ModifyMaximalReconvergence>(add));
- }
- Optimizer::PassToken CreateOpExtInstWithForwardReferenceFixupPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::OpExtInstWithForwardReferenceFixupPass>());
- }
- Optimizer::PassToken CreateSplitCombinedImageSamplerPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::SplitCombinedImageSamplerPass>());
- }
- Optimizer::PassToken CreateResolveBindingConflictsPass() {
- return MakeUnique<Optimizer::PassToken::Impl>(
- MakeUnique<opt::ResolveBindingConflictsPass>());
- }
- } // namespace spvtools
- extern "C" {
- SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env) {
- return reinterpret_cast<spv_optimizer_t*>(new spvtools::Optimizer(env));
- }
- SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer) {
- delete reinterpret_cast<spvtools::Optimizer*>(optimizer);
- }
- SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
- spv_optimizer_t* optimizer, spv_message_consumer consumer) {
- reinterpret_cast<spvtools::Optimizer*>(optimizer)->
- SetMessageConsumer(
- [consumer](spv_message_level_t level, const char* source,
- const spv_position_t& position, const char* message) {
- return consumer(level, source, &position, message);
- });
- }
- SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
- spv_optimizer_t* optimizer) {
- reinterpret_cast<spvtools::Optimizer*>(optimizer)->
- RegisterLegalizationPasses();
- }
- SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
- spv_optimizer_t* optimizer) {
- reinterpret_cast<spvtools::Optimizer*>(optimizer)->
- RegisterPerformancePasses();
- }
- SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
- spv_optimizer_t* optimizer) {
- reinterpret_cast<spvtools::Optimizer*>(optimizer)->RegisterSizePasses();
- }
- SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
- spv_optimizer_t* optimizer, const char* flag)
- {
- return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
- RegisterPassFromFlag(flag);
- }
- SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
- spv_optimizer_t* optimizer, const char** flags, const size_t flag_count) {
- std::vector<std::string> opt_flags =
- spvtools::GetVectorOfStrings(flags, flag_count);
- return reinterpret_cast<spvtools::Optimizer*>(optimizer)
- ->RegisterPassesFromFlags(opt_flags, false);
- }
- SPIRV_TOOLS_EXPORT bool
- spvOptimizerRegisterPassesFromFlagsWhilePreservingTheInterface(
- spv_optimizer_t* optimizer, const char** flags, const size_t flag_count) {
- std::vector<std::string> opt_flags =
- spvtools::GetVectorOfStrings(flags, flag_count);
- return reinterpret_cast<spvtools::Optimizer*>(optimizer)
- ->RegisterPassesFromFlags(opt_flags, true);
- }
- SPIRV_TOOLS_EXPORT
- spv_result_t spvOptimizerRun(spv_optimizer_t* optimizer,
- const uint32_t* binary,
- const size_t word_count,
- spv_binary* optimized_binary,
- const spv_optimizer_options options) {
- std::vector<uint32_t> optimized;
- if (!reinterpret_cast<spvtools::Optimizer*>(optimizer)->
- Run(binary, word_count, &optimized, options)) {
- return SPV_ERROR_INTERNAL;
- }
- auto result_binary = new spv_binary_t();
- if (!result_binary) {
- *optimized_binary = nullptr;
- return SPV_ERROR_OUT_OF_MEMORY;
- }
- result_binary->code = new uint32_t[optimized.size()];
- if (!result_binary->code) {
- delete result_binary;
- *optimized_binary = nullptr;
- return SPV_ERROR_OUT_OF_MEMORY;
- }
- result_binary->wordCount = optimized.size();
- memcpy(result_binary->code, optimized.data(),
- optimized.size() * sizeof(uint32_t));
- *optimized_binary = result_binary;
- return SPV_SUCCESS;
- }
- } // extern "C"
|