summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend')
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp77
1 files changed, 28 insertions, 49 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index 6021ac891..b85b613f3 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -222,27 +222,6 @@ std::string DumpTree(const Tree& tree, u32 indentation = 0) {
222 return ret; 222 return ret;
223} 223}
224 224
225bool HasNode(const Tree& tree, ConstNode stmt) {
226 const auto end{tree.end()};
227 for (auto it = tree.begin(); it != end; ++it) {
228 if (it == stmt || (HasChildren(it->type) && HasNode(it->children, stmt))) {
229 return true;
230 }
231 }
232 return false;
233}
234
235Node FindStatementWithLabel(Tree& tree, ConstNode goto_stmt) {
236 const ConstNode label_stmt{goto_stmt->label};
237 const ConstNode end{tree.end()};
238 for (auto it = tree.begin(); it != end; ++it) {
239 if (it == label_stmt || (HasChildren(it->type) && HasNode(it->children, label_stmt))) {
240 return it;
241 }
242 }
243 throw LogicError("Lift label not in tree");
244}
245
246void SanitizeNoBreaks(const Tree& tree) { 225void SanitizeNoBreaks(const Tree& tree) {
247 if (std::ranges::find(tree, StatementType::Break, &Statement::type) != tree.end()) { 226 if (std::ranges::find(tree, StatementType::Break, &Statement::type) != tree.end()) {
248 throw NotImplementedException("Capturing statement with break nodes"); 227 throw NotImplementedException("Capturing statement with break nodes");
@@ -288,22 +267,6 @@ bool IsIndirectlyRelated(Node goto_stmt, Node label_stmt) {
288 return goto_stmt->up != label_stmt->up && !IsDirectlyRelated(goto_stmt, label_stmt); 267 return goto_stmt->up != label_stmt->up && !IsDirectlyRelated(goto_stmt, label_stmt);
289} 268}
290 269
291bool SearchNode(const Tree& tree, ConstNode stmt, size_t& offset) {
292 ++offset;
293
294 const auto end = tree.end();
295 for (ConstNode it = tree.begin(); it != end; ++it) {
296 ++offset;
297 if (stmt == it) {
298 return true;
299 }
300 if (HasChildren(it->type) && SearchNode(it->children, stmt, offset)) {
301 return true;
302 }
303 }
304 return false;
305}
306
307bool AreSiblings(Node goto_stmt, Node label_stmt) noexcept { 270bool AreSiblings(Node goto_stmt, Node label_stmt) noexcept {
308 Node it{goto_stmt}; 271 Node it{goto_stmt};
309 do { 272 do {
@@ -321,6 +284,30 @@ bool AreSiblings(Node goto_stmt, Node label_stmt) noexcept {
321 return false; 284 return false;
322} 285}
323 286
287Node SiblingFromNephew(Node uncle, Node nephew) noexcept {
288 Statement* const parent{uncle->up};
289 Statement* it{&*nephew};
290 while (it->up != parent) {
291 it = it->up;
292 }
293 return Tree::s_iterator_to(*it);
294}
295
296bool AreOrdered(Node left_sibling, Node right_sibling) noexcept {
297 const Node end{right_sibling->up->children.end()};
298 for (auto it = right_sibling; it != end; ++it) {
299 if (it == left_sibling) {
300 return false;
301 }
302 }
303 return true;
304}
305
306bool NeedsLift(Node goto_stmt, Node label_stmt) noexcept {
307 const Node sibling{SiblingFromNephew(goto_stmt, label_stmt)};
308 return AreOrdered(sibling, goto_stmt);
309}
310
324class GotoPass { 311class GotoPass {
325public: 312public:
326 explicit GotoPass(Flow::CFG& cfg, ObjectPool<IR::Inst>& inst_pool_, 313 explicit GotoPass(Flow::CFG& cfg, ObjectPool<IR::Inst>& inst_pool_,
@@ -358,7 +345,7 @@ private:
358 --goto_level; 345 --goto_level;
359 } 346 }
360 } else { // Level(goto_stmt) < Level(label_stmt) 347 } else { // Level(goto_stmt) < Level(label_stmt)
361 if (Offset(goto_stmt) > Offset(label_stmt)) { 348 if (NeedsLift(goto_stmt, label_stmt)) {
362 // Lift goto_stmt to above stmt containing label_stmt using goto-lifting 349 // Lift goto_stmt to above stmt containing label_stmt using goto-lifting
363 // transformations 350 // transformations
364 goto_stmt = Lift(goto_stmt); 351 goto_stmt = Lift(goto_stmt);
@@ -378,7 +365,7 @@ private:
378 if (std::next(goto_stmt) == label_stmt) { 365 if (std::next(goto_stmt) == label_stmt) {
379 // Simply eliminate the goto if the label is next to it 366 // Simply eliminate the goto if the label is next to it
380 goto_stmt->up->children.erase(goto_stmt); 367 goto_stmt->up->children.erase(goto_stmt);
381 } else if (Offset(goto_stmt) < Offset(label_stmt)) { 368 } else if (AreOrdered(goto_stmt, label_stmt)) {
382 // Eliminate goto_stmt with a conditional 369 // Eliminate goto_stmt with a conditional
383 EliminateAsConditional(goto_stmt, label_stmt); 370 EliminateAsConditional(goto_stmt, label_stmt);
384 } else { 371 } else {
@@ -523,8 +510,8 @@ private:
523 [[nodiscard]] Node MoveInward(Node goto_stmt) { 510 [[nodiscard]] Node MoveInward(Node goto_stmt) {
524 Statement* const parent{goto_stmt->up}; 511 Statement* const parent{goto_stmt->up};
525 Tree& body{parent->children}; 512 Tree& body{parent->children};
526 const Node label_nested_stmt{FindStatementWithLabel(body, goto_stmt)};
527 const Node label{goto_stmt->label}; 513 const Node label{goto_stmt->label};
514 const Node label_nested_stmt{SiblingFromNephew(goto_stmt, label)};
528 const u32 label_id{label->id}; 515 const u32 label_id{label->id};
529 516
530 Statement* const goto_cond{goto_stmt->cond}; 517 Statement* const goto_cond{goto_stmt->cond};
@@ -562,7 +549,7 @@ private:
562 Tree& body{parent->children}; 549 Tree& body{parent->children};
563 const Node label{goto_stmt->label}; 550 const Node label{goto_stmt->label};
564 const u32 label_id{label->id}; 551 const u32 label_id{label->id};
565 const Node label_nested_stmt{FindStatementWithLabel(body, goto_stmt)}; 552 const Node label_nested_stmt{SiblingFromNephew(goto_stmt, label)};
566 553
567 Tree loop_body; 554 Tree loop_body;
568 loop_body.splice(loop_body.begin(), body, label_nested_stmt, goto_stmt); 555 loop_body.splice(loop_body.begin(), body, label_nested_stmt, goto_stmt);
@@ -627,14 +614,6 @@ private:
627 return parent_tree.insert(std::next(loop), *new_goto); 614 return parent_tree.insert(std::next(loop), *new_goto);
628 } 615 }
629 616
630 size_t Offset(ConstNode stmt) const {
631 size_t offset{0};
632 if (!SearchNode(root_stmt.children, stmt, offset)) {
633 throw LogicError("Node not found in tree");
634 }
635 return offset;
636 }
637
638 ObjectPool<IR::Inst>& inst_pool; 617 ObjectPool<IR::Inst>& inst_pool;
639 ObjectPool<IR::Block>& block_pool; 618 ObjectPool<IR::Block>& block_pool;
640 ObjectPool<Statement>& pool; 619 ObjectPool<Statement>& pool;