diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/drop.cpp | 54 | ||||
-rw-r--r-- | src/ir/drop.h | 19 | ||||
-rw-r--r-- | src/passes/Directize.cpp | 28 |
3 files changed, 48 insertions, 53 deletions
diff --git a/src/ir/drop.cpp b/src/ir/drop.cpp index 5a860fa29..f732e3730 100644 --- a/src/ir/drop.cpp +++ b/src/ir/drop.cpp @@ -14,9 +14,7 @@ * limitations under the License. */ -#ifndef wasm_ir_drop_h -#define wasm_ir_drop_h - +#include "ir/drop.h" #include "ir/branch-utils.h" #include "ir/effects.h" #include "ir/iteration.h" @@ -25,27 +23,26 @@ namespace wasm { -// Given an expression, returns a new expression that drops the given -// expression's children that cannot be removed outright due to their side -// effects. Note that this only operates on children that execute -// unconditionally. That is the case in almost all expressions, except for those -// with conditional execution, like if, which unconditionally executes the -// condition but then conditionally executes one of the two arms. -Expression* getDroppedChildrenAndAppend(Expression* curr, +Expression* getDroppedChildrenAndAppend(Expression* parent, Module& wasm, const PassOptions& options, - Expression* last) { - // We check for shallow effects here, since we may be able to remove |curr| + Expression* last, + DropMode mode) { + // We check for shallow effects here, since we may be able to remove |parent| // itself but keep its children around - we don't want effects in the children // to stop us from improving the code. Note that there are cases where the - // combined curr+children has fewer effects than curr itself, such as if curr - // is a block and the child branches to it, but in such cases we cannot remove - // curr anyhow (those cases are ruled out below), so looking at non-shallow - // effects would never help us (and would be slower to run). - ShallowEffectAnalyzer effects(options, wasm, curr); - // Ignore a trap, as the unreachable replacement would trap too. - if (last->is<Unreachable>()) { - effects.trap = false; + // combined parent+children has fewer effects than parent itself, such as if + // parent is a block and the child branches to it, but in such cases we cannot + // remove parent anyhow (those cases are ruled out below), so looking at + // non-shallow effects would never help us (and would be slower to run). + bool keepParent = false; + if (mode == DropMode::NoticeParentEffects) { + ShallowEffectAnalyzer effects(options, wasm, parent); + // Ignore a trap, as the unreachable replacement would trap too. + if (last->is<Unreachable>()) { + effects.trap = false; + } + keepParent = effects.hasUnremovableSideEffects(); } // We cannot remove @@ -56,19 +53,18 @@ Expression* getDroppedChildrenAndAppend(Expression* curr, // 5. Branch targets: We will need the target for the branches to it to // validate. Builder builder(wasm); - if (effects.hasUnremovableSideEffects() || curr->is<If>() || - curr->is<Try>() || curr->is<Pop>() || - BranchUtils::getDefinedName(curr).is()) { - // If curr is concrete we must drop it. Or, if it is unreachable or none, + if (keepParent || parent->is<If>() || parent->is<Try>() || + parent->is<Pop>() || BranchUtils::getDefinedName(parent).is()) { + // If parent is concrete we must drop it. Or, if it is unreachable or none, // then we can leave it as it is. - if (curr->type.isConcrete()) { - curr = builder.makeDrop(curr); + if (parent->type.isConcrete()) { + parent = builder.makeDrop(parent); } - return builder.makeSequence(curr, last); + return builder.makeSequence(parent, last); } std::vector<Expression*> contents; - for (auto* child : ChildIterator(curr)) { + for (auto* child : ChildIterator(parent)) { if (!EffectAnalyzer(options, wasm, child).hasUnremovableSideEffects()) { continue; } @@ -87,5 +83,3 @@ Expression* getDroppedChildrenAndAppend(Expression* curr, } } // namespace wasm - -#endif // wasm_ir_drop_h diff --git a/src/ir/drop.h b/src/ir/drop.h index 78ff98c66..c6da166c6 100644 --- a/src/ir/drop.h +++ b/src/ir/drop.h @@ -70,12 +70,19 @@ struct PassOptions; // ) // (appended last item) // -// Also this function preserves other unremovable expressions like trys, pops, -// and named blocks. -Expression* getDroppedChildrenAndAppend(Expression* curr, - Module& wasm, - const PassOptions& options, - Expression* last); +// Also this function preserves other unremovable expressions like trys, pops, +// and named blocks. +// +// We can run in two modes: where we notice parent effects, and in that case we +// won't remove effects there (we'll keep a drop of the parent too), or we can +// ignore parent effects. +enum class DropMode { NoticeParentEffects, IgnoreParentEffects }; +Expression* +getDroppedChildrenAndAppend(Expression* parent, + Module& wasm, + const PassOptions& options, + Expression* last, + DropMode mode = DropMode::NoticeParentEffects); } // namespace wasm diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 21254cda7..3fc7d6c41 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -33,6 +33,7 @@ #include <unordered_map> #include "call-utils.h" +#include "ir/drop.h" #include "ir/table-utils.h" #include "ir/utils.h" #include "pass.h" @@ -170,12 +171,18 @@ private: // We don't know anything here. return; } - // If the index is invalid, or the type is wrong, we can - // emit an unreachable here, since in Binaryen it is ok to - // reorder/replace traps when optimizing (but never to + // If the index is invalid, or the type is wrong, we can skip the call and + // emit an unreachable here (with dropped children as needed), since in + // Binaryen it is ok to reorder/replace traps when optimizing (but never to // remove them, at least not by default). if (std::get_if<CallUtils::Trap>(&info)) { - replaceCurrent(replaceWithUnreachable(operands)); + replaceCurrent( + getDroppedChildrenAndAppend(original, + *getModule(), + getPassOptions(), + Builder(*getModule()).makeUnreachable(), + DropMode::IgnoreParentEffects)); + changedTypes = true; return; } @@ -185,19 +192,6 @@ private: Builder(*getModule()) .makeCall(name, operands, original->type, original->isReturn)); } - - Expression* replaceWithUnreachable(const std::vector<Expression*>& operands) { - // Emitting an unreachable means we must update parent types. - changedTypes = true; - - Builder builder(*getModule()); - std::vector<Expression*> newOperands; - for (auto* operand : operands) { - newOperands.push_back(builder.makeDrop(operand)); - } - return builder.makeSequence(builder.makeBlock(newOperands), - builder.makeUnreachable()); - } }; struct Directize : public Pass { |