diff options
Diffstat (limited to 'src/shader_recompiler/ir_opt')
| -rw-r--r-- | src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index 7713e3ba9..15a9db90a 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | |||
| @@ -104,32 +104,34 @@ private: | |||
| 104 | val = ReadVariable(variable, preds.front()); | 104 | val = ReadVariable(variable, preds.front()); |
| 105 | } else { | 105 | } else { |
| 106 | // Break potential cycles with operandless phi | 106 | // Break potential cycles with operandless phi |
| 107 | val = IR::Value{&*block->PrependNewInst(block->begin(), IR::Opcode::Phi)}; | 107 | IR::Inst& phi_inst{*block->PrependNewInst(block->begin(), IR::Opcode::Phi)}; |
| 108 | val = IR::Value{&phi_inst}; | ||
| 108 | WriteVariable(variable, block, val); | 109 | WriteVariable(variable, block, val); |
| 109 | val = AddPhiOperands(variable, val, block); | 110 | val = AddPhiOperands(variable, phi_inst, block); |
| 110 | } | 111 | } |
| 111 | WriteVariable(variable, block, val); | 112 | WriteVariable(variable, block, val); |
| 112 | return val; | 113 | return val; |
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | IR::Value AddPhiOperands(auto variable, const IR::Value& phi, IR::Block* block) { | 116 | IR::Value AddPhiOperands(auto variable, IR::Inst& phi, IR::Block* block) { |
| 116 | for (IR::Block* const pred : block->ImmediatePredecessors()) { | 117 | for (IR::Block* const pred : block->ImmediatePredecessors()) { |
| 117 | phi.Inst()->AddPhiOperand(pred, ReadVariable(variable, pred)); | 118 | phi.AddPhiOperand(pred, ReadVariable(variable, pred)); |
| 118 | } | 119 | } |
| 119 | return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable)); | 120 | return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable)); |
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | IR::Value TryRemoveTrivialPhi(const IR::Value& phi, IR::Block* block, IR::Opcode undef_opcode) { | 123 | IR::Value TryRemoveTrivialPhi(IR::Inst& phi, IR::Block* block, IR::Opcode undef_opcode) { |
| 123 | IR::Value same; | 124 | IR::Value same; |
| 124 | for (const auto& pair : phi.Inst()->PhiOperands()) { | 125 | const size_t num_args{phi.NumArgs()}; |
| 125 | const IR::Value& op{pair.second}; | 126 | for (size_t arg_index = 0; arg_index < num_args; ++arg_index) { |
| 126 | if (op == same || op == phi) { | 127 | const IR::Value& op{phi.Arg(arg_index)}; |
| 128 | if (op == same || op == IR::Value{&phi}) { | ||
| 127 | // Unique value or self-reference | 129 | // Unique value or self-reference |
| 128 | continue; | 130 | continue; |
| 129 | } | 131 | } |
| 130 | if (!same.IsEmpty()) { | 132 | if (!same.IsEmpty()) { |
| 131 | // The phi merges at least two values: not trivial | 133 | // The phi merges at least two values: not trivial |
| 132 | return phi; | 134 | return IR::Value{&phi}; |
| 133 | } | 135 | } |
| 134 | same = op; | 136 | same = op; |
| 135 | } | 137 | } |
| @@ -139,7 +141,7 @@ private: | |||
| 139 | same = IR::Value{&*block->PrependNewInst(first_not_phi, undef_opcode)}; | 141 | same = IR::Value{&*block->PrependNewInst(first_not_phi, undef_opcode)}; |
| 140 | } | 142 | } |
| 141 | // Reroute all uses of phi to same and remove phi | 143 | // Reroute all uses of phi to same and remove phi |
| 142 | phi.Inst()->ReplaceUsesWith(same); | 144 | phi.ReplaceUsesWith(same); |
| 143 | // TODO: Try to recursively remove all phi users, which might have become trivial | 145 | // TODO: Try to recursively remove all phi users, which might have become trivial |
| 144 | return same; | 146 | return same; |
| 145 | } | 147 | } |