summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/ir/microinstruction.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-02-06 02:38:22 -0300
committerGravatar ameerj2021-07-22 21:51:21 -0400
commitda8096e6e35af250dcc56a1af76b8a211df63a90 (patch)
tree5bac3a389afddd1ba23a9fb2ea410c077c28f3b8 /src/shader_recompiler/frontend/ir/microinstruction.cpp
parentshader: Add pools and rename files (diff)
downloadyuzu-da8096e6e35af250dcc56a1af76b8a211df63a90.tar.gz
yuzu-da8096e6e35af250dcc56a1af76b8a211df63a90.tar.xz
yuzu-da8096e6e35af250dcc56a1af76b8a211df63a90.zip
shader: Properly store phi on Inst
Diffstat (limited to 'src/shader_recompiler/frontend/ir/microinstruction.cpp')
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp102
1 files changed, 74 insertions, 28 deletions
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index de953838c..e7ca92039 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <memory>
6 7
7#include "shader_recompiler/exception.h" 8#include "shader_recompiler/exception.h"
8#include "shader_recompiler/frontend/ir/microinstruction.h" 9#include "shader_recompiler/frontend/ir/microinstruction.h"
@@ -30,6 +31,22 @@ static void RemovePseudoInstruction(IR::Inst*& inst, IR::Opcode expected_opcode)
30 inst = nullptr; 31 inst = nullptr;
31} 32}
32 33
34Inst::Inst(IR::Opcode op_, u64 flags_) noexcept : op{op_}, flags{flags_} {
35 if (op == Opcode::Phi) {
36 std::construct_at(&phi_args);
37 } else {
38 std::construct_at(&args);
39 }
40}
41
42Inst::~Inst() {
43 if (op == Opcode::Phi) {
44 std::destroy_at(&phi_args);
45 } else {
46 std::destroy_at(&args);
47 }
48}
49
33bool Inst::MayHaveSideEffects() const noexcept { 50bool Inst::MayHaveSideEffects() const noexcept {
34 switch (op) { 51 switch (op) {
35 case Opcode::Branch: 52 case Opcode::Branch:
@@ -71,7 +88,10 @@ bool Inst::IsPseudoInstruction() const noexcept {
71 } 88 }
72} 89}
73 90
74bool Inst::AreAllArgsImmediates() const noexcept { 91bool Inst::AreAllArgsImmediates() const {
92 if (op == Opcode::Phi) {
93 throw LogicError("Testing for all arguments are immediates on phi instruction");
94 }
75 return std::all_of(args.begin(), args.begin() + NumArgs(), 95 return std::all_of(args.begin(), args.begin() + NumArgs(),
76 [](const IR::Value& value) { return value.IsImmediate(); }); 96 [](const IR::Value& value) { return value.IsImmediate(); });
77} 97}
@@ -101,7 +121,7 @@ Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) {
101} 121}
102 122
103size_t Inst::NumArgs() const { 123size_t Inst::NumArgs() const {
104 return NumArgsOf(op); 124 return op == Opcode::Phi ? phi_args.size() : NumArgsOf(op);
105} 125}
106 126
107IR::Type Inst::Type() const { 127IR::Type Inst::Type() const {
@@ -109,13 +129,23 @@ IR::Type Inst::Type() const {
109} 129}
110 130
111Value Inst::Arg(size_t index) const { 131Value Inst::Arg(size_t index) const {
112 if (index >= NumArgsOf(op)) { 132 if (op == Opcode::Phi) {
113 throw InvalidArgument("Out of bounds argument index {} in opcode {}", index, op); 133 if (index >= phi_args.size()) {
134 throw InvalidArgument("Out of bounds argument index {} in phi instruction", index);
135 }
136 return phi_args[index].second;
137 } else {
138 if (index >= NumArgsOf(op)) {
139 throw InvalidArgument("Out of bounds argument index {} in opcode {}", index, op);
140 }
141 return args[index];
114 } 142 }
115 return args[index];
116} 143}
117 144
118void Inst::SetArg(size_t index, Value value) { 145void Inst::SetArg(size_t index, Value value) {
146 if (op == Opcode::Phi) {
147 throw LogicError("Setting argument on a phi instruction");
148 }
119 if (index >= NumArgsOf(op)) { 149 if (index >= NumArgsOf(op)) {
120 throw InvalidArgument("Out of bounds argument index {} in opcode {}", index, op); 150 throw InvalidArgument("Out of bounds argument index {} in opcode {}", index, op);
121 } 151 }
@@ -128,15 +158,21 @@ void Inst::SetArg(size_t index, Value value) {
128 args[index] = value; 158 args[index] = value;
129} 159}
130 160
131std::span<const std::pair<Block*, Value>> Inst::PhiOperands() const noexcept { 161Block* Inst::PhiBlock(size_t index) const {
132 return phi_operands; 162 if (op != Opcode::Phi) {
163 throw LogicError("{} is not a Phi instruction", op);
164 }
165 if (index >= phi_args.size()) {
166 throw InvalidArgument("Out of bounds argument index {} in phi instruction");
167 }
168 return phi_args[index].first;
133} 169}
134 170
135void Inst::AddPhiOperand(Block* predecessor, const Value& value) { 171void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
136 if (!value.IsImmediate()) { 172 if (!value.IsImmediate()) {
137 Use(value); 173 Use(value);
138 } 174 }
139 phi_operands.emplace_back(predecessor, value); 175 phi_args.emplace_back(predecessor, value);
140} 176}
141 177
142void Inst::Invalidate() { 178void Inst::Invalidate() {
@@ -145,18 +181,22 @@ void Inst::Invalidate() {
145} 181}
146 182
147void Inst::ClearArgs() { 183void Inst::ClearArgs() {
148 for (auto& value : args) { 184 if (op == Opcode::Phi) {
149 if (!value.IsImmediate()) { 185 for (auto& pair : phi_args) {
150 UndoUse(value); 186 IR::Value& value{pair.second};
187 if (!value.IsImmediate()) {
188 UndoUse(value);
189 }
151 } 190 }
152 value = {}; 191 phi_args.clear();
153 } 192 } else {
154 for (auto& [phi_block, phi_op] : phi_operands) { 193 for (auto& value : args) {
155 if (!phi_op.IsImmediate()) { 194 if (!value.IsImmediate()) {
156 UndoUse(phi_op); 195 UndoUse(value);
196 }
197 value = {};
157 } 198 }
158 } 199 }
159 phi_operands.clear();
160} 200}
161 201
162void Inst::ReplaceUsesWith(Value replacement) { 202void Inst::ReplaceUsesWith(Value replacement) {
@@ -167,24 +207,29 @@ void Inst::ReplaceUsesWith(Value replacement) {
167 if (!replacement.IsImmediate()) { 207 if (!replacement.IsImmediate()) {
168 Use(replacement); 208 Use(replacement);
169 } 209 }
170 args[0] = replacement; 210 if (op == Opcode::Phi) {
211 phi_args[0].second = replacement;
212 } else {
213 args[0] = replacement;
214 }
171} 215}
172 216
173void Inst::Use(const Value& value) { 217void Inst::Use(const Value& value) {
174 ++value.Inst()->use_count; 218 Inst* const inst{value.Inst()};
219 ++inst->use_count;
175 220
176 switch (op) { 221 switch (op) {
177 case Opcode::GetZeroFromOp: 222 case Opcode::GetZeroFromOp:
178 SetPseudoInstruction(value.Inst()->zero_inst, this); 223 SetPseudoInstruction(inst->zero_inst, this);
179 break; 224 break;
180 case Opcode::GetSignFromOp: 225 case Opcode::GetSignFromOp:
181 SetPseudoInstruction(value.Inst()->sign_inst, this); 226 SetPseudoInstruction(inst->sign_inst, this);
182 break; 227 break;
183 case Opcode::GetCarryFromOp: 228 case Opcode::GetCarryFromOp:
184 SetPseudoInstruction(value.Inst()->carry_inst, this); 229 SetPseudoInstruction(inst->carry_inst, this);
185 break; 230 break;
186 case Opcode::GetOverflowFromOp: 231 case Opcode::GetOverflowFromOp:
187 SetPseudoInstruction(value.Inst()->overflow_inst, this); 232 SetPseudoInstruction(inst->overflow_inst, this);
188 break; 233 break;
189 default: 234 default:
190 break; 235 break;
@@ -192,20 +237,21 @@ void Inst::Use(const Value& value) {
192} 237}
193 238
194void Inst::UndoUse(const Value& value) { 239void Inst::UndoUse(const Value& value) {
195 --value.Inst()->use_count; 240 Inst* const inst{value.Inst()};
241 --inst->use_count;
196 242
197 switch (op) { 243 switch (op) {
198 case Opcode::GetZeroFromOp: 244 case Opcode::GetZeroFromOp:
199 RemovePseudoInstruction(value.Inst()->zero_inst, Opcode::GetZeroFromOp); 245 RemovePseudoInstruction(inst->zero_inst, Opcode::GetZeroFromOp);
200 break; 246 break;
201 case Opcode::GetSignFromOp: 247 case Opcode::GetSignFromOp:
202 RemovePseudoInstruction(value.Inst()->sign_inst, Opcode::GetSignFromOp); 248 RemovePseudoInstruction(inst->sign_inst, Opcode::GetSignFromOp);
203 break; 249 break;
204 case Opcode::GetCarryFromOp: 250 case Opcode::GetCarryFromOp:
205 RemovePseudoInstruction(value.Inst()->carry_inst, Opcode::GetCarryFromOp); 251 RemovePseudoInstruction(inst->carry_inst, Opcode::GetCarryFromOp);
206 break; 252 break;
207 case Opcode::GetOverflowFromOp: 253 case Opcode::GetOverflowFromOp:
208 RemovePseudoInstruction(value.Inst()->overflow_inst, Opcode::GetOverflowFromOp); 254 RemovePseudoInstruction(inst->overflow_inst, Opcode::GetOverflowFromOp);
209 break; 255 break;
210 default: 256 default:
211 break; 257 break;