diff options
Diffstat (limited to 'src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 51 |
1 files changed, 50 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 259233746..7dab33034 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | |||
| @@ -38,6 +38,10 @@ struct ZeroFlagTag : FlagTag {}; | |||
| 38 | struct SignFlagTag : FlagTag {}; | 38 | struct SignFlagTag : FlagTag {}; |
| 39 | struct CarryFlagTag : FlagTag {}; | 39 | struct CarryFlagTag : FlagTag {}; |
| 40 | struct OverflowFlagTag : FlagTag {}; | 40 | struct OverflowFlagTag : FlagTag {}; |
| 41 | struct FCSMFlagTag : FlagTag {}; | ||
| 42 | struct TAFlagTag : FlagTag {}; | ||
| 43 | struct TRFlagTag : FlagTag {}; | ||
| 44 | struct MXFlagTag : FlagTag {}; | ||
| 41 | 45 | ||
| 42 | struct GotoVariable : FlagTag { | 46 | struct GotoVariable : FlagTag { |
| 43 | GotoVariable() = default; | 47 | GotoVariable() = default; |
| @@ -53,7 +57,8 @@ struct IndirectBranchVariable { | |||
| 53 | }; | 57 | }; |
| 54 | 58 | ||
| 55 | using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, | 59 | using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, |
| 56 | OverflowFlagTag, GotoVariable, IndirectBranchVariable>; | 60 | OverflowFlagTag, FCSMFlagTag, TAFlagTag, TRFlagTag, MXFlagTag, |
| 61 | GotoVariable, IndirectBranchVariable>; | ||
| 57 | using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>; | 62 | using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>; |
| 58 | 63 | ||
| 59 | struct DefTable { | 64 | struct DefTable { |
| @@ -89,6 +94,22 @@ struct DefTable { | |||
| 89 | return overflow_flag; | 94 | return overflow_flag; |
| 90 | } | 95 | } |
| 91 | 96 | ||
| 97 | [[nodiscard]] ValueMap& operator[](FCSMFlagTag) noexcept { | ||
| 98 | return fcsm_flag; | ||
| 99 | } | ||
| 100 | |||
| 101 | [[nodiscard]] ValueMap& operator[](TAFlagTag) noexcept { | ||
| 102 | return ta_flag; | ||
| 103 | } | ||
| 104 | |||
| 105 | [[nodiscard]] ValueMap& operator[](TRFlagTag) noexcept { | ||
| 106 | return tr_flag; | ||
| 107 | } | ||
| 108 | |||
| 109 | [[nodiscard]] ValueMap& operator[](MXFlagTag) noexcept { | ||
| 110 | return mr_flag; | ||
| 111 | } | ||
| 112 | |||
| 92 | std::array<ValueMap, IR::NUM_USER_REGS> regs; | 113 | std::array<ValueMap, IR::NUM_USER_REGS> regs; |
| 93 | std::array<ValueMap, IR::NUM_USER_PREDS> preds; | 114 | std::array<ValueMap, IR::NUM_USER_PREDS> preds; |
| 94 | boost::container::flat_map<u32, ValueMap> goto_vars; | 115 | boost::container::flat_map<u32, ValueMap> goto_vars; |
| @@ -97,6 +118,10 @@ struct DefTable { | |||
| 97 | ValueMap sign_flag; | 118 | ValueMap sign_flag; |
| 98 | ValueMap carry_flag; | 119 | ValueMap carry_flag; |
| 99 | ValueMap overflow_flag; | 120 | ValueMap overflow_flag; |
| 121 | ValueMap fcsm_flag; | ||
| 122 | ValueMap ta_flag; | ||
| 123 | ValueMap tr_flag; | ||
| 124 | ValueMap mr_flag; | ||
| 100 | }; | 125 | }; |
| 101 | 126 | ||
| 102 | IR::Opcode UndefOpcode(IR::Reg) noexcept { | 127 | IR::Opcode UndefOpcode(IR::Reg) noexcept { |
| @@ -247,6 +272,18 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { | |||
| 247 | case IR::Opcode::SetOFlag: | 272 | case IR::Opcode::SetOFlag: |
| 248 | pass.WriteVariable(OverflowFlagTag{}, block, inst.Arg(0)); | 273 | pass.WriteVariable(OverflowFlagTag{}, block, inst.Arg(0)); |
| 249 | break; | 274 | break; |
| 275 | case IR::Opcode::SetFCSMFlag: | ||
| 276 | pass.WriteVariable(FCSMFlagTag{}, block, inst.Arg(0)); | ||
| 277 | break; | ||
| 278 | case IR::Opcode::SetTAFlag: | ||
| 279 | pass.WriteVariable(TAFlagTag{}, block, inst.Arg(0)); | ||
| 280 | break; | ||
| 281 | case IR::Opcode::SetTRFlag: | ||
| 282 | pass.WriteVariable(TRFlagTag{}, block, inst.Arg(0)); | ||
| 283 | break; | ||
| 284 | case IR::Opcode::SetMXFlag: | ||
| 285 | pass.WriteVariable(MXFlagTag{}, block, inst.Arg(0)); | ||
| 286 | break; | ||
| 250 | case IR::Opcode::GetRegister: | 287 | case IR::Opcode::GetRegister: |
| 251 | if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) { | 288 | if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) { |
| 252 | inst.ReplaceUsesWith(pass.ReadVariable(reg, block)); | 289 | inst.ReplaceUsesWith(pass.ReadVariable(reg, block)); |
| @@ -275,6 +312,18 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { | |||
| 275 | case IR::Opcode::GetOFlag: | 312 | case IR::Opcode::GetOFlag: |
| 276 | inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block)); | 313 | inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block)); |
| 277 | break; | 314 | break; |
| 315 | case IR::Opcode::GetFCSMFlag: | ||
| 316 | inst.ReplaceUsesWith(pass.ReadVariable(FCSMFlagTag{}, block)); | ||
| 317 | break; | ||
| 318 | case IR::Opcode::GetTAFlag: | ||
| 319 | inst.ReplaceUsesWith(pass.ReadVariable(TAFlagTag{}, block)); | ||
| 320 | break; | ||
| 321 | case IR::Opcode::GetTRFlag: | ||
| 322 | inst.ReplaceUsesWith(pass.ReadVariable(TRFlagTag{}, block)); | ||
| 323 | break; | ||
| 324 | case IR::Opcode::GetMXFlag: | ||
| 325 | inst.ReplaceUsesWith(pass.ReadVariable(MXFlagTag{}, block)); | ||
| 326 | break; | ||
| 278 | default: | 327 | default: |
| 279 | break; | 328 | break; |
| 280 | } | 329 | } |