2016-09-12 18:11:46 +00:00
|
|
|
// 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.
|
|
|
|
|
2016-09-16 20:12:04 +00:00
|
|
|
#include "spirv-tools/optimizer.hpp"
|
2016-09-12 18:11:46 +00:00
|
|
|
|
|
|
|
#include "build_module.h"
|
|
|
|
#include "make_unique.h"
|
|
|
|
#include "pass_manager.h"
|
|
|
|
#include "passes.h"
|
2018-05-07 16:31:03 +00:00
|
|
|
#include "reduce_load_size.h"
|
2018-02-02 16:55:05 +00:00
|
|
|
#include "simplification_pass.h"
|
2016-09-12 18:11:46 +00:00
|
|
|
|
|
|
|
namespace spvtools {
|
|
|
|
|
|
|
|
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)) {}
|
2018-05-22 21:31:26 +00:00
|
|
|
|
|
|
|
Optimizer::PassToken::PassToken(std::unique_ptr<opt::Pass>&& pass)
|
|
|
|
: impl_(MakeUnique<Optimizer::PassToken::Impl>(std::move(pass))) {}
|
|
|
|
|
2016-09-12 18:11:46 +00:00
|
|
|
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() {}
|
|
|
|
|
|
|
|
const spv_target_env target_env; // Target environment.
|
|
|
|
opt::PassManager pass_manager; // Internal implementation pass manager.
|
|
|
|
};
|
|
|
|
|
|
|
|
Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {}
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
Optimizer& Optimizer::RegisterPass(PassToken&& p) {
|
|
|
|
// Change to use the pass manager's consumer.
|
|
|
|
p.impl_->pass->SetMessageConsumer(impl_->pass_manager.consumer());
|
|
|
|
impl_->pass_manager.AddPass(std::move(p.impl_->pass));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-12-19 20:08:54 +00:00
|
|
|
// 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.
|
2017-11-17 21:50:43 +00:00
|
|
|
Optimizer& Optimizer::RegisterLegalizationPasses() {
|
2017-12-19 20:08:54 +00:00
|
|
|
return
|
2018-03-06 16:20:28 +00:00
|
|
|
// 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())
|
2017-12-19 20:08:54 +00:00
|
|
|
// Make private variable function scope
|
|
|
|
.RegisterPass(CreateEliminateDeadFunctionsPass())
|
|
|
|
.RegisterPass(CreatePrivateToLocalPass())
|
2018-02-22 17:23:21 +00:00
|
|
|
// Propagate the value stored to the loads in very simple cases.
|
|
|
|
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
|
|
|
.RegisterPass(CreateLocalSingleStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2017-12-19 20:08:54 +00:00
|
|
|
// Split up aggragates so they are easier to deal with.
|
2018-04-16 13:58:00 +00:00
|
|
|
.RegisterPass(CreateScalarReplacementPass(0))
|
2017-12-19 20:08:54 +00:00
|
|
|
// Remove loads and stores so everything is in intermediate values.
|
|
|
|
// Takes care of copy propagation of non-members.
|
2018-01-03 19:03:07 +00:00
|
|
|
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
|
|
|
.RegisterPass(CreateLocalSingleStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2017-12-19 20:08:54 +00:00
|
|
|
.RegisterPass(CreateLocalMultiStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-02-15 17:14:39 +00:00
|
|
|
// Propagate constants to get as many constant conditions on branches
|
|
|
|
// as possible.
|
|
|
|
.RegisterPass(CreateCCPPass())
|
|
|
|
.RegisterPass(CreateDeadBranchElimPass())
|
2017-12-19 20:08:54 +00:00
|
|
|
// Copy propagate members. Cleans up code sequences generated by
|
2018-02-15 17:14:39 +00:00
|
|
|
// scalar replacement. Also important for removing OpPhi nodes.
|
2018-02-02 16:55:05 +00:00
|
|
|
.RegisterPass(CreateSimplificationPass())
|
2018-03-21 03:33:24 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
|
|
|
.RegisterPass(CreateCopyPropagateArraysPass())
|
2017-12-19 20:08:54 +00:00
|
|
|
// May need loop unrolling here see
|
|
|
|
// https://github.com/Microsoft/DirectXShaderCompiler/pull/930
|
2018-01-27 00:05:33 +00:00
|
|
|
// Get rid of unused code that contain traces of illegal code
|
|
|
|
// or unused references to unbound external objects
|
2018-04-23 15:13:07 +00:00
|
|
|
.RegisterPass(CreateVectorDCEPass())
|
2018-04-23 15:17:07 +00:00
|
|
|
.RegisterPass(CreateDeadInsertElimPass())
|
2018-05-07 16:31:03 +00:00
|
|
|
.RegisterPass(CreateReduceLoadSizePass())
|
2018-01-12 20:15:57 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass());
|
2017-11-17 21:50:43 +00:00
|
|
|
}
|
|
|
|
|
2017-08-30 18:19:22 +00:00
|
|
|
Optimizer& Optimizer::RegisterPerformancePasses() {
|
2018-06-29 14:21:56 +00:00
|
|
|
return RegisterPass(CreateMergeReturnPass())
|
2017-11-08 21:22:10 +00:00
|
|
|
.RegisterPass(CreateInlineExhaustivePass())
|
2017-12-18 17:13:10 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-07-04 19:26:32 +00:00
|
|
|
.RegisterPass(CreatePrivateToLocalPass())
|
2018-02-22 17:23:21 +00:00
|
|
|
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
|
|
|
.RegisterPass(CreateLocalSingleStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2017-11-30 22:03:06 +00:00
|
|
|
.RegisterPass(CreateScalarReplacementPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateLocalAccessChainConvertPass())
|
|
|
|
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
|
|
|
.RegisterPass(CreateLocalSingleStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-01-03 17:38:21 +00:00
|
|
|
.RegisterPass(CreateLocalMultiStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-01-08 16:56:57 +00:00
|
|
|
.RegisterPass(CreateCCPPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-01-31 15:40:33 +00:00
|
|
|
.RegisterPass(CreateRedundancyEliminationPass())
|
2018-05-18 15:15:38 +00:00
|
|
|
.RegisterPass(CreateSimplificationPass())
|
2018-04-23 15:13:07 +00:00
|
|
|
.RegisterPass(CreateVectorDCEPass())
|
2018-04-23 15:17:07 +00:00
|
|
|
.RegisterPass(CreateDeadInsertElimPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateDeadBranchElimPass())
|
2018-02-15 17:14:39 +00:00
|
|
|
.RegisterPass(CreateSimplificationPass())
|
2018-01-16 16:15:06 +00:00
|
|
|
.RegisterPass(CreateIfConversionPass())
|
2018-03-28 16:27:19 +00:00
|
|
|
.RegisterPass(CreateCopyPropagateArraysPass())
|
2018-05-07 16:31:03 +00:00
|
|
|
.RegisterPass(CreateReduceLoadSizePass())
|
2018-01-16 16:15:06 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateBlockMergePass())
|
2017-12-04 17:29:51 +00:00
|
|
|
.RegisterPass(CreateRedundancyEliminationPass())
|
2018-01-31 15:40:33 +00:00
|
|
|
.RegisterPass(CreateDeadBranchElimPass())
|
|
|
|
.RegisterPass(CreateBlockMergePass())
|
2018-05-18 15:15:38 +00:00
|
|
|
.RegisterPass(CreateSimplificationPass());
|
2018-01-31 15:40:33 +00:00
|
|
|
// Currently exposing driver bugs resulting in crashes (#946)
|
|
|
|
// .RegisterPass(CreateCommonUniformElimPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Optimizer& Optimizer::RegisterSizePasses() {
|
2018-06-29 14:21:56 +00:00
|
|
|
return RegisterPass(CreateMergeReturnPass())
|
2017-11-08 21:22:10 +00:00
|
|
|
.RegisterPass(CreateInlineExhaustivePass())
|
2017-12-18 17:13:10 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-07-04 19:26:32 +00:00
|
|
|
.RegisterPass(CreatePrivateToLocalPass())
|
2018-01-31 01:13:30 +00:00
|
|
|
.RegisterPass(CreateScalarReplacementPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateLocalAccessChainConvertPass())
|
|
|
|
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
|
|
|
.RegisterPass(CreateLocalSingleStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-05-18 15:15:38 +00:00
|
|
|
.RegisterPass(CreateSimplificationPass())
|
2018-01-27 00:05:33 +00:00
|
|
|
.RegisterPass(CreateDeadInsertElimPass())
|
2018-01-03 17:38:21 +00:00
|
|
|
.RegisterPass(CreateLocalMultiStoreElimPass())
|
2018-02-22 21:05:37 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2018-01-08 16:56:57 +00:00
|
|
|
.RegisterPass(CreateCCPPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
|
|
|
.RegisterPass(CreateDeadBranchElimPass())
|
2018-01-16 16:15:06 +00:00
|
|
|
.RegisterPass(CreateIfConversionPass())
|
|
|
|
.RegisterPass(CreateAggressiveDCEPass())
|
2017-08-30 18:19:22 +00:00
|
|
|
.RegisterPass(CreateBlockMergePass())
|
2018-05-18 15:15:38 +00:00
|
|
|
.RegisterPass(CreateSimplificationPass())
|
2018-01-27 00:05:33 +00:00
|
|
|
.RegisterPass(CreateDeadInsertElimPass())
|
2017-12-04 17:29:51 +00:00
|
|
|
.RegisterPass(CreateRedundancyEliminationPass())
|
2017-12-05 16:39:25 +00:00
|
|
|
.RegisterPass(CreateCFGCleanupPass())
|
2017-11-07 00:00:44 +00:00
|
|
|
// Currently exposing driver bugs resulting in crashes (#946)
|
|
|
|
// .RegisterPass(CreateCommonUniformElimPass())
|
2017-12-18 17:13:10 +00:00
|
|
|
.RegisterPass(CreateAggressiveDCEPass());
|
2017-08-30 18:19:22 +00:00
|
|
|
}
|
|
|
|
|
2016-09-12 18:11:46 +00:00
|
|
|
bool Optimizer::Run(const uint32_t* original_binary,
|
|
|
|
const size_t original_binary_size,
|
|
|
|
std::vector<uint32_t>* optimized_binary) const {
|
2018-07-09 15:32:29 +00:00
|
|
|
std::unique_ptr<opt::IRContext> context =
|
2016-09-12 18:11:46 +00:00
|
|
|
BuildModule(impl_->target_env, impl_->pass_manager.consumer(),
|
|
|
|
original_binary, original_binary_size);
|
2017-11-14 19:11:50 +00:00
|
|
|
if (context == nullptr) return false;
|
2016-09-12 18:11:46 +00:00
|
|
|
|
2017-11-14 19:11:50 +00:00
|
|
|
auto status = impl_->pass_manager.Run(context.get());
|
2017-04-02 06:17:41 +00:00
|
|
|
if (status == opt::Pass::Status::SuccessWithChange ||
|
|
|
|
(status == opt::Pass::Status::SuccessWithoutChange &&
|
|
|
|
(optimized_binary->data() != original_binary ||
|
|
|
|
optimized_binary->size() != original_binary_size))) {
|
2016-09-12 18:11:46 +00:00
|
|
|
optimized_binary->clear();
|
2017-11-14 19:11:50 +00:00
|
|
|
context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
|
2016-09-12 18:11:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return status != opt::Pass::Status::Failure;
|
|
|
|
}
|
|
|
|
|
2018-01-04 17:59:50 +00:00
|
|
|
Optimizer& Optimizer::SetPrintAll(std::ostream* out) {
|
|
|
|
impl_->pass_manager.SetPrintAll(out);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-03-07 14:25:51 +00:00
|
|
|
Optimizer& Optimizer::SetTimeReport(std::ostream* out) {
|
|
|
|
impl_->pass_manager.SetTimeReport(out);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-09-12 18:11:46 +00:00
|
|
|
Optimizer::PassToken CreateNullPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
|
|
|
|
}
|
|
|
|
|
|
|
|
Optimizer::PassToken CreateStripDebugInfoPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::StripDebugInfoPass>());
|
|
|
|
}
|
|
|
|
|
2018-03-09 21:08:57 +00:00
|
|
|
Optimizer::PassToken CreateStripReflectInfoPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::StripReflectInfoPass>());
|
|
|
|
}
|
|
|
|
|
2017-09-19 14:12:13 +00:00
|
|
|
Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::EliminateDeadFunctionsPass>());
|
|
|
|
}
|
|
|
|
|
2016-09-12 18:11:46 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-04-19 22:10:59 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2017-04-01 20:10:16 +00:00
|
|
|
Optimizer::PassToken CreateFlattenDecorationPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::FlattenDecorationPass>());
|
|
|
|
}
|
|
|
|
|
2016-09-12 18:11:46 +00:00
|
|
|
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>());
|
|
|
|
}
|
|
|
|
|
2017-10-20 16:17:41 +00:00
|
|
|
Optimizer::PassToken CreateDeadVariableEliminationPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::DeadVariableElimination>());
|
|
|
|
}
|
|
|
|
|
2017-09-08 16:08:03 +00:00
|
|
|
Optimizer::PassToken CreateStrengthReductionPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::StrengthReductionPass>());
|
|
|
|
}
|
|
|
|
|
2017-06-07 21:28:53 +00:00
|
|
|
Optimizer::PassToken CreateBlockMergePass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::BlockMergePass>());
|
|
|
|
}
|
|
|
|
|
2017-08-01 23:20:13 +00:00
|
|
|
Optimizer::PassToken CreateInlineExhaustivePass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::InlineExhaustivePass>());
|
2016-11-10 17:11:50 +00:00
|
|
|
}
|
2017-08-30 18:19:22 +00:00
|
|
|
|
2017-08-15 23:58:28 +00:00
|
|
|
Optimizer::PassToken CreateInlineOpaquePass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::InlineOpaquePass>());
|
|
|
|
}
|
2017-08-30 18:19:22 +00:00
|
|
|
|
2017-05-12 23:27:21 +00:00
|
|
|
Optimizer::PassToken CreateLocalAccessChainConvertPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LocalAccessChainConvertPass>());
|
|
|
|
}
|
2017-08-30 18:19:22 +00:00
|
|
|
|
2017-05-18 20:51:55 +00:00
|
|
|
Optimizer::PassToken CreateLocalSingleBlockLoadStoreElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LocalSingleBlockLoadStoreElimPass>());
|
|
|
|
}
|
2017-05-12 23:27:21 +00:00
|
|
|
|
2017-05-19 23:31:28 +00:00
|
|
|
Optimizer::PassToken CreateLocalSingleStoreElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LocalSingleStoreElimPass>());
|
|
|
|
}
|
|
|
|
|
2017-05-26 16:33:11 +00:00
|
|
|
Optimizer::PassToken CreateInsertExtractElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
2018-05-31 03:50:07 +00:00
|
|
|
MakeUnique<opt::SimplificationPass>());
|
2017-05-26 16:33:11 +00:00
|
|
|
}
|
|
|
|
|
2018-01-27 00:05:33 +00:00
|
|
|
Optimizer::PassToken CreateDeadInsertElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::DeadInsertElimPass>());
|
|
|
|
}
|
|
|
|
|
2017-06-02 19:23:20 +00:00
|
|
|
Optimizer::PassToken CreateDeadBranchElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::DeadBranchElimPass>());
|
|
|
|
}
|
|
|
|
|
2017-06-16 21:37:31 +00:00
|
|
|
Optimizer::PassToken CreateLocalMultiStoreElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LocalMultiStoreElimPass>());
|
|
|
|
}
|
|
|
|
|
2017-06-08 16:37:21 +00:00
|
|
|
Optimizer::PassToken CreateAggressiveDCEPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::AggressiveDCEPass>());
|
|
|
|
}
|
|
|
|
|
2017-07-03 23:23:04 +00:00
|
|
|
Optimizer::PassToken CreateCommonUniformElimPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::CommonUniformElimPass>());
|
|
|
|
}
|
|
|
|
|
2017-04-11 19:11:04 +00:00
|
|
|
Optimizer::PassToken CreateCompactIdsPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::CompactIdsPass>());
|
|
|
|
}
|
|
|
|
|
2017-11-08 21:22:10 +00:00
|
|
|
Optimizer::PassToken CreateMergeReturnPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::MergeReturnPass>());
|
|
|
|
}
|
|
|
|
|
2017-08-30 18:19:22 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-10-19 19:22:02 +00:00
|
|
|
Optimizer::PassToken CreateCFGCleanupPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::CFGCleanupPass>());
|
|
|
|
}
|
|
|
|
|
2017-11-11 01:26:55 +00:00
|
|
|
Optimizer::PassToken CreateLocalRedundancyEliminationPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LocalRedundancyEliminationPass>());
|
|
|
|
}
|
2017-12-04 17:29:51 +00:00
|
|
|
|
2018-04-23 20:01:12 +00:00
|
|
|
Optimizer::PassToken CreateLoopFissionPass(size_t threshold) {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LoopFissionPass>(threshold));
|
|
|
|
}
|
|
|
|
|
2018-04-20 14:14:45 +00:00
|
|
|
Optimizer::PassToken CreateLoopFusionPass(size_t max_registers_per_loop) {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LoopFusionPass>(max_registers_per_loop));
|
|
|
|
}
|
|
|
|
|
2018-01-29 10:39:55 +00:00
|
|
|
Optimizer::PassToken CreateLoopInvariantCodeMotionPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::LICMPass>());
|
|
|
|
}
|
|
|
|
|
2018-03-29 11:22:42 +00:00
|
|
|
Optimizer::PassToken CreateLoopPeelingPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LoopPeelingPass>());
|
|
|
|
}
|
|
|
|
|
2018-02-12 21:42:15 +00:00
|
|
|
Optimizer::PassToken CreateLoopUnswitchPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::LoopUnswitchPass>());
|
|
|
|
}
|
|
|
|
|
2017-12-04 17:29:51 +00:00
|
|
|
Optimizer::PassToken CreateRedundancyEliminationPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::RedundancyEliminationPass>());
|
|
|
|
}
|
2017-11-30 22:03:06 +00:00
|
|
|
|
2017-12-08 20:33:19 +00:00
|
|
|
Optimizer::PassToken CreateRemoveDuplicatesPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::RemoveDuplicatesPass>());
|
|
|
|
}
|
|
|
|
|
2018-04-16 13:58:00 +00:00
|
|
|
Optimizer::PassToken CreateScalarReplacementPass(uint32_t size_limit) {
|
2017-11-30 22:03:06 +00:00
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
2018-04-16 13:58:00 +00:00
|
|
|
MakeUnique<opt::ScalarReplacementPass>(size_limit));
|
2017-11-30 22:03:06 +00:00
|
|
|
}
|
2017-12-11 18:10:24 +00:00
|
|
|
|
|
|
|
Optimizer::PassToken CreatePrivateToLocalPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::PrivateToLocalPass>());
|
|
|
|
}
|
2017-12-05 16:39:25 +00:00
|
|
|
|
|
|
|
Optimizer::PassToken CreateCCPPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::CCPPass>());
|
|
|
|
}
|
|
|
|
|
2018-01-17 19:57:37 +00:00
|
|
|
Optimizer::PassToken CreateWorkaround1209Pass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::Workaround1209>());
|
|
|
|
}
|
|
|
|
|
2018-01-16 16:15:06 +00:00
|
|
|
Optimizer::PassToken CreateIfConversionPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::IfConversion>());
|
|
|
|
}
|
|
|
|
|
2018-01-30 16:24:03 +00:00
|
|
|
Optimizer::PassToken CreateReplaceInvalidOpcodePass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::ReplaceInvalidOpcodePass>());
|
|
|
|
}
|
2018-02-02 16:55:05 +00:00
|
|
|
|
|
|
|
Optimizer::PassToken CreateSimplificationPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::SimplificationPass>());
|
|
|
|
}
|
2018-02-14 17:03:12 +00:00
|
|
|
|
2018-02-27 11:50:08 +00:00
|
|
|
Optimizer::PassToken CreateLoopUnrollPass(bool fully_unroll, int factor) {
|
2018-02-14 17:03:12 +00:00
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
2018-02-27 11:50:08 +00:00
|
|
|
MakeUnique<opt::LoopUnroller>(fully_unroll, factor));
|
2018-02-14 17:03:12 +00:00
|
|
|
}
|
SSA rewrite pass.
This pass replaces the load/store elimination passes. It implements the
SSA re-writing algorithm proposed in
Simple and Efficient Construction of Static Single Assignment Form.
Braun M., Buchwald S., Hack S., Leißa R., Mallon C., Zwinkau A. (2013)
In: Jhala R., De Bosschere K. (eds)
Compiler Construction. CC 2013.
Lecture Notes in Computer Science, vol 7791.
Springer, Berlin, Heidelberg
https://link.springer.com/chapter/10.1007/978-3-642-37051-9_6
In contrast to common eager algorithms based on dominance and dominance
frontier information, this algorithm works backwards from load operations.
When a target variable is loaded, it queries the variable's reaching
definition. If the reaching definition is unknown at the current location,
it searches backwards in the CFG, inserting Phi instructions at join points
in the CFG along the way until it finds the desired store instruction.
The algorithm avoids repeated lookups using memoization.
For reducible CFGs, which are a superset of the structured CFGs in SPIRV,
this algorithm is proven to produce minimal SSA. That is, it inserts the
minimal number of Phi instructions required to ensure the SSA property, but
some Phi instructions may be dead
(https://en.wikipedia.org/wiki/Static_single_assignment_form).
2018-02-22 21:18:29 +00:00
|
|
|
|
|
|
|
Optimizer::PassToken CreateSSARewritePass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::SSARewritePass>());
|
|
|
|
}
|
|
|
|
|
2018-03-21 03:33:24 +00:00
|
|
|
Optimizer::PassToken CreateCopyPropagateArraysPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::CopyPropagateArrays>());
|
|
|
|
}
|
|
|
|
|
2018-04-23 15:13:07 +00:00
|
|
|
Optimizer::PassToken CreateVectorDCEPass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::VectorDCE>());
|
|
|
|
}
|
|
|
|
|
2018-05-07 16:31:03 +00:00
|
|
|
Optimizer::PassToken CreateReduceLoadSizePass() {
|
|
|
|
return MakeUnique<Optimizer::PassToken::Impl>(
|
|
|
|
MakeUnique<opt::ReduceLoadSize>());
|
|
|
|
}
|
2016-09-12 18:11:46 +00:00
|
|
|
} // namespace spvtools
|