spirv-reduce: Support reducing a specific function (#3774)
Motivated by integrating spirv-reduce into spirv-fuzz, so that an added function can be made smaller during shrinking, this adds support in spirv-reduce for asking reduction to be restricted to the instructions of a single specified function.
This commit is contained in:
Родитель
de7d57984d
Коммит
5dcb576b69
|
@ -674,6 +674,13 @@ SPIRV_TOOLS_EXPORT void spvReducerOptionsSetStepLimit(
|
||||||
SPIRV_TOOLS_EXPORT void spvReducerOptionsSetFailOnValidationError(
|
SPIRV_TOOLS_EXPORT void spvReducerOptionsSetFailOnValidationError(
|
||||||
spv_reducer_options options, bool fail_on_validation_error);
|
spv_reducer_options options, bool fail_on_validation_error);
|
||||||
|
|
||||||
|
// Sets the function that the reducer should target. If set to zero the reducer
|
||||||
|
// will target all functions as well as parts of the module that lie outside
|
||||||
|
// functions. Otherwise the reducer will restrict reduction to the function
|
||||||
|
// with result id |target_function|, which is required to exist.
|
||||||
|
SPIRV_TOOLS_EXPORT void spvReducerOptionsSetTargetFunction(
|
||||||
|
spv_reducer_options options, uint32_t target_function);
|
||||||
|
|
||||||
// Creates a fuzzer options object with default options. Returns a valid
|
// Creates a fuzzer options object with default options. Returns a valid
|
||||||
// options object. The object remains valid until it is passed into
|
// options object. The object remains valid until it is passed into
|
||||||
// |spvFuzzerOptionsDestroy|.
|
// |spvFuzzerOptionsDestroy|.
|
||||||
|
|
|
@ -202,6 +202,11 @@ class ReducerOptions {
|
||||||
fail_on_validation_error);
|
fail_on_validation_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See spvReducerOptionsSetTargetFunction.
|
||||||
|
void set_target_function(uint32_t target_function) {
|
||||||
|
spvReducerOptionsSetTargetFunction(options_, target_function);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spv_reducer_options options_;
|
spv_reducer_options options_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,7 @@ set(SPIRV_TOOLS_REDUCE_SOURCES
|
||||||
operand_to_dominating_id_reduction_opportunity_finder.cpp
|
operand_to_dominating_id_reduction_opportunity_finder.cpp
|
||||||
reducer.cpp
|
reducer.cpp
|
||||||
reduction_opportunity.cpp
|
reduction_opportunity.cpp
|
||||||
|
reduction_opportunity_finder.cpp
|
||||||
reduction_pass.cpp
|
reduction_pass.cpp
|
||||||
reduction_util.cpp
|
reduction_util.cpp
|
||||||
remove_block_reduction_opportunity.cpp
|
remove_block_reduction_opportunity.cpp
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
ConditionalBranchToSimpleConditionalBranchOpportunityFinder::
|
ConditionalBranchToSimpleConditionalBranchOpportunityFinder::
|
||||||
GetAvailableOpportunities(opt::IRContext* context) const {
|
GetAvailableOpportunities(opt::IRContext* context,
|
||||||
|
uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
// Find the opportunities for redirecting all false targets before the
|
// Find the opportunities for redirecting all false targets before the
|
||||||
|
@ -31,10 +32,10 @@ ConditionalBranchToSimpleConditionalBranchOpportunityFinder::
|
||||||
// reducer is improved by avoiding contiguous opportunities that disable one
|
// reducer is improved by avoiding contiguous opportunities that disable one
|
||||||
// another.
|
// another.
|
||||||
for (bool redirect_to_true : {true, false}) {
|
for (bool redirect_to_true : {true, false}) {
|
||||||
// Consider every function.
|
// Consider every relevant function.
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
// Consider every block in the function.
|
// Consider every block in the function.
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
// The terminator must be SpvOpBranchConditional.
|
// The terminator must be SpvOpBranchConditional.
|
||||||
opt::Instruction* terminator = block.terminator();
|
opt::Instruction* terminator = block.terminator();
|
||||||
if (terminator->opcode() != SpvOpBranchConditional) {
|
if (terminator->opcode() != SpvOpBranchConditional) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ConditionalBranchToSimpleConditionalBranchOpportunityFinder
|
||||||
: public ReductionOpportunityFinder {
|
: public ReductionOpportunityFinder {
|
||||||
public:
|
public:
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const override;
|
opt::IRContext* context, uint32_t target_function) const override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,17 +25,17 @@ std::string MergeBlocksReductionOpportunityFinder::GetName() const {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
MergeBlocksReductionOpportunityFinder::GetAvailableOpportunities(
|
MergeBlocksReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
// Consider every block in every function.
|
// Consider every block in every function.
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
// See whether it is possible to merge this block with its successor.
|
// See whether it is possible to merge this block with its successor.
|
||||||
if (opt::blockmergeutil::CanMergeWithSuccessor(context, &block)) {
|
if (opt::blockmergeutil::CanMergeWithSuccessor(context, &block)) {
|
||||||
// It is, so record an opportunity to do this.
|
// It is, so record an opportunity to do this.
|
||||||
result.push_back(spvtools::MakeUnique<MergeBlocksReductionOpportunity>(
|
result.push_back(spvtools::MakeUnique<MergeBlocksReductionOpportunity>(
|
||||||
context, &function, &block));
|
context, function, &block));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ class MergeBlocksReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
OperandToConstReductionOpportunityFinder::GetAvailableOpportunities(
|
OperandToConstReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
assert(result.empty());
|
assert(result.empty());
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ OperandToConstReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
// contiguous blocks of opportunities early on, and we want to avoid having a
|
// contiguous blocks of opportunities early on, and we want to avoid having a
|
||||||
// large block of incompatible opportunities if possible.
|
// large block of incompatible opportunities if possible.
|
||||||
for (const auto& constant : context->GetConstants()) {
|
for (const auto& constant : context->GetConstants()) {
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
for (auto& inst : block) {
|
for (auto& inst : block) {
|
||||||
// We iterate through the operands using an explicit index (rather
|
// We iterate through the operands using an explicit index (rather
|
||||||
// than using a lambda) so that we use said index in the construction
|
// than using a lambda) so that we use said index in the construction
|
||||||
|
|
|
@ -33,7 +33,7 @@ class OperandToConstReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
OperandToDominatingIdReductionOpportunityFinder::GetAvailableOpportunities(
|
OperandToDominatingIdReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
// Go through every instruction in every block, considering it as a potential
|
// Go through every instruction in every block, considering it as a potential
|
||||||
|
@ -38,15 +38,15 @@ OperandToDominatingIdReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
// to prioritise replacing e with its smallest sub-expressions; generalising
|
// to prioritise replacing e with its smallest sub-expressions; generalising
|
||||||
// this idea to dominating ids this roughly corresponds to more distant
|
// this idea to dominating ids this roughly corresponds to more distant
|
||||||
// dominators.
|
// dominators.
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto dominating_block = function.begin();
|
for (auto dominating_block = function->begin();
|
||||||
dominating_block != function.end(); ++dominating_block) {
|
dominating_block != function->end(); ++dominating_block) {
|
||||||
for (auto& dominating_inst : *dominating_block) {
|
for (auto& dominating_inst : *dominating_block) {
|
||||||
if (dominating_inst.HasResultId() && dominating_inst.type_id()) {
|
if (dominating_inst.HasResultId() && dominating_inst.type_id()) {
|
||||||
// Consider replacing any operand with matching type in a dominated
|
// Consider replacing any operand with matching type in a dominated
|
||||||
// instruction with the id generated by this instruction.
|
// instruction with the id generated by this instruction.
|
||||||
GetOpportunitiesForDominatingInst(
|
GetOpportunitiesForDominatingInst(
|
||||||
&result, &dominating_inst, dominating_block, &function, context);
|
&result, &dominating_inst, dominating_block, function, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class OperandToDominatingIdReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetOpportunitiesForDominatingInst(
|
void GetOpportunitiesForDominatingInst(
|
||||||
|
|
|
@ -22,11 +22,11 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
OperandToUndefReductionOpportunityFinder::GetAvailableOpportunities(
|
OperandToUndefReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
for (auto& inst : block) {
|
for (auto& inst : block) {
|
||||||
// Skip instructions that result in a pointer type.
|
// Skip instructions that result in a pointer type.
|
||||||
auto type_id = inst.type_id();
|
auto type_id = inst.type_id();
|
||||||
|
|
|
@ -32,7 +32,7 @@ class OperandToUndefReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -183,7 +183,8 @@ Reducer::ReductionResultStatus Reducer::RunPasses(
|
||||||
consumer_(SPV_MSG_INFO, nullptr, {},
|
consumer_(SPV_MSG_INFO, nullptr, {},
|
||||||
("Trying pass " + pass->GetName() + ".").c_str());
|
("Trying pass " + pass->GetName() + ".").c_str());
|
||||||
do {
|
do {
|
||||||
auto maybe_result = pass->TryApplyReduction(*current_binary);
|
auto maybe_result =
|
||||||
|
pass->TryApplyReduction(*current_binary, options->target_function);
|
||||||
if (maybe_result.empty()) {
|
if (maybe_result.empty()) {
|
||||||
// For this round, the pass has no more opportunities (chunks) to
|
// For this round, the pass has no more opportunities (chunks) to
|
||||||
// apply, so move on to the next pass.
|
// apply, so move on to the next pass.
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) 2020 Google LLC
|
||||||
|
//
|
||||||
|
// 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 "reduction_opportunity_finder.h"
|
||||||
|
|
||||||
|
namespace spvtools {
|
||||||
|
namespace reduce {
|
||||||
|
|
||||||
|
std::vector<opt::Function*> ReductionOpportunityFinder::GetTargetFunctions(
|
||||||
|
opt::IRContext* ir_context, uint32_t target_function) {
|
||||||
|
std::vector<opt::Function*> result;
|
||||||
|
for (auto& function : *ir_context->module()) {
|
||||||
|
if (!target_function || function.result_id() == target_function) {
|
||||||
|
result.push_back(&function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert((!target_function || !result.empty()) &&
|
||||||
|
"Requested target function must exist.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace reduce
|
||||||
|
} // namespace spvtools
|
|
@ -15,6 +15,8 @@
|
||||||
#ifndef SOURCE_REDUCE_REDUCTION_OPPORTUNITY_FINDER_H_
|
#ifndef SOURCE_REDUCE_REDUCTION_OPPORTUNITY_FINDER_H_
|
||||||
#define SOURCE_REDUCE_REDUCTION_OPPORTUNITY_FINDER_H_
|
#define SOURCE_REDUCE_REDUCTION_OPPORTUNITY_FINDER_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "source/opt/ir_context.h"
|
#include "source/opt/ir_context.h"
|
||||||
#include "source/reduce/reduction_opportunity.h"
|
#include "source/reduce/reduction_opportunity.h"
|
||||||
|
|
||||||
|
@ -29,12 +31,25 @@ class ReductionOpportunityFinder {
|
||||||
virtual ~ReductionOpportunityFinder() = default;
|
virtual ~ReductionOpportunityFinder() = default;
|
||||||
|
|
||||||
// Finds and returns the reduction opportunities relevant to this pass that
|
// Finds and returns the reduction opportunities relevant to this pass that
|
||||||
// could be applied to the given SPIR-V module.
|
// could be applied to SPIR-V module |context|.
|
||||||
|
//
|
||||||
|
// If |target_function| is non-zero then the available opportunities will be
|
||||||
|
// restricted to only those opportunities that modify the function with result
|
||||||
|
// id |target_function|.
|
||||||
virtual std::vector<std::unique_ptr<ReductionOpportunity>>
|
virtual std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
GetAvailableOpportunities(opt::IRContext* context) const = 0;
|
GetAvailableOpportunities(opt::IRContext* context,
|
||||||
|
uint32_t target_function) const = 0;
|
||||||
|
|
||||||
// Provides a name for the finder.
|
// Provides a name for the finder.
|
||||||
virtual std::string GetName() const = 0;
|
virtual std::string GetName() const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Requires that |target_function| is zero or the id of a function in
|
||||||
|
// |ir_context|. If |target_function| is zero, returns all the functions in
|
||||||
|
// |ir_context|. Otherwise, returns the function with id |target_function|.
|
||||||
|
// This allows fuzzer passes to restrict attention to a single function.
|
||||||
|
static std::vector<opt::Function*> GetTargetFunctions(
|
||||||
|
opt::IRContext* ir_context, uint32_t target_function);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace reduce
|
} // namespace reduce
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace spvtools {
|
||||||
namespace reduce {
|
namespace reduce {
|
||||||
|
|
||||||
std::vector<uint32_t> ReductionPass::TryApplyReduction(
|
std::vector<uint32_t> ReductionPass::TryApplyReduction(
|
||||||
const std::vector<uint32_t>& binary) {
|
const std::vector<uint32_t>& binary, uint32_t target_function) {
|
||||||
// We represent modules as binaries because (a) attempts at reduction need to
|
// We represent modules as binaries because (a) attempts at reduction need to
|
||||||
// end up in binary form to be passed on to SPIR-V-consuming tools, and (b)
|
// end up in binary form to be passed on to SPIR-V-consuming tools, and (b)
|
||||||
// when we apply a reduction step we need to do it on a fresh version of the
|
// when we apply a reduction step we need to do it on a fresh version of the
|
||||||
|
@ -34,7 +34,7 @@ std::vector<uint32_t> ReductionPass::TryApplyReduction(
|
||||||
assert(context);
|
assert(context);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> opportunities =
|
std::vector<std::unique_ptr<ReductionOpportunity>> opportunities =
|
||||||
finder_->GetAvailableOpportunities(context.get());
|
finder_->GetAvailableOpportunities(context.get(), target_function);
|
||||||
|
|
||||||
// There is no point in having a granularity larger than the number of
|
// There is no point in having a granularity larger than the number of
|
||||||
// opportunities, so reduce the granularity in this case.
|
// opportunities, so reduce the granularity in this case.
|
||||||
|
|
|
@ -49,7 +49,12 @@ class ReductionPass {
|
||||||
// Returns an empty vector if there are no more chunks left to apply; in this
|
// Returns an empty vector if there are no more chunks left to apply; in this
|
||||||
// case, the index will be reset and the granularity lowered for the next
|
// case, the index will be reset and the granularity lowered for the next
|
||||||
// round.
|
// round.
|
||||||
std::vector<uint32_t> TryApplyReduction(const std::vector<uint32_t>& binary);
|
//
|
||||||
|
// If |target_function| is non-zero, only reduction opportunities that
|
||||||
|
// simplify the internals of the function with result id |target_function|
|
||||||
|
// will be applied.
|
||||||
|
std::vector<uint32_t> TryApplyReduction(const std::vector<uint32_t>& binary,
|
||||||
|
uint32_t target_function);
|
||||||
|
|
||||||
// Notifies the reduction pass whether the binary returned from
|
// Notifies the reduction pass whether the binary returned from
|
||||||
// TryApplyReduction is interesting, so that the next call to
|
// TryApplyReduction is interesting, so that the next call to
|
||||||
|
|
|
@ -25,15 +25,15 @@ std::string RemoveBlockReductionOpportunityFinder::GetName() const {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
RemoveBlockReductionOpportunityFinder::GetAvailableOpportunities(
|
RemoveBlockReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
// Consider every block in every function.
|
// Consider every block in every relevant function.
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto bi = function.begin(); bi != function.end(); ++bi) {
|
for (auto bi = function->begin(); bi != function->end(); ++bi) {
|
||||||
if (IsBlockValidOpportunity(context, function, bi)) {
|
if (IsBlockValidOpportunity(context, function, &bi)) {
|
||||||
result.push_back(spvtools::MakeUnique<RemoveBlockReductionOpportunity>(
|
result.push_back(
|
||||||
&function, &*bi));
|
MakeUnique<RemoveBlockReductionOpportunity>(function, &*bi));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,22 +41,22 @@ RemoveBlockReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveBlockReductionOpportunityFinder::IsBlockValidOpportunity(
|
bool RemoveBlockReductionOpportunityFinder::IsBlockValidOpportunity(
|
||||||
opt::IRContext* context, opt::Function& function,
|
opt::IRContext* context, opt::Function* function,
|
||||||
opt::Function::iterator& bi) {
|
opt::Function::iterator* bi) {
|
||||||
assert(bi != function.end() && "Block iterator was out of bounds");
|
assert(*bi != function->end() && "Block iterator was out of bounds");
|
||||||
|
|
||||||
// Don't remove first block; we don't want to end up with no blocks.
|
// Don't remove first block; we don't want to end up with no blocks.
|
||||||
if (bi == function.begin()) {
|
if (*bi == function->begin()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't remove blocks with references.
|
// Don't remove blocks with references.
|
||||||
if (context->get_def_use_mgr()->NumUsers(bi->id()) > 0) {
|
if (context->get_def_use_mgr()->NumUsers((*bi)->id()) > 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't remove blocks whose instructions have outside references.
|
// Don't remove blocks whose instructions have outside references.
|
||||||
if (!BlockInstructionsHaveNoOutsideReferences(context, bi)) {
|
if (!BlockInstructionsHaveNoOutsideReferences(context, *bi)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,14 +34,14 @@ class RemoveBlockReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns true if the block |bi| in function |function| is a valid
|
// Returns true if the block |bi| in function |function| is a valid
|
||||||
// opportunity according to various restrictions.
|
// opportunity according to various restrictions.
|
||||||
static bool IsBlockValidOpportunity(opt::IRContext* context,
|
static bool IsBlockValidOpportunity(opt::IRContext* context,
|
||||||
opt::Function& function,
|
opt::Function* function,
|
||||||
opt::Function::iterator& bi);
|
opt::Function::iterator* bi);
|
||||||
|
|
||||||
// Returns true if the instructions (definitions) in block |bi| have no
|
// Returns true if the instructions (definitions) in block |bi| have no
|
||||||
// references, except for references from inside the block itself.
|
// references, except for references from inside the block itself.
|
||||||
|
|
|
@ -21,7 +21,14 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
RemoveFunctionReductionOpportunityFinder::GetAvailableOpportunities(
|
RemoveFunctionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
|
if (target_function) {
|
||||||
|
// If we are targeting a specific function then we are only interested in
|
||||||
|
// opportunities that simplify the internals of that function; removing
|
||||||
|
// whole functions does not fit the bill.
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
// Consider each function.
|
// Consider each function.
|
||||||
for (auto& function : *context->module()) {
|
for (auto& function : *context->module()) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ class RemoveFunctionReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,11 +30,11 @@ std::string RemoveSelectionReductionOpportunityFinder::GetName() const {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
RemoveSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
// Get all loop merge and continue blocks so we can check for these later.
|
// Get all loop merge and continue blocks so we can check for these later.
|
||||||
std::unordered_set<uint32_t> merge_and_continue_blocks_from_loops;
|
std::unordered_set<uint32_t> merge_and_continue_blocks_from_loops;
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
if (auto merge_instruction = block.GetMergeInst()) {
|
if (auto merge_instruction = block.GetMergeInst()) {
|
||||||
if (merge_instruction->opcode() == SpvOpLoopMerge) {
|
if (merge_instruction->opcode() == SpvOpLoopMerge) {
|
||||||
uint32_t merge_block_id =
|
uint32_t merge_block_id =
|
||||||
|
|
|
@ -33,7 +33,7 @@ class RemoveSelectionReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
// Returns true if the OpSelectionMerge instruction |merge_instruction| in
|
// Returns true if the OpSelectionMerge instruction |merge_instruction| in
|
||||||
// block |header_block| can be removed.
|
// block |header_block| can be removed.
|
||||||
|
|
|
@ -28,61 +28,72 @@ RemoveUnusedInstructionReductionOpportunityFinder::
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
RemoveUnusedInstructionReductionOpportunityFinder::GetAvailableOpportunities(
|
RemoveUnusedInstructionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
for (auto& inst : context->module()->debugs1()) {
|
if (!target_function) {
|
||||||
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
// We are not restricting reduction to a specific function, so we consider
|
||||||
continue;
|
// unused instructions defined outside functions.
|
||||||
|
|
||||||
|
for (auto& inst : context->module()->debugs1()) {
|
||||||
|
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& inst : context->module()->debugs2()) {
|
||||||
|
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& inst : context->module()->debugs3()) {
|
||||||
|
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& inst : context->module()->ext_inst_debuginfo()) {
|
||||||
|
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& inst : context->module()->types_values()) {
|
||||||
|
if (!remove_constants_and_undefs_ &&
|
||||||
|
spvOpcodeIsConstantOrUndef(inst.opcode())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!OnlyReferencedByIntimateDecorationOrEntryPointInterface(context,
|
||||||
|
inst)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& inst : context->module()->annotations()) {
|
||||||
|
if (context->get_def_use_mgr()->NumUsers(&inst) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!IsIndependentlyRemovableDecoration(inst)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push_back(
|
||||||
|
MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||||
}
|
}
|
||||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& inst : context->module()->debugs2()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
for (auto& block : *function) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst : context->module()->debugs3()) {
|
|
||||||
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst : context->module()->ext_inst_debuginfo()) {
|
|
||||||
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst : context->module()->types_values()) {
|
|
||||||
if (!remove_constants_and_undefs_ &&
|
|
||||||
spvOpcodeIsConstantOrUndef(inst.opcode())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!OnlyReferencedByIntimateDecorationOrEntryPointInterface(context,
|
|
||||||
inst)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& inst : context->module()->annotations()) {
|
|
||||||
if (context->get_def_use_mgr()->NumUsers(&inst) > 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!IsIndependentlyRemovableDecoration(inst)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& function : *context->module()) {
|
|
||||||
for (auto& block : function) {
|
|
||||||
for (auto& inst : block) {
|
for (auto& inst : block) {
|
||||||
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -38,7 +38,7 @@ class RemoveUnusedInstructionReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns true if and only if the only uses of |inst| are by decorations that
|
// Returns true if and only if the only uses of |inst| are by decorations that
|
||||||
|
|
|
@ -24,7 +24,14 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
RemoveUnusedStructMemberReductionOpportunityFinder::GetAvailableOpportunities(
|
RemoveUnusedStructMemberReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
|
if (target_function) {
|
||||||
|
// Removing an unused struct member is a global change, as struct types are
|
||||||
|
// global. We thus do not consider such opportunities if we are targeting
|
||||||
|
// a specific function.
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
// We track those struct members that are never accessed. We do this by
|
// We track those struct members that are never accessed. We do this by
|
||||||
|
|
|
@ -32,7 +32,7 @@ class RemoveUnusedStructMemberReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// A helper method to update |unused_members_to_structs| by removing from it
|
// A helper method to update |unused_members_to_structs| by removing from it
|
||||||
|
|
|
@ -22,13 +22,13 @@ namespace reduce {
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
SimpleConditionalBranchToBranchOpportunityFinder::GetAvailableOpportunities(
|
SimpleConditionalBranchToBranchOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
// Consider every function.
|
// Consider every function.
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
// Consider every block in the function.
|
// Consider every block in the function.
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
// The terminator must be SpvOpBranchConditional.
|
// The terminator must be SpvOpBranchConditional.
|
||||||
opt::Instruction* terminator = block.terminator();
|
opt::Instruction* terminator = block.terminator();
|
||||||
if (terminator->opcode() != SpvOpBranchConditional) {
|
if (terminator->opcode() != SpvOpBranchConditional) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ class SimpleConditionalBranchToBranchOpportunityFinder
|
||||||
: public ReductionOpportunityFinder {
|
: public ReductionOpportunityFinder {
|
||||||
public:
|
public:
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const override;
|
opt::IRContext* context, uint32_t target_function) const override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,12 +26,12 @@ const uint32_t kContinueNodeIndex = 1;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>>
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
||||||
StructuredLoopToSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
StructuredLoopToSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const {
|
opt::IRContext* context, uint32_t target_function) const {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
|
|
||||||
std::set<uint32_t> merge_block_ids;
|
std::set<uint32_t> merge_block_ids;
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
auto merge_block_id = block.MergeBlockIdIfAny();
|
auto merge_block_id = block.MergeBlockIdIfAny();
|
||||||
if (merge_block_id) {
|
if (merge_block_id) {
|
||||||
merge_block_ids.insert(merge_block_id);
|
merge_block_ids.insert(merge_block_id);
|
||||||
|
@ -40,8 +40,8 @@ StructuredLoopToSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consider each loop construct header in the module.
|
// Consider each loop construct header in the module.
|
||||||
for (auto& function : *context->module()) {
|
for (auto* function : GetTargetFunctions(context, target_function)) {
|
||||||
for (auto& block : function) {
|
for (auto& block : *function) {
|
||||||
auto loop_merge_inst = block.GetLoopMergeInst();
|
auto loop_merge_inst = block.GetLoopMergeInst();
|
||||||
if (!loop_merge_inst) {
|
if (!loop_merge_inst) {
|
||||||
// This is not a loop construct header.
|
// This is not a loop construct header.
|
||||||
|
@ -69,8 +69,8 @@ StructuredLoopToSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
// so we cautiously do not consider applying a transformation.
|
// so we cautiously do not consider applying a transformation.
|
||||||
auto merge_block_id =
|
auto merge_block_id =
|
||||||
loop_merge_inst->GetSingleWordInOperand(kMergeNodeIndex);
|
loop_merge_inst->GetSingleWordInOperand(kMergeNodeIndex);
|
||||||
if (!context->GetDominatorAnalysis(&function)->Dominates(
|
if (!context->GetDominatorAnalysis(function)->Dominates(block.id(),
|
||||||
block.id(), merge_block_id)) {
|
merge_block_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ StructuredLoopToSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
// construct header. If not (e.g. because the loop contains OpReturn,
|
// construct header. If not (e.g. because the loop contains OpReturn,
|
||||||
// OpKill or OpUnreachable), we cautiously do not consider applying
|
// OpKill or OpUnreachable), we cautiously do not consider applying
|
||||||
// a transformation.
|
// a transformation.
|
||||||
if (!context->GetPostDominatorAnalysis(&function)->Dominates(
|
if (!context->GetPostDominatorAnalysis(function)->Dominates(
|
||||||
merge_block_id, block.id())) {
|
merge_block_id, block.id())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ StructuredLoopToSelectionReductionOpportunityFinder::GetAvailableOpportunities(
|
||||||
// opportunity to do so.
|
// opportunity to do so.
|
||||||
result.push_back(
|
result.push_back(
|
||||||
MakeUnique<StructuredLoopToSelectionReductionOpportunity>(
|
MakeUnique<StructuredLoopToSelectionReductionOpportunity>(
|
||||||
context, &block, &function));
|
context, &block, function));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -46,7 +46,7 @@ class StructuredLoopToSelectionReductionOpportunityFinder
|
||||||
std::string GetName() const final;
|
std::string GetName() const final;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
opt::IRContext* context) const final;
|
opt::IRContext* context, uint32_t target_function) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,9 @@ const uint32_t kDefaultStepLimit = 2500;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
spv_reducer_options_t::spv_reducer_options_t()
|
spv_reducer_options_t::spv_reducer_options_t()
|
||||||
: step_limit(kDefaultStepLimit), fail_on_validation_error(false) {}
|
: step_limit(kDefaultStepLimit),
|
||||||
|
fail_on_validation_error(false),
|
||||||
|
target_function(0) {}
|
||||||
|
|
||||||
SPIRV_TOOLS_EXPORT spv_reducer_options spvReducerOptionsCreate() {
|
SPIRV_TOOLS_EXPORT spv_reducer_options spvReducerOptionsCreate() {
|
||||||
return new spv_reducer_options_t();
|
return new spv_reducer_options_t();
|
||||||
|
@ -42,3 +44,8 @@ SPIRV_TOOLS_EXPORT void spvReducerOptionsSetFailOnValidationError(
|
||||||
spv_reducer_options options, bool fail_on_validation_error) {
|
spv_reducer_options options, bool fail_on_validation_error) {
|
||||||
options->fail_on_validation_error = fail_on_validation_error;
|
options->fail_on_validation_error = fail_on_validation_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPIRV_TOOLS_EXPORT void spvReducerOptionsSetTargetFunction(
|
||||||
|
spv_reducer_options options, uint32_t target_function) {
|
||||||
|
options->target_function = target_function;
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ struct spv_reducer_options_t {
|
||||||
|
|
||||||
// See spvReducerOptionsSetFailOnValidationError.
|
// See spvReducerOptionsSetFailOnValidationError.
|
||||||
bool fail_on_validation_error;
|
bool fail_on_validation_error;
|
||||||
|
|
||||||
|
// See spvReducerOptionsSetTargetFunction.
|
||||||
|
uint32_t target_function;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SOURCE_SPIRV_REDUCER_OPTIONS_H_
|
#endif // SOURCE_SPIRV_REDUCER_OPTIONS_H_
|
||||||
|
|
|
@ -80,7 +80,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, Diamond) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, Diamond) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
|
|
||||||
// Start again, and apply the other op.
|
// Start again, and apply the other op.
|
||||||
|
@ -134,7 +134,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, Diamond) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -225,7 +225,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, AlreadySimplified) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, DontRemoveBackEdge) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, DontRemoveBackEdge) {
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +361,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest,
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest,
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +453,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, BackEdgeUnreachable) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
auto ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -492,7 +492,7 @@ TEST(ConditionalBranchToSimpleConditionalBranchTest, BackEdgeUnreachable) {
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
ops = ConditionalBranchToSimpleConditionalBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ TEST(MergeBlocksReductionPassTest, BasicCheck) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(5, ops.size());
|
ASSERT_EQ(5, ops.size());
|
||||||
|
|
||||||
// Try order 3, 0, 2, 4, 1
|
// Try order 3, 0, 2, 4, 1
|
||||||
|
@ -356,7 +356,7 @@ TEST(MergeBlocksReductionPassTest, Loops) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(11, ops.size());
|
ASSERT_EQ(11, ops.size());
|
||||||
|
|
||||||
for (auto& ri : ops) {
|
for (auto& ri : ops) {
|
||||||
|
@ -474,7 +474,7 @@ TEST(MergeBlocksReductionPassTest, MergeWithOpPhi) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -556,7 +556,7 @@ void MergeBlocksReductionPassTest_LoopReturn_Helper(bool reverse) {
|
||||||
ASSERT_NE(context.get(), nullptr);
|
ASSERT_NE(context.get(), nullptr);
|
||||||
auto opportunities =
|
auto opportunities =
|
||||||
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
// A->B and B->C
|
// A->B and B->C
|
||||||
ASSERT_EQ(opportunities.size(), 2);
|
ASSERT_EQ(opportunities.size(), 2);
|
||||||
|
|
|
@ -101,7 +101,7 @@ TEST(OperandToConstantReductionPassTest, BasicCheck) {
|
||||||
BuildModule(env, consumer, original, kReduceAssembleOption);
|
BuildModule(env, consumer, original, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(17, ops.size());
|
ASSERT_EQ(17, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
ops[0]->TryToApply();
|
ops[0]->TryToApply();
|
||||||
|
@ -151,10 +151,158 @@ TEST(OperandToConstantReductionPassTest, WithCalledFunction) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(OperandToConstantReductionPassTest, TargetSpecificFunction) {
|
||||||
|
std::string shader = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %4 "main"
|
||||||
|
OpExecutionMode %4 OriginUpperLeft
|
||||||
|
OpSource ESSL 320
|
||||||
|
%2 = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %2
|
||||||
|
%6 = OpTypeInt 32 1
|
||||||
|
%7 = OpTypePointer Function %6
|
||||||
|
%8 = OpTypeFunction %6 %7
|
||||||
|
%17 = OpConstant %6 1
|
||||||
|
%20 = OpConstant %6 2
|
||||||
|
%23 = OpConstant %6 0
|
||||||
|
%24 = OpTypeBool
|
||||||
|
%35 = OpConstant %6 3
|
||||||
|
%53 = OpConstant %6 10
|
||||||
|
%4 = OpFunction %2 None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%65 = OpVariable %7 Function
|
||||||
|
%68 = OpVariable %7 Function
|
||||||
|
%73 = OpVariable %7 Function
|
||||||
|
OpStore %65 %35
|
||||||
|
%66 = OpLoad %6 %65
|
||||||
|
%67 = OpIAdd %6 %66 %17
|
||||||
|
OpStore %65 %67
|
||||||
|
%69 = OpLoad %6 %65
|
||||||
|
OpStore %68 %69
|
||||||
|
%70 = OpFunctionCall %6 %13 %68
|
||||||
|
%71 = OpLoad %6 %65
|
||||||
|
%72 = OpIAdd %6 %71 %70
|
||||||
|
OpStore %65 %72
|
||||||
|
%74 = OpLoad %6 %65
|
||||||
|
OpStore %73 %74
|
||||||
|
%75 = OpFunctionCall %6 %10 %73
|
||||||
|
%76 = OpLoad %6 %65
|
||||||
|
%77 = OpIAdd %6 %76 %75
|
||||||
|
OpStore %65 %77
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%10 = OpFunction %6 None %8
|
||||||
|
%9 = OpFunctionParameter %7
|
||||||
|
%11 = OpLabel
|
||||||
|
%15 = OpVariable %7 Function
|
||||||
|
%16 = OpLoad %6 %9
|
||||||
|
%18 = OpIAdd %6 %16 %17
|
||||||
|
OpStore %15 %18
|
||||||
|
%19 = OpLoad %6 %15
|
||||||
|
%21 = OpIAdd %6 %19 %20
|
||||||
|
OpStore %15 %21
|
||||||
|
%22 = OpLoad %6 %15
|
||||||
|
%25 = OpSGreaterThan %24 %22 %23
|
||||||
|
OpSelectionMerge %27 None
|
||||||
|
OpBranchConditional %25 %26 %27
|
||||||
|
%26 = OpLabel
|
||||||
|
%28 = OpLoad %6 %9
|
||||||
|
OpReturnValue %28
|
||||||
|
%27 = OpLabel
|
||||||
|
%30 = OpLoad %6 %9
|
||||||
|
%31 = OpIAdd %6 %30 %17
|
||||||
|
OpReturnValue %31
|
||||||
|
OpFunctionEnd
|
||||||
|
%13 = OpFunction %6 None %8
|
||||||
|
%12 = OpFunctionParameter %7
|
||||||
|
%14 = OpLabel
|
||||||
|
%41 = OpVariable %7 Function
|
||||||
|
%46 = OpVariable %7 Function
|
||||||
|
%55 = OpVariable %7 Function
|
||||||
|
%34 = OpLoad %6 %12
|
||||||
|
%36 = OpIEqual %24 %34 %35
|
||||||
|
OpSelectionMerge %38 None
|
||||||
|
OpBranchConditional %36 %37 %38
|
||||||
|
%37 = OpLabel
|
||||||
|
%39 = OpLoad %6 %12
|
||||||
|
%40 = OpIMul %6 %20 %39
|
||||||
|
OpStore %41 %40
|
||||||
|
%42 = OpFunctionCall %6 %10 %41
|
||||||
|
OpReturnValue %42
|
||||||
|
%38 = OpLabel
|
||||||
|
%44 = OpLoad %6 %12
|
||||||
|
%45 = OpIAdd %6 %44 %17
|
||||||
|
OpStore %12 %45
|
||||||
|
OpStore %46 %23
|
||||||
|
OpBranch %47
|
||||||
|
%47 = OpLabel
|
||||||
|
OpLoopMerge %49 %50 None
|
||||||
|
OpBranch %51
|
||||||
|
%51 = OpLabel
|
||||||
|
%52 = OpLoad %6 %46
|
||||||
|
%54 = OpSLessThan %24 %52 %53
|
||||||
|
OpBranchConditional %54 %48 %49
|
||||||
|
%48 = OpLabel
|
||||||
|
%56 = OpLoad %6 %12
|
||||||
|
OpStore %55 %56
|
||||||
|
%57 = OpFunctionCall %6 %10 %55
|
||||||
|
%58 = OpLoad %6 %12
|
||||||
|
%59 = OpIAdd %6 %58 %57
|
||||||
|
OpStore %12 %59
|
||||||
|
OpBranch %50
|
||||||
|
%50 = OpLabel
|
||||||
|
%60 = OpLoad %6 %46
|
||||||
|
%61 = OpIAdd %6 %60 %17
|
||||||
|
OpStore %46 %61
|
||||||
|
OpBranch %47
|
||||||
|
%49 = OpLabel
|
||||||
|
%62 = OpLoad %6 %12
|
||||||
|
OpReturnValue %62
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
|
const auto consumer = nullptr;
|
||||||
|
const auto context =
|
||||||
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
|
|
||||||
|
// Targeting all functions, there are quite a few opportunities. To avoid
|
||||||
|
// making the test too sensitive, we check that there are more than a number
|
||||||
|
// somewhat lower than the real number.
|
||||||
|
const auto all_ops =
|
||||||
|
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
|
context.get(), 0);
|
||||||
|
ASSERT_TRUE(all_ops.size() > 100);
|
||||||
|
|
||||||
|
// Targeting individual functions, there are fewer opportunities. Again, we
|
||||||
|
// avoid checking against an exact number so that the test is not too
|
||||||
|
// sensitive.
|
||||||
|
const auto ops_for_function_4 =
|
||||||
|
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
|
context.get(), 4);
|
||||||
|
const auto ops_for_function_10 =
|
||||||
|
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
|
context.get(), 10);
|
||||||
|
const auto ops_for_function_13 =
|
||||||
|
OperandToConstReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
|
context.get(), 13);
|
||||||
|
ASSERT_TRUE(ops_for_function_4.size() < 60);
|
||||||
|
ASSERT_TRUE(ops_for_function_10.size() < 50);
|
||||||
|
ASSERT_TRUE(ops_for_function_13.size() < 80);
|
||||||
|
|
||||||
|
// The total number of opportunities should be the sum of the per-function
|
||||||
|
// opportunities.
|
||||||
|
ASSERT_EQ(all_ops.size(), ops_for_function_4.size() +
|
||||||
|
ops_for_function_10.size() +
|
||||||
|
ops_for_function_13.size());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace reduce
|
} // namespace reduce
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
|
@ -56,7 +56,7 @@ TEST(OperandToDominatingIdReductionPassTest, BasicCheck) {
|
||||||
const auto context =
|
const auto context =
|
||||||
BuildModule(env, consumer, original, kReduceAssembleOption);
|
BuildModule(env, consumer, original, kReduceAssembleOption);
|
||||||
const auto ops = OperandToDominatingIdReductionOpportunityFinder()
|
const auto ops = OperandToDominatingIdReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(10, ops.size());
|
ASSERT_EQ(10, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
ops[0]->TryToApply();
|
ops[0]->TryToApply();
|
||||||
|
|
|
@ -167,7 +167,7 @@ TEST(OperandToUndefReductionPassTest, BasicCheck) {
|
||||||
BuildModule(env, consumer, original, kReduceAssembleOption);
|
BuildModule(env, consumer, original, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities(
|
OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(10, ops.size());
|
ASSERT_EQ(10, ops.size());
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ TEST(OperandToUndefReductionPassTest, WithCalledFunction) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities(
|
OperandToUndefReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "source/reduce/reducer.h"
|
#include "source/reduce/reducer.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "source/opt/build_module.h"
|
#include "source/opt/build_module.h"
|
||||||
#include "source/reduce/operand_to_const_reduction_opportunity_finder.h"
|
#include "source/reduce/operand_to_const_reduction_opportunity_finder.h"
|
||||||
#include "source/reduce/remove_unused_instruction_reduction_opportunity_finder.h"
|
#include "source/reduce/remove_unused_instruction_reduction_opportunity_finder.h"
|
||||||
|
@ -23,11 +25,8 @@ namespace spvtools {
|
||||||
namespace reduce {
|
namespace reduce {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using opt::BasicBlock;
|
|
||||||
using opt::IRContext;
|
|
||||||
|
|
||||||
const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3;
|
const spv_target_env kEnv = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const MessageConsumer kMessageConsumer = CLIMessageConsumer;
|
const MessageConsumer kMessageConsumer = NopDiagnostic;
|
||||||
|
|
||||||
// This changes its mind each time IsInteresting is invoked as to whether the
|
// This changes its mind each time IsInteresting is invoked as to whether the
|
||||||
// binary is interesting, until some limit is reached after which the binary is
|
// binary is interesting, until some limit is reached after which the binary is
|
||||||
|
@ -42,7 +41,7 @@ class PingPongInteresting {
|
||||||
always_interesting_after_(always_interesting_after),
|
always_interesting_after_(always_interesting_after),
|
||||||
count_(0) {}
|
count_(0) {}
|
||||||
|
|
||||||
bool IsInteresting(const std::vector<uint32_t>&) {
|
bool IsInteresting() {
|
||||||
bool result;
|
bool result;
|
||||||
if (count_ > always_interesting_after_) {
|
if (count_ > always_interesting_after_) {
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -194,10 +193,10 @@ TEST(ReducerTest, ExprToConstantAndRemoveUnreferenced) {
|
||||||
|
|
||||||
Reducer reducer(kEnv);
|
Reducer reducer(kEnv);
|
||||||
PingPongInteresting ping_pong_interesting(10);
|
PingPongInteresting ping_pong_interesting(10);
|
||||||
reducer.SetMessageConsumer(NopDiagnostic);
|
reducer.SetMessageConsumer(kMessageConsumer);
|
||||||
reducer.SetInterestingnessFunction(
|
reducer.SetInterestingnessFunction(
|
||||||
[&](const std::vector<uint32_t>& binary, uint32_t) -> bool {
|
[&ping_pong_interesting](const std::vector<uint32_t>&, uint32_t) -> bool {
|
||||||
return ping_pong_interesting.IsInteresting(binary);
|
return ping_pong_interesting.IsInteresting();
|
||||||
});
|
});
|
||||||
reducer.AddReductionPass(
|
reducer.AddReductionPass(
|
||||||
MakeUnique<RemoveUnusedInstructionReductionOpportunityFinder>(false));
|
MakeUnique<RemoveUnusedInstructionReductionOpportunityFinder>(false));
|
||||||
|
@ -230,13 +229,14 @@ bool InterestingWhileOpcodeExists(const std::vector<uint32_t>& binary,
|
||||||
DumpShader(binary, ss.str().c_str());
|
DumpShader(binary, ss.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IRContext> context =
|
std::unique_ptr<opt::IRContext> context =
|
||||||
BuildModule(kEnv, kMessageConsumer, binary.data(), binary.size());
|
BuildModule(kEnv, kMessageConsumer, binary.data(), binary.size());
|
||||||
assert(context);
|
assert(context);
|
||||||
bool interesting = false;
|
bool interesting = false;
|
||||||
for (auto& function : *context->module()) {
|
for (auto& function : *context->module()) {
|
||||||
context->cfg()->ForEachBlockInPostOrder(
|
context->cfg()->ForEachBlockInPostOrder(
|
||||||
&*function.begin(), [opcode, &interesting](BasicBlock* block) -> void {
|
&*function.begin(),
|
||||||
|
[opcode, &interesting](opt::BasicBlock* block) -> void {
|
||||||
for (auto& inst : *block) {
|
for (auto& inst : *block) {
|
||||||
if (inst.opcode() == opcode) {
|
if (inst.opcode() == opcode) {
|
||||||
interesting = true;
|
interesting = true;
|
||||||
|
@ -369,6 +369,147 @@ const std::string kShaderWithLoopsDivAndMul = R"(
|
||||||
OpFunctionEnd
|
OpFunctionEnd
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
// The shader below comes from the following GLSL.
|
||||||
|
// #version 320 es
|
||||||
|
//
|
||||||
|
// int baz(int x) {
|
||||||
|
// int y = x + 1;
|
||||||
|
// y = y + 2;
|
||||||
|
// if (y > 0) {
|
||||||
|
// return x;
|
||||||
|
// }
|
||||||
|
// return x + 1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int bar(int a) {
|
||||||
|
// if (a == 3) {
|
||||||
|
// return baz(2*a);
|
||||||
|
// }
|
||||||
|
// a = a + 1;
|
||||||
|
// for (int i = 0; i < 10; i++) {
|
||||||
|
// a += baz(a);
|
||||||
|
// }
|
||||||
|
// return a;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void main() {
|
||||||
|
// int x;
|
||||||
|
// x = 3;
|
||||||
|
// x += 1;
|
||||||
|
// x += bar(x);
|
||||||
|
// x += baz(x);
|
||||||
|
// }
|
||||||
|
const std::string kShaderWithMultipleFunctions = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %4 "main"
|
||||||
|
OpExecutionMode %4 OriginUpperLeft
|
||||||
|
OpSource ESSL 320
|
||||||
|
%2 = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %2
|
||||||
|
%6 = OpTypeInt 32 1
|
||||||
|
%7 = OpTypePointer Function %6
|
||||||
|
%8 = OpTypeFunction %6 %7
|
||||||
|
%17 = OpConstant %6 1
|
||||||
|
%20 = OpConstant %6 2
|
||||||
|
%23 = OpConstant %6 0
|
||||||
|
%24 = OpTypeBool
|
||||||
|
%35 = OpConstant %6 3
|
||||||
|
%53 = OpConstant %6 10
|
||||||
|
%4 = OpFunction %2 None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%65 = OpVariable %7 Function
|
||||||
|
%68 = OpVariable %7 Function
|
||||||
|
%73 = OpVariable %7 Function
|
||||||
|
OpStore %65 %35
|
||||||
|
%66 = OpLoad %6 %65
|
||||||
|
%67 = OpIAdd %6 %66 %17
|
||||||
|
OpStore %65 %67
|
||||||
|
%69 = OpLoad %6 %65
|
||||||
|
OpStore %68 %69
|
||||||
|
%70 = OpFunctionCall %6 %13 %68
|
||||||
|
%71 = OpLoad %6 %65
|
||||||
|
%72 = OpIAdd %6 %71 %70
|
||||||
|
OpStore %65 %72
|
||||||
|
%74 = OpLoad %6 %65
|
||||||
|
OpStore %73 %74
|
||||||
|
%75 = OpFunctionCall %6 %10 %73
|
||||||
|
%76 = OpLoad %6 %65
|
||||||
|
%77 = OpIAdd %6 %76 %75
|
||||||
|
OpStore %65 %77
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%10 = OpFunction %6 None %8
|
||||||
|
%9 = OpFunctionParameter %7
|
||||||
|
%11 = OpLabel
|
||||||
|
%15 = OpVariable %7 Function
|
||||||
|
%16 = OpLoad %6 %9
|
||||||
|
%18 = OpIAdd %6 %16 %17
|
||||||
|
OpStore %15 %18
|
||||||
|
%19 = OpLoad %6 %15
|
||||||
|
%21 = OpIAdd %6 %19 %20
|
||||||
|
OpStore %15 %21
|
||||||
|
%22 = OpLoad %6 %15
|
||||||
|
%25 = OpSGreaterThan %24 %22 %23
|
||||||
|
OpSelectionMerge %27 None
|
||||||
|
OpBranchConditional %25 %26 %27
|
||||||
|
%26 = OpLabel
|
||||||
|
%28 = OpLoad %6 %9
|
||||||
|
OpReturnValue %28
|
||||||
|
%27 = OpLabel
|
||||||
|
%30 = OpLoad %6 %9
|
||||||
|
%31 = OpIAdd %6 %30 %17
|
||||||
|
OpReturnValue %31
|
||||||
|
OpFunctionEnd
|
||||||
|
%13 = OpFunction %6 None %8
|
||||||
|
%12 = OpFunctionParameter %7
|
||||||
|
%14 = OpLabel
|
||||||
|
%41 = OpVariable %7 Function
|
||||||
|
%46 = OpVariable %7 Function
|
||||||
|
%55 = OpVariable %7 Function
|
||||||
|
%34 = OpLoad %6 %12
|
||||||
|
%36 = OpIEqual %24 %34 %35
|
||||||
|
OpSelectionMerge %38 None
|
||||||
|
OpBranchConditional %36 %37 %38
|
||||||
|
%37 = OpLabel
|
||||||
|
%39 = OpLoad %6 %12
|
||||||
|
%40 = OpIMul %6 %20 %39
|
||||||
|
OpStore %41 %40
|
||||||
|
%42 = OpFunctionCall %6 %10 %41
|
||||||
|
OpReturnValue %42
|
||||||
|
%38 = OpLabel
|
||||||
|
%44 = OpLoad %6 %12
|
||||||
|
%45 = OpIAdd %6 %44 %17
|
||||||
|
OpStore %12 %45
|
||||||
|
OpStore %46 %23
|
||||||
|
OpBranch %47
|
||||||
|
%47 = OpLabel
|
||||||
|
OpLoopMerge %49 %50 None
|
||||||
|
OpBranch %51
|
||||||
|
%51 = OpLabel
|
||||||
|
%52 = OpLoad %6 %46
|
||||||
|
%54 = OpSLessThan %24 %52 %53
|
||||||
|
OpBranchConditional %54 %48 %49
|
||||||
|
%48 = OpLabel
|
||||||
|
%56 = OpLoad %6 %12
|
||||||
|
OpStore %55 %56
|
||||||
|
%57 = OpFunctionCall %6 %10 %55
|
||||||
|
%58 = OpLoad %6 %12
|
||||||
|
%59 = OpIAdd %6 %58 %57
|
||||||
|
OpStore %12 %59
|
||||||
|
OpBranch %50
|
||||||
|
%50 = OpLabel
|
||||||
|
%60 = OpLoad %6 %46
|
||||||
|
%61 = OpIAdd %6 %60 %17
|
||||||
|
OpStore %46 %61
|
||||||
|
OpBranch %47
|
||||||
|
%49 = OpLabel
|
||||||
|
%62 = OpLoad %6 %12
|
||||||
|
OpReturnValue %62
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
TEST(ReducerTest, ShaderReduceWhileMulReachable) {
|
TEST(ReducerTest, ShaderReduceWhileMulReachable) {
|
||||||
Reducer reducer(kEnv);
|
Reducer reducer(kEnv);
|
||||||
|
|
||||||
|
@ -417,6 +558,70 @@ TEST(ReducerTest, ShaderReduceWhileDivReachable) {
|
||||||
ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete);
|
ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computes an instruction count for each function in the module represented by
|
||||||
|
// |binary|.
|
||||||
|
std::unordered_map<uint32_t, uint32_t> GetFunctionInstructionCount(
|
||||||
|
const std::vector<uint32_t>& binary) {
|
||||||
|
std::unique_ptr<opt::IRContext> context =
|
||||||
|
BuildModule(kEnv, kMessageConsumer, binary.data(), binary.size());
|
||||||
|
assert(context != nullptr && "Failed to build module.");
|
||||||
|
std::unordered_map<uint32_t, uint32_t> result;
|
||||||
|
for (auto& function : *context->module()) {
|
||||||
|
uint32_t& count = result[function.result_id()] = 0;
|
||||||
|
function.ForEachInst([&count](opt::Instruction*) { count++; });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ReducerTest, SingleFunctionReduction) {
|
||||||
|
Reducer reducer(kEnv);
|
||||||
|
|
||||||
|
PingPongInteresting ping_pong_interesting(4);
|
||||||
|
reducer.SetInterestingnessFunction(
|
||||||
|
[&ping_pong_interesting](const std::vector<uint32_t>&, uint32_t) -> bool {
|
||||||
|
return ping_pong_interesting.IsInteresting();
|
||||||
|
});
|
||||||
|
reducer.AddDefaultReductionPasses();
|
||||||
|
reducer.SetMessageConsumer(kMessageConsumer);
|
||||||
|
|
||||||
|
std::vector<uint32_t> binary_in;
|
||||||
|
SpirvTools t(kEnv);
|
||||||
|
|
||||||
|
ASSERT_TRUE(t.Assemble(kShaderWithMultipleFunctions, &binary_in,
|
||||||
|
kReduceAssembleOption));
|
||||||
|
|
||||||
|
auto original_instruction_count = GetFunctionInstructionCount(binary_in);
|
||||||
|
|
||||||
|
std::vector<uint32_t> binary_out;
|
||||||
|
spvtools::ReducerOptions reducer_options;
|
||||||
|
reducer_options.set_step_limit(500);
|
||||||
|
reducer_options.set_fail_on_validation_error(true);
|
||||||
|
|
||||||
|
// Instruct the reducer to only target function 13.
|
||||||
|
reducer_options.set_target_function(13);
|
||||||
|
|
||||||
|
spvtools::ValidatorOptions validator_options;
|
||||||
|
|
||||||
|
Reducer::ReductionResultStatus status = reducer.Run(
|
||||||
|
std::move(binary_in), &binary_out, reducer_options, validator_options);
|
||||||
|
|
||||||
|
ASSERT_EQ(status, Reducer::ReductionResultStatus::kComplete);
|
||||||
|
|
||||||
|
auto final_instruction_count = GetFunctionInstructionCount(binary_out);
|
||||||
|
|
||||||
|
// Nothing should have been removed from these functions.
|
||||||
|
ASSERT_EQ(original_instruction_count.at(4), final_instruction_count.at(4));
|
||||||
|
ASSERT_EQ(original_instruction_count.at(10), final_instruction_count.at(10));
|
||||||
|
|
||||||
|
// Function 13 should have been reduced to these five instructions:
|
||||||
|
// OpFunction
|
||||||
|
// OpFunctionParameter
|
||||||
|
// OpLabel
|
||||||
|
// OpReturnValue
|
||||||
|
// OpFunctionEnd
|
||||||
|
ASSERT_EQ(5, final_instruction_count.at(13));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace reduce
|
} // namespace reduce
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
|
@ -66,7 +66,7 @@ TEST(RemoveBlockReductionPassTest, BasicCheck) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -181,7 +181,7 @@ TEST(RemoveBlockReductionPassTest, UnreachableContinueAndMerge) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ TEST(RemoveBlockReductionPassTest, OneBlock) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ TEST(RemoveBlockReductionPassTest, UnreachableBlocksWithOutsideIdUses) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
const auto ops =
|
const auto ops =
|
||||||
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ TEST(RemoveBlockReductionPassTest, UnreachableBlocksWithInsideIdUses) {
|
||||||
const auto context =
|
const auto context =
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
auto ops = RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
auto ops = RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -323,7 +323,7 @@ TEST(RemoveBlockReductionPassTest, UnreachableBlocksWithInsideIdUses) {
|
||||||
// removed.
|
// removed.
|
||||||
|
|
||||||
ops = RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
ops = RemoveBlockReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ TEST(RemoveFunctionTest, BasicCheck) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -97,7 +97,7 @@ TEST(RemoveFunctionTest, BasicCheck) {
|
||||||
CheckEqual(env, after_first, context.get());
|
CheckEqual(env, after_first, context.get());
|
||||||
|
|
||||||
ops = RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
ops = RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ TEST(RemoveFunctionTest, NothingToRemove) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ TEST(RemoveFunctionTest, TwoRemovableFunctions) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -254,7 +254,7 @@ TEST(RemoveFunctionTest, NoRemovalsDueToOpName) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ TEST(RemoveFunctionTest, NoRemovalDueToLinkageDecoration) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveFunctionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlock) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlock) {
|
||||||
CheckEqual(env, after, context.get());
|
CheckEqual(env, after, context.get());
|
||||||
|
|
||||||
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlockMerge) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseSameTargetBlockMerge) {
|
||||||
CheckEqual(env, after, context.get());
|
CheckEqual(env, after, context.get());
|
||||||
|
|
||||||
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocksOneMerge) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ TEST(RemoveSelectionTest, NoOpportunityBecauseDifferentTargetBlocks) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ TEST(RemoveSelectionTest, NoOpportunityBecauseMergeUsed) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseLoopMergeUsed) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -427,7 +427,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseLoopMergeUsed) {
|
||||||
CheckEqual(env, after, context.get());
|
CheckEqual(env, after, context.get());
|
||||||
|
|
||||||
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseLoopContinueUsed) {
|
||||||
|
|
||||||
auto ops =
|
auto ops =
|
||||||
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -548,7 +548,7 @@ TEST(RemoveSelectionTest, OpportunityBecauseLoopContinueUsed) {
|
||||||
CheckEqual(env, after, context.get());
|
CheckEqual(env, after, context.get());
|
||||||
|
|
||||||
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
ops = RemoveSelectionReductionOpportunityFinder().GetAvailableOpportunities(
|
||||||
context.get());
|
context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
|
||||||
|
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = finder.GetAvailableOpportunities(context.get());
|
auto ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(10, ops.size());
|
ASSERT_EQ(10, ops.size());
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
|
||||||
|
|
||||||
CheckEqual(kEnv, step_2, context.get());
|
CheckEqual(kEnv, step_2, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(7, ops.size());
|
ASSERT_EQ(7, ops.size());
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
|
||||||
|
|
||||||
CheckEqual(kEnv, step_3, context.get());
|
CheckEqual(kEnv, step_3, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
|
||||||
|
|
||||||
CheckEqual(kEnv, step_4, context.get());
|
CheckEqual(kEnv, step_4, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
|
||||||
|
|
||||||
CheckEqual(kEnv, step_5, context.get());
|
CheckEqual(kEnv, step_5, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, RemoveStores) {
|
||||||
|
|
||||||
CheckEqual(kEnv, step_6, context.get());
|
CheckEqual(kEnv, step_6, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
|
||||||
|
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = finder.GetAvailableOpportunities(context.get());
|
auto ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(6, ops.size());
|
ASSERT_EQ(6, ops.size());
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
|
||||||
|
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(3, ops.size());
|
ASSERT_EQ(3, ops.size());
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
|
||||||
|
|
||||||
CheckEqual(kEnv, after_2, context.get());
|
CheckEqual(kEnv, after_2, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
|
||||||
|
|
||||||
CheckEqual(kEnv, after_3, context.get());
|
CheckEqual(kEnv, after_3, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ TEST(RemoveUnusedInstructionReductionPassTest, Referenced) {
|
||||||
|
|
||||||
CheckEqual(kEnv, after_4, context.get());
|
CheckEqual(kEnv, after_4, context.get());
|
||||||
|
|
||||||
ops = finder.GetAvailableOpportunities(context.get());
|
ops = finder.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
@ -438,7 +438,7 @@ TEST(RemoveUnusedResourceVariableTest, RemoveUnusedResourceVariables) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
|
|
||||||
auto ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
|
auto ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(7, ops.size());
|
ASSERT_EQ(7, ops.size());
|
||||||
|
|
||||||
for (auto& op : ops) {
|
for (auto& op : ops) {
|
||||||
|
@ -487,7 +487,7 @@ TEST(RemoveUnusedResourceVariableTest, RemoveUnusedResourceVariables) {
|
||||||
CheckEqual(env, expected_1, context.get());
|
CheckEqual(env, expected_1, context.get());
|
||||||
|
|
||||||
ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
|
ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(6, ops.size());
|
ASSERT_EQ(6, ops.size());
|
||||||
|
|
||||||
for (auto& op : ops) {
|
for (auto& op : ops) {
|
||||||
|
@ -530,7 +530,7 @@ TEST(RemoveUnusedResourceVariableTest, RemoveUnusedResourceVariables) {
|
||||||
CheckEqual(env, expected_2, context.get());
|
CheckEqual(env, expected_2, context.get());
|
||||||
|
|
||||||
ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
|
ops = RemoveUnusedInstructionReductionOpportunityFinder(true)
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(6, ops.size());
|
ASSERT_EQ(6, ops.size());
|
||||||
|
|
||||||
for (auto& op : ops) {
|
for (auto& op : ops) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ TEST(RemoveUnusedStructMemberTest, RemoveOneMember) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
|
|
||||||
auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
|
auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
ops[0]->TryToApply();
|
ops[0]->TryToApply();
|
||||||
|
@ -143,7 +143,7 @@ TEST(RemoveUnusedStructMemberTest, RemoveUniformBufferMember) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
|
|
||||||
auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
|
auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
ops[0]->TryToApply();
|
ops[0]->TryToApply();
|
||||||
|
@ -229,7 +229,7 @@ TEST(RemoveUnusedStructMemberTest, DoNotRemoveNamedMemberRemoveOneMember) {
|
||||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||||
|
|
||||||
auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
|
auto ops = RemoveUnusedStructMemberReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ TEST(SimpleConditionalBranchToBranchTest, Diamond) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ TEST(SimpleConditionalBranchToBranchTest, DiamondNoSelection) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ TEST(SimpleConditionalBranchToBranchTest, DiamondNoSelection) {
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ TEST(SimpleConditionalBranchToBranchTest, ConditionalBranchesButNotSimple) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
@ -266,7 +266,7 @@ TEST(SimpleConditionalBranchToBranchTest, SimplifyBackEdge) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ TEST(SimpleConditionalBranchToBranchTest, SimplifyBackEdge) {
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ TEST(SimpleConditionalBranchToBranchTest,
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ TEST(SimpleConditionalBranchToBranchTest,
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ TEST(SimpleConditionalBranchToBranchTest, BackEdgeUnreachable) {
|
||||||
CheckValid(kEnv, context.get());
|
CheckValid(kEnv, context.get());
|
||||||
|
|
||||||
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
auto ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
|
@ -477,7 +477,7 @@ TEST(SimpleConditionalBranchToBranchTest, BackEdgeUnreachable) {
|
||||||
CheckEqual(kEnv, after, context.get());
|
CheckEqual(kEnv, after, context.get());
|
||||||
|
|
||||||
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
ops = SimpleConditionalBranchToBranchOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader1) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -211,7 +211,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader2) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(4, ops.size());
|
ASSERT_EQ(4, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -680,7 +680,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader3) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +758,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LoopyShader4) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
// Initially there are two opportunities.
|
// Initially there are two opportunities.
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
|
@ -881,7 +881,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, ConditionalBreak1) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -956,7 +956,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, ConditionalBreak2) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -1024,7 +1024,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, UnconditionalBreak) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -1224,7 +1224,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, Complex) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -1691,7 +1691,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, ComplexOptimized) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2008,7 +2008,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, DominanceIssue) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2156,7 +2156,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, AccessChainIssue) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2313,7 +2313,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, DominanceAndPhiIssue) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2421,7 +2421,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, OpLineBeforeOpPhi) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2511,7 +2511,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
// There should be no opportunities.
|
// There should be no opportunities.
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
|
@ -2555,7 +2555,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
// There should be no opportunities.
|
// There should be no opportunities.
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
|
@ -2595,7 +2595,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, ContinueTargetIsSwitchTarget) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2670,7 +2670,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2733,7 +2733,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LoopBranchesStraightToMerge) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2790,7 +2790,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2874,7 +2874,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, MultipleAccessChains) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -2970,7 +2970,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -3089,7 +3089,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(2, ops.size());
|
ASSERT_EQ(2, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -3209,7 +3209,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
// We cannot transform the inner loop due to its header jumping straight to
|
// We cannot transform the inner loop due to its header jumping straight to
|
||||||
// the outer loop merge (the inner loop's merge does not post-dominate its
|
// the outer loop merge (the inner loop's merge does not post-dominate its
|
||||||
|
@ -3254,7 +3254,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
|
|
||||||
// Now look again for more opportunities.
|
// Now look again for more opportunities.
|
||||||
ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
// What was the inner loop should now be transformable, as the jump to the
|
// What was the inner loop should now be transformable, as the jump to the
|
||||||
// outer loop's merge has been redirected.
|
// outer loop's merge has been redirected.
|
||||||
|
@ -3422,7 +3422,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LongAccessChains) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
|
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -3513,7 +3513,7 @@ TEST(StructuredLoopToSelectionReductionPassTest, LoopyShaderWithOpDecorate) {
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(1, ops.size());
|
ASSERT_EQ(1, ops.size());
|
||||||
|
|
||||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||||
|
@ -3619,7 +3619,7 @@ TEST(StructuredLoopToSelectionReductionPassTest,
|
||||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||||
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
const auto context = BuildModule(env, nullptr, shader, kReduceAssembleOption);
|
||||||
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
const auto ops = StructuredLoopToSelectionReductionOpportunityFinder()
|
||||||
.GetAvailableOpportunities(context.get());
|
.GetAvailableOpportunities(context.get(), 0);
|
||||||
ASSERT_EQ(0, ops.size());
|
ASSERT_EQ(0, ops.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ namespace reduce {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using opt::Function;
|
using opt::Function;
|
||||||
using opt::Instruction;
|
|
||||||
using opt::IRContext;
|
using opt::IRContext;
|
||||||
|
using opt::Instruction;
|
||||||
|
|
||||||
// A reduction opportunity finder that finds opportunities to remove global
|
// A reduction opportunity finder that finds opportunities to remove global
|
||||||
// values regardless of whether they are referenced. This is very likely to make
|
// values regardless of whether they are referenced. This is very likely to make
|
||||||
|
@ -43,7 +43,7 @@ class BlindlyRemoveGlobalValuesReductionOpportunityFinder
|
||||||
// referenced (directly or indirectly) from elsewhere in the module, each such
|
// referenced (directly or indirectly) from elsewhere in the module, each such
|
||||||
// opportunity will make the module invalid.
|
// opportunity will make the module invalid.
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
IRContext* context) const final {
|
IRContext* context, uint32_t /*unused*/) const final {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
for (auto& inst : context->module()->types_values()) {
|
for (auto& inst : context->module()->types_values()) {
|
||||||
if (inst.HasResultId()) {
|
if (inst.HasResultId()) {
|
||||||
|
@ -101,7 +101,7 @@ class OpVariableDuplicatorReductionOpportunityFinder
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
std::vector<std::unique_ptr<ReductionOpportunity>> GetAvailableOpportunities(
|
||||||
IRContext* context) const final {
|
IRContext* context, uint32_t /*unused*/) const final {
|
||||||
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
||||||
for (auto& function : *context->module()) {
|
for (auto& function : *context->module()) {
|
||||||
Instruction* first_instruction = &*function.begin()[0].begin();
|
Instruction* first_instruction = &*function.begin()[0].begin();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "source/opt/build_module.h"
|
#include "source/opt/build_module.h"
|
||||||
#include "source/opt/ir_context.h"
|
#include "source/opt/ir_context.h"
|
||||||
|
@ -102,6 +103,14 @@ Options (in lexicographical order):
|
||||||
--step-limit=
|
--step-limit=
|
||||||
32-bit unsigned integer specifying maximum number of steps the
|
32-bit unsigned integer specifying maximum number of steps the
|
||||||
reducer will take before giving up.
|
reducer will take before giving up.
|
||||||
|
--target-function=
|
||||||
|
32-bit unsigned integer specifying the id of a function in the
|
||||||
|
input module. The reducer will restrict attention to this
|
||||||
|
function, and will not make changes to other functions or to
|
||||||
|
instructions outside of functions, except that some global
|
||||||
|
instructions may be added in support of reducing the target
|
||||||
|
function. If 0 is specified (the default) then all functions are
|
||||||
|
reduced.
|
||||||
--temp-file-prefix=
|
--temp-file-prefix=
|
||||||
Specifies a temporary file prefix that will be used to output
|
Specifies a temporary file prefix that will be used to output
|
||||||
temporary shader files during reduction. A number and .spv
|
temporary shader files during reduction. A number and .spv
|
||||||
|
@ -169,6 +178,15 @@ ReduceStatus ParseFlags(int argc, const char** argv,
|
||||||
static_cast<uint32_t>(strtol(split_flag.second.c_str(), &end, 10));
|
static_cast<uint32_t>(strtol(split_flag.second.c_str(), &end, 10));
|
||||||
assert(end != split_flag.second.c_str() && errno == 0);
|
assert(end != split_flag.second.c_str() && errno == 0);
|
||||||
reducer_options->set_step_limit(step_limit);
|
reducer_options->set_step_limit(step_limit);
|
||||||
|
} else if (0 == strncmp(cur_arg, "--target-function=",
|
||||||
|
sizeof("--target-function=") - 1)) {
|
||||||
|
const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
|
||||||
|
char* end = nullptr;
|
||||||
|
errno = 0;
|
||||||
|
const auto target_function =
|
||||||
|
static_cast<uint32_t>(strtol(split_flag.second.c_str(), &end, 10));
|
||||||
|
assert(end != split_flag.second.c_str() && errno == 0);
|
||||||
|
reducer_options->set_target_function(target_function);
|
||||||
} else if (0 == strcmp(cur_arg, "--fail-on-validation-error")) {
|
} else if (0 == strcmp(cur_arg, "--fail-on-validation-error")) {
|
||||||
reducer_options->set_fail_on_validation_error(true);
|
reducer_options->set_fail_on_validation_error(true);
|
||||||
} else if (0 == strcmp(cur_arg, "--before-hlsl-legalization")) {
|
} else if (0 == strcmp(cur_arg, "--before-hlsl-legalization")) {
|
||||||
|
@ -304,6 +322,29 @@ int main(int argc, const char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t target_function = (*reducer_options).target_function;
|
||||||
|
if (target_function) {
|
||||||
|
// A target function was specified; check that it exists.
|
||||||
|
std::unique_ptr<spvtools::opt::IRContext> context = spvtools::BuildModule(
|
||||||
|
kDefaultEnvironment, spvtools::utils::CLIMessageConsumer,
|
||||||
|
binary_in.data(), binary_in.size());
|
||||||
|
bool found_target_function = false;
|
||||||
|
for (auto& function : *context->module()) {
|
||||||
|
if (function.result_id() == target_function) {
|
||||||
|
found_target_function = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found_target_function) {
|
||||||
|
std::stringstream strstr;
|
||||||
|
strstr << "Target function with id " << target_function
|
||||||
|
<< " was requested, but not found in the module; stopping.";
|
||||||
|
spvtools::utils::CLIMessageConsumer(SPV_MSG_ERROR, nullptr, {},
|
||||||
|
strstr.str().c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> binary_out;
|
std::vector<uint32_t> binary_out;
|
||||||
const auto reduction_status = reducer.Run(std::move(binary_in), &binary_out,
|
const auto reduction_status = reducer.Run(std::move(binary_in), &binary_out,
|
||||||
reducer_options, validator_options);
|
reducer_options, validator_options);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче