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.cpp21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
index bab7ca186..259233746 100644
--- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
+++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
@@ -48,8 +48,12 @@ struct GotoVariable : FlagTag {
48 u32 index; 48 u32 index;
49}; 49};
50 50
51struct IndirectBranchVariable {
52 auto operator<=>(const IndirectBranchVariable&) const noexcept = default;
53};
54
51using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, 55using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag,
52 OverflowFlagTag, GotoVariable>; 56 OverflowFlagTag, GotoVariable, IndirectBranchVariable>;
53using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>; 57using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>;
54 58
55struct DefTable { 59struct DefTable {
@@ -65,6 +69,10 @@ struct DefTable {
65 return goto_vars[goto_variable.index]; 69 return goto_vars[goto_variable.index];
66 } 70 }
67 71
72 [[nodiscard]] ValueMap& operator[](IndirectBranchVariable) {
73 return indirect_branch_var;
74 }
75
68 [[nodiscard]] ValueMap& operator[](ZeroFlagTag) noexcept { 76 [[nodiscard]] ValueMap& operator[](ZeroFlagTag) noexcept {
69 return zero_flag; 77 return zero_flag;
70 } 78 }
@@ -84,6 +92,7 @@ struct DefTable {
84 std::array<ValueMap, IR::NUM_USER_REGS> regs; 92 std::array<ValueMap, IR::NUM_USER_REGS> regs;
85 std::array<ValueMap, IR::NUM_USER_PREDS> preds; 93 std::array<ValueMap, IR::NUM_USER_PREDS> preds;
86 boost::container::flat_map<u32, ValueMap> goto_vars; 94 boost::container::flat_map<u32, ValueMap> goto_vars;
95 ValueMap indirect_branch_var;
87 ValueMap zero_flag; 96 ValueMap zero_flag;
88 ValueMap sign_flag; 97 ValueMap sign_flag;
89 ValueMap carry_flag; 98 ValueMap carry_flag;
@@ -102,6 +111,10 @@ IR::Opcode UndefOpcode(const FlagTag&) noexcept {
102 return IR::Opcode::UndefU1; 111 return IR::Opcode::UndefU1;
103} 112}
104 113
114IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept {
115 return IR::Opcode::UndefU32;
116}
117
105[[nodiscard]] bool IsPhi(const IR::Inst& inst) noexcept { 118[[nodiscard]] bool IsPhi(const IR::Inst& inst) noexcept {
106 return inst.Opcode() == IR::Opcode::Phi; 119 return inst.Opcode() == IR::Opcode::Phi;
107} 120}
@@ -219,6 +232,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) {
219 case IR::Opcode::SetGotoVariable: 232 case IR::Opcode::SetGotoVariable:
220 pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); 233 pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1));
221 break; 234 break;
235 case IR::Opcode::SetIndirectBranchVariable:
236 pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0));
237 break;
222 case IR::Opcode::SetZFlag: 238 case IR::Opcode::SetZFlag:
223 pass.WriteVariable(ZeroFlagTag{}, block, inst.Arg(0)); 239 pass.WriteVariable(ZeroFlagTag{}, block, inst.Arg(0));
224 break; 240 break;
@@ -244,6 +260,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) {
244 case IR::Opcode::GetGotoVariable: 260 case IR::Opcode::GetGotoVariable:
245 inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); 261 inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block));
246 break; 262 break;
263 case IR::Opcode::GetIndirectBranchVariable:
264 inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block));
265 break;
247 case IR::Opcode::GetZFlag: 266 case IR::Opcode::GetZFlag:
248 inst.ReplaceUsesWith(pass.ReadVariable(ZeroFlagTag{}, block)); 267 inst.ReplaceUsesWith(pass.ReadVariable(ZeroFlagTag{}, block));
249 break; 268 break;