diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-31 17:31:35 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-31 17:52:59 +0300 |
commit | 00973cea25907124926db3d35d8cb8710a915b34 (patch) | |
tree | 99275ae210e1a899c3b3bf67217d1c64f29a4a7c | |
parent | 76b6e8a4e713124fd731710ccaa5e17f7bde5b7b (diff) |
Do not attempt to rewrite loops if outer header does not dominate inner.
-rw-r--r-- | cfg_structurizer.cpp | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/cfg_structurizer.cpp b/cfg_structurizer.cpp index c7497ae..490fe65 100644 --- a/cfg_structurizer.cpp +++ b/cfg_structurizer.cpp @@ -3138,8 +3138,10 @@ void CFGStructurizer::find_loops() CFGNode *CFGStructurizer::get_target_break_block_for_inner_header(const CFGNode *node, size_t header_index) { + CFGNode *inner_header = node->headers[header_index]; CFGNode *target_header = nullptr; - for (size_t j = header_index; j; j--) + + for (size_t j = header_index; j && !target_header; j--) { if (node->headers[j - 1]->merge == MergeType::Loop) { @@ -3153,11 +3155,19 @@ CFGNode *CFGStructurizer::get_target_break_block_for_inner_header(const CFGNode else if (candidate_header->loop_merge_block) candidate_merge = candidate_header->loop_merge_block; - if (candidate_merge && !query_reachability(*candidate_merge, *node->headers[header_index])) - { - target_header = candidate_header; - break; - } + if (!candidate_merge) + continue; + + // Check for backwards branch. + if (query_reachability(*candidate_merge, *node->headers[header_index])) + continue; + + // An outer header is expected to dominate the inner header. Otherwise, they live in + // separate scopes, and we should look for a header that is further out. + if (!candidate_header->dominates(inner_header)) + continue; + + target_header = candidate_header; } } |