Skip to content

Commit

Permalink
Add passes to eliminate dead output stores
Browse files Browse the repository at this point in the history
This adds two passes to accomplish this: one pass to analyze a shader
to determine the input slots that are live. The second pass is run on
the preceding shader to eliminate any stores to output slots that are
not consumed by the following shader.

These passes support vert, tesc, tese, geom, and frag shaders.

These passes are currently only available through the API.

These passes together with dead code elimination, and elimination of
dead input and output components and variables (WIP), will allow users
to do dead code elimination across shader boundaries.
  • Loading branch information
greg-lunarg committed Oct 27, 2022
1 parent eb113f0 commit c490015
Show file tree
Hide file tree
Showing 18 changed files with 2,633 additions and 2 deletions.
3 changes: 3 additions & 0 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ SPVTOOLS_SRC_FILES := \
SPVTOOLS_OPT_SRC_FILES := \
source/opt/aggressive_dead_code_elim_pass.cpp \
source/opt/amd_ext_to_khr.cpp \
source/opt/analyze_live_input_pass.cpp \
source/opt/basic_block.cpp \
source/opt/block_merge_pass.cpp \
source/opt/block_merge_util.cpp \
Expand Down Expand Up @@ -111,6 +112,7 @@ SPVTOOLS_OPT_SRC_FILES := \
source/opt/eliminate_dead_functions_util.cpp \
source/opt/eliminate_dead_input_components_pass.cpp \
source/opt/eliminate_dead_members_pass.cpp \
source/opt/eliminate_dead_output_stores_pass.cpp \
source/opt/feature_manager.cpp \
source/opt/fix_func_call_arguments.cpp \
source/opt/fix_storage_class.cpp \
Expand All @@ -136,6 +138,7 @@ SPVTOOLS_OPT_SRC_FILES := \
source/opt/ir_context.cpp \
source/opt/ir_loader.cpp \
source/opt/licm_pass.cpp \
source/opt/liveness.cpp \
source/opt/local_access_chain_convert_pass.cpp \
source/opt/local_redundancy_elimination.cpp \
source/opt/local_single_block_elim_pass.cpp \
Expand Down
6 changes: 6 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ static_library("spvtools_opt") {
"source/opt/aggressive_dead_code_elim_pass.h",
"source/opt/amd_ext_to_khr.cpp",
"source/opt/amd_ext_to_khr.h",
"source/opt/analyze_live_input_pass.cpp",
"source/opt/analyze_live_input_pass.h",
"source/opt/basic_block.cpp",
"source/opt/basic_block.h",
"source/opt/block_merge_pass.cpp",
Expand Down Expand Up @@ -628,6 +630,8 @@ static_library("spvtools_opt") {
"source/opt/eliminate_dead_input_components_pass.h",
"source/opt/eliminate_dead_members_pass.cpp",
"source/opt/eliminate_dead_members_pass.h",
"source/opt/eliminate_dead_output_stores_pass.cpp",
"source/opt/eliminate_dead_output_stores_pass.h",
"source/opt/empty_pass.h",
"source/opt/feature_manager.cpp",
"source/opt/feature_manager.h",
Expand Down Expand Up @@ -681,6 +685,8 @@ static_library("spvtools_opt") {
"source/opt/iterator.h",
"source/opt/licm_pass.cpp",
"source/opt/licm_pass.h",
"source/opt/liveness.cpp",
"source/opt/liveness.h",
"source/opt/local_access_chain_convert_pass.cpp",
"source/opt/local_access_chain_convert_pass.h",
"source/opt/local_redundancy_elimination.cpp",
Expand Down
21 changes: 21 additions & 0 deletions include/spirv-tools/optimizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <ostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -893,6 +894,26 @@ Optimizer::PassToken CreateInterpolateFixupPass();
// types.
Optimizer::PassToken CreateEliminateDeadInputComponentsPass();

// Analyzes shader and populates |live_locs| and |live_builtins|. Best results
// will be obtained if shader has all dead code eliminated first. |live_locs|
// and |live_builtins| are subsequently used when calling
// CreateEliminateDeadOutputStoresPass on the preceding shader. Currently only
// supports tesc, tese, geom, and frag shaders.
Optimizer::PassToken CreateAnalyzeLiveInputPass(
std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins);

// Removes stores to output locations not listed in |live_locs| or
// |live_builtins|. Best results are obtained if constant propagation is
// performed first. A subsequent call to ADCE will eliminate any dead code
// created by the removal of the stores. A subsequent call to
// CreateEliminateDeadOutputComponentsPass will eliminate any dead output
// components created by the elimination of the stores. Currently only supports
// vert, tesc, tese, and geom shaders.
Optimizer::PassToken CreateEliminateDeadOutputStoresPass(
std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins);

// Creates a convert-to-sampled-image pass to convert images and/or
// samplers with given pairs of descriptor set and binding to sampled image.
// If a pair of an image and a sampler have the same pair of descriptor set and
Expand Down
6 changes: 6 additions & 0 deletions source/opt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
fix_func_call_arguments.h
aggressive_dead_code_elim_pass.h
amd_ext_to_khr.h
analyze_live_input_pass.h
basic_block.h
block_merge_pass.h
block_merge_util.h
Expand Down Expand Up @@ -48,6 +49,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
eliminate_dead_functions_util.h
eliminate_dead_input_components_pass.h
eliminate_dead_members_pass.h
eliminate_dead_output_stores_pass.h
empty_pass.h
feature_manager.h
fix_storage_class.h
Expand All @@ -74,6 +76,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
ir_context.h
ir_loader.h
licm_pass.h
liveness.h
local_access_chain_convert_pass.h
local_redundancy_elimination.h
local_single_block_elim_pass.h
Expand Down Expand Up @@ -131,6 +134,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
fix_func_call_arguments.cpp
aggressive_dead_code_elim_pass.cpp
amd_ext_to_khr.cpp
analyze_live_input_pass.cpp
basic_block.cpp
block_merge_pass.cpp
block_merge_util.cpp
Expand Down Expand Up @@ -164,6 +168,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
eliminate_dead_functions_util.cpp
eliminate_dead_input_components_pass.cpp
eliminate_dead_members_pass.cpp
eliminate_dead_output_stores_pass.cpp
feature_manager.cpp
fix_storage_class.cpp
flatten_decoration_pass.cpp
Expand All @@ -188,6 +193,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
ir_context.cpp
ir_loader.cpp
licm_pass.cpp
liveness.cpp
local_access_chain_convert_pass.cpp
local_redundancy_elimination.cpp
local_single_block_elim_pass.cpp
Expand Down
45 changes: 45 additions & 0 deletions source/opt/analyze_live_input_pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2022 The Khronos Group Inc.
// Copyright (c) 2022 LunarG Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/opt/analyze_live_input_pass.h"

#include "source/opt/ir_context.h"

namespace spvtools {
namespace opt {

Pass::Status AnalyzeLiveInputPass::Process() {
// Current functionality assumes shader capability
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
return Status::SuccessWithoutChange;
Pass::Status status = DoLiveInputAnalysis();
return status;
}

Pass::Status AnalyzeLiveInputPass::DoLiveInputAnalysis() {
// Current functionality only supports frag, tesc, tese or geom shaders.
// Report failure for any other stage.
auto stage = context()->GetStage();
if (stage != SpvExecutionModelFragment &&
stage != SpvExecutionModelTessellationControl &&
stage != SpvExecutionModelTessellationEvaluation &&
stage != SpvExecutionModelGeometry)
return Status::Failure;
context()->get_liveness_mgr()->GetLiveness(live_locs_, live_builtins_);
return Status::SuccessWithoutChange;
}

} // namespace opt
} // namespace spvtools
57 changes: 57 additions & 0 deletions source/opt/analyze_live_input_pass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2022 The Khronos Group Inc.
// Copyright (c) 2022 LunarG Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
#define SOURCE_OPT_ANALYZE_LIVE_INPUT_H_

#include <unordered_set>

#include "source/opt/pass.h"

namespace spvtools {
namespace opt {

// See optimizer.hpp for documentation.
class AnalyzeLiveInputPass : public Pass {
public:
explicit AnalyzeLiveInputPass(std::unordered_set<uint32_t>* live_locs,
std::unordered_set<uint32_t>* live_builtins)
: live_locs_(live_locs), live_builtins_(live_builtins) {}

const char* name() const override { return "analyze-live-input"; }
Status Process() override;

// Return the mask of preserved Analyses.
IRContext::Analysis GetPreservedAnalyses() override {
return IRContext::kAnalysisDefUse |
IRContext::kAnalysisInstrToBlockMapping |
IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG |
IRContext::kAnalysisDominatorAnalysis |
IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
}

private:
// Do live input analysis
Status DoLiveInputAnalysis();

std::unordered_set<uint32_t>* live_locs_;
std::unordered_set<uint32_t>* live_builtins_;
};

} // namespace opt
} // namespace spvtools

#endif // SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
Loading

0 comments on commit c490015

Please sign in to comment.