diff options
author | Alon Zakai <azakai@google.com> | 2021-05-05 19:12:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-05 19:12:50 -0700 |
commit | 4687c85d38540a9840cb0f5208b684ddbb88b650 (patch) | |
tree | 514c4d9a36264013cd97dc972da3cc7af6149843 /src | |
parent | 16dc2d06041473b838e5486a620e53416ff7e9fd (diff) | |
download | binaryen-4687c85d38540a9840cb0f5208b684ddbb88b650.tar.gz binaryen-4687c85d38540a9840cb0f5208b684ddbb88b650.tar.bz2 binaryen-4687c85d38540a9840cb0f5208b684ddbb88b650.zip |
Refactor getFallthrough() to use a loop instead of recursion. NFC (#3859)
A new getImmediateFallthrough is called in the loop.
Aside from this being more efficient than recursion, the new method will
be used in escape analysis.
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/properties.h | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/src/ir/properties.h b/src/ir/properties.h index 379a85708..fdf31f4e2 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -223,12 +223,18 @@ inline Index getZeroExtBits(Expression* curr) { // and other operations that receive a value and let it flow through them. If // there is no value falling through, returns the node itself (as that is the // value that trivially falls through, with 0 steps in the middle). +// // Note that this returns the value that would fall through if one does in fact // do so. For example, the final element in a block may not fall through if we // hit a return or a trap or an exception is thrown before we get there. -inline Expression* getFallthrough(Expression* curr, - const PassOptions& passOptions, - FeatureSet features) { +// +// This method returns the 'immediate' fallthrough, that is, the immediate +// child of this expression. See getFallthrough for a method that looks all the +// way to the final value falling through, potentially through multiple +// intermediate expressions. +inline Expression* getImmediateFallthrough(Expression* curr, + const PassOptions& passOptions, + FeatureSet features) { // If the current node is unreachable, there is no value // falling through. if (curr->type == Type::unreachable) { @@ -236,42 +242,56 @@ inline Expression* getFallthrough(Expression* curr, } if (auto* set = curr->dynCast<LocalSet>()) { if (set->isTee()) { - return getFallthrough(set->value, passOptions, features); + return set->value; } } else if (auto* block = curr->dynCast<Block>()) { // if no name, we can't be broken to, and then can look at the fallthrough if (!block->name.is() && block->list.size() > 0) { - return getFallthrough(block->list.back(), passOptions, features); + return block->list.back(); } } else if (auto* loop = curr->dynCast<Loop>()) { - return getFallthrough(loop->body, passOptions, features); + return loop->body; } else if (auto* iff = curr->dynCast<If>()) { if (iff->ifFalse) { // Perhaps just one of the two actually returns. if (iff->ifTrue->type == Type::unreachable) { - return getFallthrough(iff->ifFalse, passOptions, features); + return iff->ifFalse; } else if (iff->ifFalse->type == Type::unreachable) { - return getFallthrough(iff->ifTrue, passOptions, features); + return iff->ifTrue; } } } else if (auto* br = curr->dynCast<Break>()) { if (br->condition && br->value) { - return getFallthrough(br->value, passOptions, features); + return br->value; } } else if (auto* tryy = curr->dynCast<Try>()) { if (!EffectAnalyzer(passOptions, features, tryy->body).throws) { - return getFallthrough(tryy->body, passOptions, features); + return tryy->body; } } else if (auto* as = curr->dynCast<RefCast>()) { - return getFallthrough(as->ref, passOptions, features); + return as->ref; } else if (auto* as = curr->dynCast<RefAs>()) { - return getFallthrough(as->value, passOptions, features); + return as->value; } else if (auto* br = curr->dynCast<BrOn>()) { - return getFallthrough(br->ref, passOptions, features); + return br->ref; } return curr; } +// Similar to getImmediateFallthrough, but looks through multiple children to +// find the final value that falls through. +inline Expression* getFallthrough(Expression* curr, + const PassOptions& passOptions, + FeatureSet features) { + while (1) { + auto* next = getImmediateFallthrough(curr, passOptions, features); + if (next == curr) { + return curr; + } + curr = next; + } +} + // Returns whether the resulting value here must fall through without being // modified. For example, a tee always does so. That is, this returns false if // and only if the return value may have some computation performed on it to |