diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast_utils.h | 20 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 6 |
2 files changed, 13 insertions, 13 deletions
diff --git a/src/ast_utils.h b/src/ast_utils.h index 4664f22ae..ff5d93e02 100644 --- a/src/ast_utils.h +++ b/src/ast_utils.h @@ -51,12 +51,14 @@ struct BreakSeeker : public PostWalker<BreakSeeker, Visitor<BreakSeeker>> { } static bool has(Expression* tree, Name target) { + if (!target.is()) return false; BreakSeeker breakSeeker(target); breakSeeker.walk(tree); return breakSeeker.found > 0; } static Index count(Expression* tree, Name target) { + if (!target.is()) return 0; BreakSeeker breakSeeker(target); breakSeeker.walk(tree); return breakSeeker.found; @@ -425,18 +427,16 @@ struct ExpressionAnalyzer { return !curr->condition && !curr->value; } - // Checks if an expression ends with a simple break, - // and returns a pointer to it if so. - // (It might also have other internal branches.) - static Expression* getEndingSimpleBreak(Expression* curr) { + // Checks if an expression does not flow out in an obvious way. + // We return true if it cannot flow out. If it can flow out, we + // might still return true, as the analysis here is simple and fast. + static bool obviouslyDoesNotFlowOut(Expression* curr) { if (auto* br = curr->dynCast<Break>()) { - if (isSimple(br)) return br; - return nullptr; + if (!br->condition) return true; + } else if (auto* block = curr->dynCast<Block>()) { + if (block->list.size() > 0 && obviouslyDoesNotFlowOut(block->list.back()) && !BreakSeeker::has(block, block->name)) return true; } - if (auto* block = curr->dynCast<Block>()) { - if (block->list.size() > 0) return getEndingSimpleBreak(block->list.back()); - } - return nullptr; + return false; } template<typename T> diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 86a46374f..fa8ab2f6c 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -218,7 +218,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R // let's try to move the code going to the top of the loop into the if-else if (!iff->ifFalse) { // we need the ifTrue to break, so it cannot reach the code we want to move - if (ExpressionAnalyzer::getEndingSimpleBreak(iff->ifTrue)) { + if (ExpressionAnalyzer::obviouslyDoesNotFlowOut(iff->ifTrue)) { iff->ifFalse = builder.stealSlice(block, i + 1, list.size()); return true; } @@ -226,10 +226,10 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R // this is already an if-else. if one side is a dead end, we can append to the other, if // there is no returned value to concern us assert(!isConcreteWasmType(iff->type)); // can't be, since in the middle of a block - if (ExpressionAnalyzer::getEndingSimpleBreak(iff->ifTrue)) { + if (ExpressionAnalyzer::obviouslyDoesNotFlowOut(iff->ifTrue)) { iff->ifFalse = builder.blockifyMerge(iff->ifFalse, builder.stealSlice(block, i + 1, list.size())); return true; - } else if (ExpressionAnalyzer::getEndingSimpleBreak(iff->ifFalse)) { + } else if (ExpressionAnalyzer::obviouslyDoesNotFlowOut(iff->ifFalse)) { iff->ifTrue = builder.blockifyMerge(iff->ifTrue, builder.stealSlice(block, i + 1, list.size())); return true; } |