diff options
| author | 2021-07-08 17:22:31 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:35 -0400 | |
| commit | 373f75d944473731408d7a72c967d5c4b37af5bb (patch) | |
| tree | a6af34845e9cae1429bbd004a36b324bb02f9932 /src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | |
| parent | shader: Comment why the array component is not read in TMML (diff) | |
| download | yuzu-373f75d944473731408d7a72c967d5c4b37af5bb.tar.gz yuzu-373f75d944473731408d7a72c967d5c4b37af5bb.tar.xz yuzu-373f75d944473731408d7a72c967d5c4b37af5bb.zip | |
shader: Add shader loop safety check settings
Also add a setting for enable Nsight Aftermath.
Diffstat (limited to 'src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index e54499ba5..a4ba393ef 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp | |||
| @@ -48,73 +48,91 @@ struct GotoVariable : FlagTag { | |||
| 48 | u32 index; | 48 | u32 index; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | struct LoopSafetyVariable { | ||
| 52 | LoopSafetyVariable() = default; | ||
| 53 | explicit LoopSafetyVariable(u32 index_) : index{index_} {} | ||
| 54 | |||
| 55 | auto operator<=>(const LoopSafetyVariable&) const noexcept = default; | ||
| 56 | |||
| 57 | u32 index; | ||
| 58 | }; | ||
| 59 | |||
| 51 | struct IndirectBranchVariable { | 60 | struct IndirectBranchVariable { |
| 52 | auto operator<=>(const IndirectBranchVariable&) const noexcept = default; | 61 | auto operator<=>(const IndirectBranchVariable&) const noexcept = default; |
| 53 | }; | 62 | }; |
| 54 | 63 | ||
| 55 | using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, | 64 | using Variant = |
| 56 | OverflowFlagTag, GotoVariable, IndirectBranchVariable>; | 65 | std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, OverflowFlagTag, |
| 57 | using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>; | 66 | GotoVariable, LoopSafetyVariable, IndirectBranchVariable>; |
| 67 | using ValueMap = boost::container::flat_map<IR::Block*, IR::Value>; | ||
| 58 | 68 | ||
| 59 | struct DefTable { | 69 | struct DefTable { |
| 60 | const IR::Value& Def(IR::Block* block, IR::Reg variable) noexcept { | 70 | const IR::Value& Def(IR::Block* block, IR::Reg variable) { |
| 61 | return block->SsaRegValue(variable); | 71 | return block->SsaRegValue(variable); |
| 62 | } | 72 | } |
| 63 | void SetDef(IR::Block* block, IR::Reg variable, const IR::Value& value) noexcept { | 73 | void SetDef(IR::Block* block, IR::Reg variable, const IR::Value& value) { |
| 64 | block->SetSsaRegValue(variable, value); | 74 | block->SetSsaRegValue(variable, value); |
| 65 | } | 75 | } |
| 66 | 76 | ||
| 67 | const IR::Value& Def(IR::Block* block, IR::Pred variable) noexcept { | 77 | const IR::Value& Def(IR::Block* block, IR::Pred variable) { |
| 68 | return preds[IR::PredIndex(variable)][block]; | 78 | return preds[IR::PredIndex(variable)][block]; |
| 69 | } | 79 | } |
| 70 | void SetDef(IR::Block* block, IR::Pred variable, const IR::Value& value) noexcept { | 80 | void SetDef(IR::Block* block, IR::Pred variable, const IR::Value& value) { |
| 71 | preds[IR::PredIndex(variable)].insert_or_assign(block, value); | 81 | preds[IR::PredIndex(variable)].insert_or_assign(block, value); |
| 72 | } | 82 | } |
| 73 | 83 | ||
| 74 | const IR::Value& Def(IR::Block* block, GotoVariable variable) noexcept { | 84 | const IR::Value& Def(IR::Block* block, GotoVariable variable) { |
| 75 | return goto_vars[variable.index][block]; | 85 | return goto_vars[variable.index][block]; |
| 76 | } | 86 | } |
| 77 | void SetDef(IR::Block* block, GotoVariable variable, const IR::Value& value) noexcept { | 87 | void SetDef(IR::Block* block, GotoVariable variable, const IR::Value& value) { |
| 78 | goto_vars[variable.index].insert_or_assign(block, value); | 88 | goto_vars[variable.index].insert_or_assign(block, value); |
| 79 | } | 89 | } |
| 80 | 90 | ||
| 81 | const IR::Value& Def(IR::Block* block, IndirectBranchVariable) noexcept { | 91 | const IR::Value& Def(IR::Block* block, LoopSafetyVariable variable) { |
| 92 | return loop_safety_vars[variable.index][block]; | ||
| 93 | } | ||
| 94 | void SetDef(IR::Block* block, LoopSafetyVariable variable, const IR::Value& value) { | ||
| 95 | loop_safety_vars[variable.index].insert_or_assign(block, value); | ||
| 96 | } | ||
| 97 | |||
| 98 | const IR::Value& Def(IR::Block* block, IndirectBranchVariable) { | ||
| 82 | return indirect_branch_var[block]; | 99 | return indirect_branch_var[block]; |
| 83 | } | 100 | } |
| 84 | void SetDef(IR::Block* block, IndirectBranchVariable, const IR::Value& value) noexcept { | 101 | void SetDef(IR::Block* block, IndirectBranchVariable, const IR::Value& value) { |
| 85 | indirect_branch_var.insert_or_assign(block, value); | 102 | indirect_branch_var.insert_or_assign(block, value); |
| 86 | } | 103 | } |
| 87 | 104 | ||
| 88 | const IR::Value& Def(IR::Block* block, ZeroFlagTag) noexcept { | 105 | const IR::Value& Def(IR::Block* block, ZeroFlagTag) { |
| 89 | return zero_flag[block]; | 106 | return zero_flag[block]; |
| 90 | } | 107 | } |
| 91 | void SetDef(IR::Block* block, ZeroFlagTag, const IR::Value& value) noexcept { | 108 | void SetDef(IR::Block* block, ZeroFlagTag, const IR::Value& value) { |
| 92 | zero_flag.insert_or_assign(block, value); | 109 | zero_flag.insert_or_assign(block, value); |
| 93 | } | 110 | } |
| 94 | 111 | ||
| 95 | const IR::Value& Def(IR::Block* block, SignFlagTag) noexcept { | 112 | const IR::Value& Def(IR::Block* block, SignFlagTag) { |
| 96 | return sign_flag[block]; | 113 | return sign_flag[block]; |
| 97 | } | 114 | } |
| 98 | void SetDef(IR::Block* block, SignFlagTag, const IR::Value& value) noexcept { | 115 | void SetDef(IR::Block* block, SignFlagTag, const IR::Value& value) { |
| 99 | sign_flag.insert_or_assign(block, value); | 116 | sign_flag.insert_or_assign(block, value); |
| 100 | } | 117 | } |
| 101 | 118 | ||
| 102 | const IR::Value& Def(IR::Block* block, CarryFlagTag) noexcept { | 119 | const IR::Value& Def(IR::Block* block, CarryFlagTag) { |
| 103 | return carry_flag[block]; | 120 | return carry_flag[block]; |
| 104 | } | 121 | } |
| 105 | void SetDef(IR::Block* block, CarryFlagTag, const IR::Value& value) noexcept { | 122 | void SetDef(IR::Block* block, CarryFlagTag, const IR::Value& value) { |
| 106 | carry_flag.insert_or_assign(block, value); | 123 | carry_flag.insert_or_assign(block, value); |
| 107 | } | 124 | } |
| 108 | 125 | ||
| 109 | const IR::Value& Def(IR::Block* block, OverflowFlagTag) noexcept { | 126 | const IR::Value& Def(IR::Block* block, OverflowFlagTag) { |
| 110 | return overflow_flag[block]; | 127 | return overflow_flag[block]; |
| 111 | } | 128 | } |
| 112 | void SetDef(IR::Block* block, OverflowFlagTag, const IR::Value& value) noexcept { | 129 | void SetDef(IR::Block* block, OverflowFlagTag, const IR::Value& value) { |
| 113 | overflow_flag.insert_or_assign(block, value); | 130 | overflow_flag.insert_or_assign(block, value); |
| 114 | } | 131 | } |
| 115 | 132 | ||
| 116 | std::array<ValueMap, IR::NUM_USER_PREDS> preds; | 133 | std::array<ValueMap, IR::NUM_USER_PREDS> preds; |
| 117 | boost::container::flat_map<u32, ValueMap> goto_vars; | 134 | boost::container::flat_map<u32, ValueMap> goto_vars; |
| 135 | boost::container::flat_map<u32, ValueMap> loop_safety_vars; | ||
| 118 | ValueMap indirect_branch_var; | 136 | ValueMap indirect_branch_var; |
| 119 | ValueMap zero_flag; | 137 | ValueMap zero_flag; |
| 120 | ValueMap sign_flag; | 138 | ValueMap sign_flag; |
| @@ -134,6 +152,10 @@ IR::Opcode UndefOpcode(const FlagTag&) noexcept { | |||
| 134 | return IR::Opcode::UndefU1; | 152 | return IR::Opcode::UndefU1; |
| 135 | } | 153 | } |
| 136 | 154 | ||
| 155 | IR::Opcode UndefOpcode(const LoopSafetyVariable&) noexcept { | ||
| 156 | return IR::Opcode::UndefU32; | ||
| 157 | } | ||
| 158 | |||
| 137 | IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { | 159 | IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { |
| 138 | return IR::Opcode::UndefU32; | 160 | return IR::Opcode::UndefU32; |
| 139 | } | 161 | } |
| @@ -315,6 +337,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { | |||
| 315 | case IR::Opcode::SetGotoVariable: | 337 | case IR::Opcode::SetGotoVariable: |
| 316 | pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); | 338 | pass.WriteVariable(GotoVariable{inst.Arg(0).U32()}, block, inst.Arg(1)); |
| 317 | break; | 339 | break; |
| 340 | case IR::Opcode::SetLoopSafetyVariable: | ||
| 341 | pass.WriteVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block, inst.Arg(0)); | ||
| 342 | break; | ||
| 318 | case IR::Opcode::SetIndirectBranchVariable: | 343 | case IR::Opcode::SetIndirectBranchVariable: |
| 319 | pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0)); | 344 | pass.WriteVariable(IndirectBranchVariable{}, block, inst.Arg(0)); |
| 320 | break; | 345 | break; |
| @@ -343,6 +368,9 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { | |||
| 343 | case IR::Opcode::GetGotoVariable: | 368 | case IR::Opcode::GetGotoVariable: |
| 344 | inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); | 369 | inst.ReplaceUsesWith(pass.ReadVariable(GotoVariable{inst.Arg(0).U32()}, block)); |
| 345 | break; | 370 | break; |
| 371 | case IR::Opcode::GetLoopSafetyVariable: | ||
| 372 | inst.ReplaceUsesWith(pass.ReadVariable(LoopSafetyVariable{inst.Arg(0).U32()}, block)); | ||
| 373 | break; | ||
| 346 | case IR::Opcode::GetIndirectBranchVariable: | 374 | case IR::Opcode::GetIndirectBranchVariable: |
| 347 | inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block)); | 375 | inst.ReplaceUsesWith(pass.ReadVariable(IndirectBranchVariable{}, block)); |
| 348 | break; | 376 | break; |