mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-19 03:20:14 +00:00
9de4e69856
Create aggressive dead code elimination pass This pass eliminates unused code from functions. In addition, it detects and eliminates code which may have spurious uses but which do not contribute to the output of the function. The most common cause of such code sequences is summations in loops whose result is no longer used due to dead code elimination. This optimization has additional compile time cost over standard dead code elimination. This pass only processes entry point functions. It also only processes shaders with logical addressing. It currently will not process functions with function calls. It currently only supports the GLSL.std.450 extended instruction set. It currently does not support any extensions. This pass will be made more effective by first running passes that remove dead control flow and inlines function calls. This pass can be especially useful after running Local Access Chain Conversion, which tends to cause cycles of dead code to be left after Store/Load elimination passes are completed. These cycles cannot be eliminated with standard dead code elimination. Additionally: This transform uses a whitelist of instructions that it knows do have side effects, (a.k.a. combinators). It assumes other instructions have side effects: it will not remove them, and assumes they have side effects via their ID operands.
140 lines
4.6 KiB
C++
140 lines
4.6 KiB
C++
// Copyright (c) 2017 The Khronos Group Inc.
|
|
// Copyright (c) 2017 Valve Corporation
|
|
// Copyright (c) 2017 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 LIBSPIRV_OPT_AGGRESSIVE_DCE_PASS_H_
|
|
#define LIBSPIRV_OPT_AGGRESSIVE_DCE_PASS_H_
|
|
|
|
#include <algorithm>
|
|
#include <map>
|
|
#include <queue>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <utility>
|
|
|
|
#include "basic_block.h"
|
|
#include "def_use_manager.h"
|
|
#include "module.h"
|
|
#include "pass.h"
|
|
|
|
namespace spvtools {
|
|
namespace opt {
|
|
|
|
// See optimizer.hpp for documentation.
|
|
class AggressiveDCEPass : public Pass {
|
|
|
|
using cbb_ptr = const ir::BasicBlock*;
|
|
|
|
public:
|
|
using GetBlocksFunction =
|
|
std::function<std::vector<ir::BasicBlock*>*(const ir::BasicBlock*)>;
|
|
|
|
AggressiveDCEPass();
|
|
const char* name() const override { return "aggressive-dce"; }
|
|
Status Process(ir::Module*) override;
|
|
|
|
private:
|
|
// Returns true if |opcode| is a non-ptr access chain op
|
|
bool IsNonPtrAccessChain(const SpvOp opcode) const;
|
|
|
|
// Given a load or store |ip|, return the pointer instruction.
|
|
// Also return the base variable's id in |varId|.
|
|
ir::Instruction* GetPtr(ir::Instruction* ip, uint32_t* varId);
|
|
|
|
// Add all store instruction which use |ptrId|, directly or indirectly,
|
|
// to the live instruction worklist.
|
|
void AddStores(uint32_t ptrId);
|
|
|
|
// Return true if variable with |varId| is function scope
|
|
bool IsLocalVar(uint32_t varId);
|
|
|
|
// Initialize combinator data structures
|
|
void InitCombinatorSets();
|
|
|
|
// Return true if core operator |op| has no side-effects. Currently returns
|
|
// true only for shader capability operations.
|
|
// TODO(greg-lunarg): Add kernel and other operators
|
|
bool IsCombinator(uint32_t op) const;
|
|
|
|
// Return true if OpExtInst |inst| has no side-effects. Currently returns
|
|
// true only for std.GLSL.450 extensions
|
|
// TODO(greg-lunarg): Add support for other extensions
|
|
bool IsCombinatorExt(ir::Instruction* inst) const;
|
|
|
|
// Return true if all extensions in this module are allowed by this pass.
|
|
// Currently, no extensions are allowed. glsl_std_450 extended instructions
|
|
// are allowed.
|
|
bool AllExtensionsAllowed();
|
|
|
|
// Delete debug or annotation |inst| if target operand is dead.
|
|
void DeleteInstIfTargetDead(ir::Instruction* inst);
|
|
|
|
// For function |func|, mark all Stores to non-function-scope variables
|
|
// and block terminating instructions as live. Recursively mark the values
|
|
// they use. When complete, delete any non-live instructions. Return true
|
|
// if the function has been modified.
|
|
//
|
|
// Note: This function does not delete useless control structures. All
|
|
// existing control structures will remain. This can leave not-insignificant
|
|
// sequences of ultimately useless code.
|
|
// TODO(): Remove useless control constructs.
|
|
bool AggressiveDCE(ir::Function* func);
|
|
|
|
void Initialize(ir::Module* module);
|
|
Pass::Status ProcessImpl();
|
|
|
|
// Module this pass is processing
|
|
ir::Module* module_;
|
|
|
|
// Def-Uses for the module we are processing
|
|
std::unique_ptr<analysis::DefUseManager> def_use_mgr_;
|
|
|
|
// Map from function's result id to function
|
|
std::unordered_map<uint32_t, ir::Function*> id2function_;
|
|
|
|
// Live Instruction Worklist
|
|
std::queue<ir::Instruction*> worklist_;
|
|
|
|
// Live Instructions
|
|
std::unordered_set<const ir::Instruction*> live_insts_;
|
|
|
|
// Live Local Variables
|
|
std::unordered_set<uint32_t> live_local_vars_;
|
|
|
|
// Dead instructions. Use for debug cleanup.
|
|
std::unordered_set<const ir::Instruction*> dead_insts_;
|
|
|
|
// Opcodes of shader capability core executable instructions
|
|
// without side-effect. This is a whitelist of operators
|
|
// that can safely be left unmarked as live at the beginning of
|
|
// aggressive DCE.
|
|
std::unordered_set<uint32_t> combinator_ops_shader_;
|
|
|
|
// Opcodes of GLSL_std_450 extension executable instructions
|
|
// without side-effect. This is a whitelist of operators
|
|
// that can safely be left unmarked as live at the beginning of
|
|
// aggressive DCE.
|
|
std::unordered_set<uint32_t> combinator_ops_glsl_std_450_;
|
|
|
|
// Set id for glsl_std_450 extension instructions
|
|
uint32_t glsl_std_450_id_;
|
|
};
|
|
|
|
} // namespace opt
|
|
} // namespace spvtools
|
|
|
|
#endif // LIBSPIRV_OPT_AGGRESSIVE_DCE_PASS_H_
|
|
|