diff options
| author | ameerj <52414509+ameerj@users.noreply.github.com> | 2022-03-22 18:34:31 -0400 | 
|---|---|---|
| committer | ameerj <52414509+ameerj@users.noreply.github.com> | 2022-03-23 17:57:22 -0400 | 
| commit | 67159e3be76cf468288ae492ea22fc43a77a9d1e (patch) | |
| tree | 1430335870a66823463f56f86cd98de6f8d5c6d8 | |
| parent | f10d40a0a25dc6709b8cbd0a6793175434db6472 (diff) | |
dead_code_elimination_pass: Remove unreachable Phi arguments
| -rw-r--r-- | src/shader_recompiler/frontend/ir/microinstruction.cpp | 5 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/value.h | 4 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp | 27 | 
3 files changed, 36 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 631446cf7..4a2564f47 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp @@ -326,6 +326,11 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) {      phi_args.emplace_back(predecessor, value);  } +void Inst::ErasePhiOperand(size_t index) { +    const auto operand_it{phi_args.begin() + static_cast<ptrdiff_t>(index)}; +    phi_args.erase(operand_it); +} +  void Inst::OrderPhiArgs() {      if (op != Opcode::Phi) {          throw LogicError("{} is not a Phi instruction", op); diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 947579852..14f6e55bc 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h @@ -179,9 +179,13 @@ public:      /// Get a pointer to the block of a phi argument.      [[nodiscard]] Block* PhiBlock(size_t index) const; +      /// Add phi operand to a phi instruction.      void AddPhiOperand(Block* predecessor, const Value& value); +    // Erase the phi operand at the given index. +    void ErasePhiOperand(size_t index); +      /// Orders the Phi arguments from farthest away to nearest.      void OrderPhiArgs(); diff --git a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp index 6c7c7b32d..6697fde85 100644 --- a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp +++ b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp @@ -2,6 +2,10 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <algorithm> + +#include <boost/container/small_vector.hpp> +  #include "shader_recompiler/frontend/ir/basic_block.h"  #include "shader_recompiler/frontend/ir/value.h"  #include "shader_recompiler/ir_opt/passes.h" @@ -25,7 +29,26 @@ void DeadInstElimination(IR::Block* const block) {      }  } +void DeletedPhiArgElimination(IR::Program& program, std::span<const IR::Block*> dead_blocks) { +    for (IR::Block* const block : program.blocks) { +        for (IR::Inst& phi : *block) { +            if (!IR::IsPhi(phi)) { +                continue; +            } +            for (size_t i = 0; i < phi.NumArgs(); ++i) { +                if (std::ranges::find(dead_blocks, phi.PhiBlock(i)) == dead_blocks.end()) { +                    continue; +                } +                // Phi operand at this index is an unreachable block +                phi.ErasePhiOperand(i); +                --i; +            } +        } +    } +} +  void DeadBranchElimination(IR::Program& program) { +    boost::container::small_vector<const IR::Block*, 3> dead_blocks;      const auto begin_it{program.syntax_list.begin()};      for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) {          if (node_it->type != IR::AbstractSyntaxNode::Type::If) { @@ -55,6 +78,7 @@ void DeadBranchElimination(IR::Program& program) {              case IR::AbstractSyntaxNode::Type::Block: {                  IR::Block* const block{node_it->data.block};                  DeadInstElimination<false>(block); +                dead_blocks.push_back(block);                  break;              }              default: @@ -66,6 +90,9 @@ void DeadBranchElimination(IR::Program& program) {          // Account for loop increment          --node_it;      } +    if (!dead_blocks.empty()) { +        DeletedPhiArgElimination(program, std::span(dead_blocks.data(), dead_blocks.size())); +    }  }  } // namespace  | 
