summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp22
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 }