summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/drop.cpp54
-rw-r--r--src/ir/drop.h19
-rw-r--r--src/passes/Directize.cpp28
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 {