summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp5
-rw-r--r--src/shader_recompiler/frontend/ir/value.h4
-rw-r--r--src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp27
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) {
326 phi_args.emplace_back(predecessor, value); 326 phi_args.emplace_back(predecessor, value);
327} 327}
328 328
329void Inst::ErasePhiOperand(size_t index) {
330 const auto operand_it{phi_args.begin() + static_cast<ptrdiff_t>(index)};
331 phi_args.erase(operand_it);
332}
333
329void Inst::OrderPhiArgs() { 334void Inst::OrderPhiArgs() {
330 if (op != Opcode::Phi) { 335 if (op != Opcode::Phi) {
331 throw LogicError("{} is not a Phi instruction", op); 336 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:
179 179
180 /// Get a pointer to the block of a phi argument. 180 /// Get a pointer to the block of a phi argument.
181 [[nodiscard]] Block* PhiBlock(size_t index) const; 181 [[nodiscard]] Block* PhiBlock(size_t index) const;
182
182 /// Add phi operand to a phi instruction. 183 /// Add phi operand to a phi instruction.
183 void AddPhiOperand(Block* predecessor, const Value& value); 184 void AddPhiOperand(Block* predecessor, const Value& value);
184 185
186 // Erase the phi operand at the given index.
187 void ErasePhiOperand(size_t index);
188
185 /// Orders the Phi arguments from farthest away to nearest. 189 /// Orders the Phi arguments from farthest away to nearest.
186 void OrderPhiArgs(); 190 void OrderPhiArgs();
187 191
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 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6
7#include <boost/container/small_vector.hpp>
8
5#include "shader_recompiler/frontend/ir/basic_block.h" 9#include "shader_recompiler/frontend/ir/basic_block.h"
6#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
7#include "shader_recompiler/ir_opt/passes.h" 11#include "shader_recompiler/ir_opt/passes.h"
@@ -25,7 +29,26 @@ void DeadInstElimination(IR::Block* const block) {
25 } 29 }
26} 30}
27 31
32void DeletedPhiArgElimination(IR::Program& program, std::span<const IR::Block*> dead_blocks) {
33 for (IR::Block* const block : program.blocks) {
34 for (IR::Inst& phi : *block) {
35 if (!IR::IsPhi(phi)) {
36 continue;
37 }
38 for (size_t i = 0; i < phi.NumArgs(); ++i) {
39 if (std::ranges::find(dead_blocks, phi.PhiBlock(i)) == dead_blocks.end()) {
40 continue;
41 }
42 // Phi operand at this index is an unreachable block
43 phi.ErasePhiOperand(i);
44 --i;
45 }
46 }
47 }
48}
49
28void DeadBranchElimination(IR::Program& program) { 50void DeadBranchElimination(IR::Program& program) {
51 boost::container::small_vector<const IR::Block*, 3> dead_blocks;
29 const auto begin_it{program.syntax_list.begin()}; 52 const auto begin_it{program.syntax_list.begin()};
30 for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) { 53 for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) {
31 if (node_it->type != IR::AbstractSyntaxNode::Type::If) { 54 if (node_it->type != IR::AbstractSyntaxNode::Type::If) {
@@ -55,6 +78,7 @@ void DeadBranchElimination(IR::Program& program) {
55 case IR::AbstractSyntaxNode::Type::Block: { 78 case IR::AbstractSyntaxNode::Type::Block: {
56 IR::Block* const block{node_it->data.block}; 79 IR::Block* const block{node_it->data.block};
57 DeadInstElimination<false>(block); 80 DeadInstElimination<false>(block);
81 dead_blocks.push_back(block);
58 break; 82 break;
59 } 83 }
60 default: 84 default:
@@ -66,6 +90,9 @@ void DeadBranchElimination(IR::Program& program) {
66 // Account for loop increment 90 // Account for loop increment
67 --node_it; 91 --node_it;
68 } 92 }
93 if (!dead_blocks.empty()) {
94 DeletedPhiArgElimination(program, std::span(dead_blocks.data(), dead_blocks.size()));
95 }
69} 96}
70} // namespace 97} // namespace
71 98