summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_instructions.h2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp8
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp24
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h2
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp14
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h3
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc2
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp42
-rw-r--r--src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp66
9 files changed, 130 insertions, 33 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
index c9f4826ce..fef9ff9be 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
@@ -42,6 +42,8 @@ void EmitSetGotoVariable(EmitContext& ctx);
42void EmitGetGotoVariable(EmitContext& ctx); 42void EmitGetGotoVariable(EmitContext& ctx);
43void EmitSetIndirectBranchVariable(EmitContext& ctx); 43void EmitSetIndirectBranchVariable(EmitContext& ctx);
44void EmitGetIndirectBranchVariable(EmitContext& ctx); 44void EmitGetIndirectBranchVariable(EmitContext& ctx);
45void EmitSetLoopSafetyVariable(EmitContext& ctx);
46void EmitGetLoopSafetyVariable(EmitContext& ctx);
45void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); 47void EmitGetCbufU8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
46void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); 48void EmitGetCbufS8(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
47void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset); 49void EmitGetCbufU16(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset);
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 95bcbd750..60735fe31 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -153,6 +153,14 @@ void EmitGetIndirectBranchVariable(EmitContext& ctx) {
153 NotImplemented(); 153 NotImplemented();
154} 154}
155 155
156void EmitSetLoopSafetyVariable(EmitContext& ctx) {
157 NotImplemented();
158}
159
160void EmitGetLoopSafetyVariable(EmitContext& ctx) {
161 NotImplemented();
162}
163
156void EmitGetZFlag(EmitContext& ctx) { 164void EmitGetZFlag(EmitContext& ctx) {
157 NotImplemented(); 165 NotImplemented();
158} 166}
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 442a958a5..42fff74e3 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -163,35 +163,43 @@ Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 inde
163} // Anonymous namespace 163} // Anonymous namespace
164 164
165void EmitGetRegister(EmitContext&) { 165void EmitGetRegister(EmitContext&) {
166 throw NotImplementedException("SPIR-V Instruction"); 166 throw LogicError("Unreachable instruction");
167} 167}
168 168
169void EmitSetRegister(EmitContext&) { 169void EmitSetRegister(EmitContext&) {
170 throw NotImplementedException("SPIR-V Instruction"); 170 throw LogicError("Unreachable instruction");
171} 171}
172 172
173void EmitGetPred(EmitContext&) { 173void EmitGetPred(EmitContext&) {
174 throw NotImplementedException("SPIR-V Instruction"); 174 throw LogicError("Unreachable instruction");
175} 175}
176 176
177void EmitSetPred(EmitContext&) { 177void EmitSetPred(EmitContext&) {
178 throw NotImplementedException("SPIR-V Instruction"); 178 throw LogicError("Unreachable instruction");
179} 179}
180 180
181void EmitSetGotoVariable(EmitContext&) { 181void EmitSetGotoVariable(EmitContext&) {
182 throw NotImplementedException("SPIR-V Instruction"); 182 throw LogicError("Unreachable instruction");
183} 183}
184 184
185void EmitGetGotoVariable(EmitContext&) { 185void EmitGetGotoVariable(EmitContext&) {
186 throw NotImplementedException("SPIR-V Instruction"); 186 throw LogicError("Unreachable instruction");
187} 187}
188 188
189void EmitSetIndirectBranchVariable(EmitContext&) { 189void EmitSetIndirectBranchVariable(EmitContext&) {
190 throw NotImplementedException("SPIR-V Instruction"); 190 throw LogicError("Unreachable instruction");
191} 191}
192 192
193void EmitGetIndirectBranchVariable(EmitContext&) { 193void EmitGetIndirectBranchVariable(EmitContext&) {
194 throw NotImplementedException("SPIR-V Instruction"); 194 throw LogicError("Unreachable instruction");
195}
196
197void EmitSetLoopSafetyVariable(EmitContext&) {
198 throw LogicError("Unreachable instruction");
199}
200
201void EmitGetLoopSafetyVariable(EmitContext&) {
202 throw LogicError("Unreachable instruction");
195} 203}
196 204
197Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { 205Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
index 1181e7b4f..e3e5b03fe 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
@@ -43,6 +43,8 @@ void EmitSetGotoVariable(EmitContext& ctx);
43void EmitGetGotoVariable(EmitContext& ctx); 43void EmitGetGotoVariable(EmitContext& ctx);
44void EmitSetIndirectBranchVariable(EmitContext& ctx); 44void EmitSetIndirectBranchVariable(EmitContext& ctx);
45void EmitGetIndirectBranchVariable(EmitContext& ctx); 45void EmitGetIndirectBranchVariable(EmitContext& ctx);
46void EmitSetLoopSafetyVariable(EmitContext& ctx);
47void EmitGetLoopSafetyVariable(EmitContext& ctx);
46Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); 48Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
47Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); 49Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
48Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset); 50Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset);
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index e9fd41237..6c37af5e7 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -125,6 +125,12 @@ U1 IREmitter::GetPred(IR::Pred pred, bool is_negated) {
125 } 125 }
126} 126}
127 127
128void IREmitter::SetPred(IR::Pred pred, const U1& value) {
129 if (pred != IR::Pred::PT) {
130 Inst(Opcode::SetPred, pred, value);
131 }
132}
133
128U1 IREmitter::GetGotoVariable(u32 id) { 134U1 IREmitter::GetGotoVariable(u32 id) {
129 return Inst<U1>(Opcode::GetGotoVariable, id); 135 return Inst<U1>(Opcode::GetGotoVariable, id);
130} 136}
@@ -141,8 +147,12 @@ void IREmitter::SetIndirectBranchVariable(const U32& value) {
141 Inst(Opcode::SetIndirectBranchVariable, value); 147 Inst(Opcode::SetIndirectBranchVariable, value);
142} 148}
143 149
144void IREmitter::SetPred(IR::Pred pred, const U1& value) { 150U32 IREmitter::GetLoopSafetyVariable(u32 id) {
145 Inst(Opcode::SetPred, pred, value); 151 return Inst<U32>(Opcode::GetLoopSafetyVariable, id);
152}
153
154void IREmitter::SetLoopSafetyVariable(u32 id, const U32& counter) {
155 Inst(Opcode::SetLoopSafetyVariable, id, counter);
146} 156}
147 157
148U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) { 158U32 IREmitter::GetCbuf(const U32& binding, const U32& byte_offset) {
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index bb3500c54..7caab1f61 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -55,6 +55,9 @@ public:
55 [[nodiscard]] U32 GetIndirectBranchVariable(); 55 [[nodiscard]] U32 GetIndirectBranchVariable();
56 void SetIndirectBranchVariable(const U32& value); 56 void SetIndirectBranchVariable(const U32& value);
57 57
58 [[nodiscard]] U32 GetLoopSafetyVariable(u32 id);
59 void SetLoopSafetyVariable(u32 id, const U32& counter);
60
58 [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset); 61 [[nodiscard]] U32 GetCbuf(const U32& binding, const U32& byte_offset);
59 [[nodiscard]] Value GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize, 62 [[nodiscard]] Value GetCbuf(const U32& binding, const U32& byte_offset, size_t bitsize,
60 bool is_signed); 63 bool is_signed);
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index 8a8d0d759..e87aeddd5 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -32,6 +32,8 @@ OPCODE(GetGotoVariable, U1, U32,
32OPCODE(SetGotoVariable, Void, U32, U1, ) 32OPCODE(SetGotoVariable, Void, U32, U1, )
33OPCODE(GetIndirectBranchVariable, U32, ) 33OPCODE(GetIndirectBranchVariable, U32, )
34OPCODE(SetIndirectBranchVariable, Void, U32, ) 34OPCODE(SetIndirectBranchVariable, Void, U32, )
35OPCODE(GetLoopSafetyVariable, U32, U32, )
36OPCODE(SetLoopSafetyVariable, Void, U32, U32, )
35OPCODE(GetCbufU8, U32, U32, U32, ) 37OPCODE(GetCbufU8, U32, U32, U32, )
36OPCODE(GetCbufS8, U32, U32, U32, ) 38OPCODE(GetCbufS8, U32, U32, U32, )
37OPCODE(GetCbufU16, U32, U32, U32, ) 39OPCODE(GetCbufU16, U32, U32, U32, )
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index c1e0646e6..b2b8c492a 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -9,11 +9,13 @@
9#include <unordered_map> 9#include <unordered_map>
10#include <utility> 10#include <utility>
11#include <vector> 11#include <vector>
12#include <version>
12 13
13#include <fmt/format.h> 14#include <fmt/format.h>
14 15
15#include <boost/intrusive/list.hpp> 16#include <boost/intrusive/list.hpp>
16 17
18#include "common/settings.h"
17#include "shader_recompiler/environment.h" 19#include "shader_recompiler/environment.h"
18#include "shader_recompiler/frontend/ir/basic_block.h" 20#include "shader_recompiler/frontend/ir/basic_block.h"
19#include "shader_recompiler/frontend/ir/ir_emitter.h" 21#include "shader_recompiler/frontend/ir/ir_emitter.h"
@@ -739,8 +741,25 @@ private:
739 } 741 }
740 case StatementType::Loop: { 742 case StatementType::Loop: {
741 IR::Block* const loop_header_block{block_pool.Create(inst_pool)}; 743 IR::Block* const loop_header_block{block_pool.Create(inst_pool)};
742 if (current_block) { 744 const u32 this_loop_id{loop_id++};
743 current_block->AddBranch(loop_header_block); 745
746 if (Settings::values.disable_shader_loop_safety_checks) {
747 if (current_block) {
748 current_block->AddBranch(loop_header_block);
749 }
750 } else {
751 IR::Block* const init_block{block_pool.Create(inst_pool)};
752 IR::IREmitter ir{*init_block};
753 ir.SetLoopSafetyVariable(this_loop_id, ir.Imm32(0x2000));
754
755 if (current_block) {
756 current_block->AddBranch(init_block);
757 }
758 init_block->AddBranch(loop_header_block);
759
760 auto& init_node{syntax_list.emplace_back()};
761 init_node.type = IR::AbstractSyntaxNode::Type::Block;
762 init_node.data.block = init_block;
744 } 763 }
745 auto& header_node{syntax_list.emplace_back()}; 764 auto& header_node{syntax_list.emplace_back()};
746 header_node.type = IR::AbstractSyntaxNode::Type::Block; 765 header_node.type = IR::AbstractSyntaxNode::Type::Block;
@@ -758,7 +777,16 @@ private:
758 777
759 // The continue block is located at the end of the loop 778 // The continue block is located at the end of the loop
760 IR::IREmitter ir{*continue_block}; 779 IR::IREmitter ir{*continue_block};
761 const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))}; 780 IR::U1 cond{VisitExpr(ir, *stmt.cond)};
781 if (!Settings::values.disable_shader_loop_safety_checks) {
782 const IR::U32 old_counter{ir.GetLoopSafetyVariable(this_loop_id)};
783 const IR::U32 new_counter{ir.ISub(old_counter, ir.Imm32(1))};
784 ir.SetLoopSafetyVariable(this_loop_id, new_counter);
785
786 const IR::U1 safety_cond{ir.INotEqual(new_counter, ir.Imm32(0))};
787 cond = ir.LogicalAnd(cond, safety_cond);
788 }
789 cond = ir.ConditionRef(cond);
762 790
763 IR::Block* const body_block{syntax_list.at(body_block_index).data.block}; 791 IR::Block* const body_block{syntax_list.at(body_block_index).data.block};
764 loop_header_block->AddBranch(body_block); 792 loop_header_block->AddBranch(body_block);
@@ -863,8 +891,14 @@ private:
863 ObjectPool<IR::Block>& block_pool; 891 ObjectPool<IR::Block>& block_pool;
864 Environment& env; 892 Environment& env;
865 IR::AbstractSyntaxList& syntax_list; 893 IR::AbstractSyntaxList& syntax_list;
866 // TODO: Make this constexpr when std::vector is constexpr 894 u32 loop_id{};
895
896// TODO: C++20 Remove this when all compilers support constexpr std::vector
897#if __cpp_lib_constexpr_vector >= 201907
898 static constexpr Flow::Block dummy_flow_block;
899#else
867 const Flow::Block dummy_flow_block; 900 const Flow::Block dummy_flow_block;
901#endif
868}; 902};
869} // Anonymous namespace 903} // Anonymous namespace
870 904
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;