Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HansKristian-Work/dxil-spirv.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2022-08-31 13:03:54 +0300
committerGitHub <noreply@github.com>2022-08-31 13:03:54 +0300
commit8a5c20fe2a9ad26c5864ee48080654c764af5168 (patch)
treed0ca9c909dbc4f2251bb8ecb45397f4605aeabe5
parent70821852ac3e81dffab220fb69faf1add0f742f4 (diff)
parent834fefa050944833e23ab76da507fe3c92e5a970 (diff)
Merge pull request #125 from HansKristian-Work/infinite-loop-fixes
Handle more cases where we need to rewrite infinite loops.
-rw-r--r--cfg_structurizer.cpp31
1 files changed, 27 insertions, 4 deletions
diff --git a/cfg_structurizer.cpp b/cfg_structurizer.cpp
index 41ee5f8..11cee8d 100644
--- a/cfg_structurizer.cpp
+++ b/cfg_structurizer.cpp
@@ -1034,6 +1034,21 @@ void CFGStructurizer::insert_phi()
for (auto *op : node->ir.operations)
if (op->id)
value_id_to_block[op->id] = node;
+
+ // If we inserted dummy branches from back-edge to rewrite infinite loops, we must prune these branches
+ // now, so we don't end up creating a wrong amount of PHI incoming values.
+ // We don't have to recompute the CFG since we don't really care about post-visit orders at this stage.
+ if (node->pred_back_edge && node->pred_back_edge->ir.terminator.type == Terminator::Type::Branch &&
+ node->pred_back_edge->succ_back_edge == node->pred_back_edge->ir.terminator.direct_block &&
+ node->pred_back_edge->succ.size() == 1)
+ {
+ auto *back_edge = node->pred_back_edge;
+ auto *succ = back_edge->succ.front();
+ back_edge->succ.clear();
+ auto itr = std::find(succ->pred.begin(), succ->pred.end(), back_edge);
+ assert(itr != succ->pred.end());
+ succ->pred.erase(itr);
+ }
}
// Resolve phi-nodes top-down since PHI nodes may depend on other PHI nodes.
@@ -1651,15 +1666,23 @@ void CFGStructurizer::backwards_visit()
return a->forward_post_visit_order > b->forward_post_visit_order;
});
- bool exit_is_pure_return = false;
+ bool transpose_loop_exit = false;
if (exits.size() == 1)
{
auto *exit_node = exits.front();
- exit_is_pure_return = exit_node->ir.phi.empty() && exit_node->ir.operations.empty() &&
- exit_node->ir.terminator.type == Terminator::Type::Return;
+ // If this is true, we never really leave the loop, which is problematic.
+ transpose_loop_exit = exit_node->dominates_all_reachable_exits();
+
+ // Only transpose if we're the innermost header, otherwise, inner loops which try to branch
+ // to the return will be considered a multi-break which is very awkward.
+ if (transpose_loop_exit)
+ {
+ auto *innermost_header = get_innermost_loop_header_for(node, exit_node);
+ transpose_loop_exit = innermost_header == node;
+ }
}
- if (exit_is_pure_return)
+ if (transpose_loop_exit)
{
for (auto *f : exits)
node->pred_back_edge->add_branch(f);