summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
diff options
context:
space:
mode:
authorGravatar lat9nq2021-07-08 17:22:31 -0400
committerGravatar ameerj2021-07-22 21:51:35 -0400
commit373f75d944473731408d7a72c967d5c4b37af5bb (patch)
treea6af34845e9cae1429bbd004a36b324bb02f9932 /src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp
parentshader: Comment why the array component is not read in TMML (diff)
downloadyuzu-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.cpp66
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
51struct 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
51struct IndirectBranchVariable { 60struct IndirectBranchVariable {
52 auto operator<=>(const IndirectBranchVariable&) const noexcept = default; 61 auto operator<=>(const IndirectBranchVariable&) const noexcept = default;
53}; 62};
54 63
55using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, 64using Variant =
56 OverflowFlagTag, GotoVariable, IndirectBranchVariable>; 65 std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, OverflowFlagTag,
57using ValueMap = boost::container::flat_map<IR::Block*, IR::Value, std::less<IR::Block*>>; 66 GotoVariable, LoopSafetyVariable, IndirectBranchVariable>;
67using ValueMap = boost::container::flat_map<IR::Block*, IR::Value>;
58 68
59struct DefTable { 69struct 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
155IR::Opcode UndefOpcode(const LoopSafetyVariable&) noexcept {
156 return IR::Opcode::UndefU32;
157}
158
137IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept { 159IR::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;