summaryrefslogtreecommitdiff
path: root/src/ir/drop.cpp
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2022-07-25 15:16:43 -0700
committerGitHub <noreply@github.com>2022-07-25 15:16:43 -0700
commitc40b402aaffa24c641cbb0e8efd0019c5c4a68b6 (patch)
tree0594369dd49ac2511c80bf440932300d9bb9b8f3 /src/ir/drop.cpp
parent7c2b3ebd518b26c01fda9db8cb2a1911c23bed2a (diff)
downloadbinaryen-c40b402aaffa24c641cbb0e8efd0019c5c4a68b6.tar.gz
binaryen-c40b402aaffa24c641cbb0e8efd0019c5c4a68b6.tar.bz2
binaryen-c40b402aaffa24c641cbb0e8efd0019c5c4a68b6.zip
Move method implementations to drop.cpp (#4823)
Now that we have `getDroppedUnconditionalChildrenAndAppend`, all passes need to use it rather than the old `getDroppedChildrenAndAppend`, which is used within the new method `getDroppedUnconditionalChildrenAndAppend`. This creates `drop.cpp` and move method implementations in drop.h there, and merge two methods given that the old method is not supposed to be used from outside anyway, and drops `Unconditional` from the new method name because this is the only method and doesn't have to be specific about that.
Diffstat (limited to 'src/ir/drop.cpp')
-rw-r--r--src/ir/drop.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/ir/drop.cpp b/src/ir/drop.cpp
new file mode 100644
index 000000000..14ab43794
--- /dev/null
+++ b/src/ir/drop.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2022 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ir_drop_h
+#define wasm_ir_drop_h
+
+#include "ir/branch-utils.h"
+#include "ir/effects.h"
+#include "ir/iteration.h"
+#include "wasm-builder.h"
+#include "wasm.h"
+
+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,
+ Module& wasm,
+ const PassOptions& options,
+ Expression* last) {
+ // We check for shallow effects here, since we may be able to remove |curr|
+ // 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->type == Type::unreachable) {
+ effects.trap = false;
+ }
+
+ // We cannot remove
+ // 1. Expressions with unremovable side effects
+ // 2. if: 'if's contains conditional expressions
+ // 3. try: Removing a try could leave a pop without a proper parent
+ // 4. pop: Pops are struturally necessary in catch bodies
+ // 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()) {
+ return builder.makeSequence(builder.makeDrop(curr), last);
+ }
+
+ std::vector<Expression*> contents;
+ for (auto* child : ChildIterator(curr)) {
+ if (!EffectAnalyzer(options, wasm, child).hasUnremovableSideEffects()) {
+ continue;
+ }
+ if (child->type.isConcrete()) {
+ contents.push_back(builder.makeDrop(child));
+ } else {
+ // The child is unreachable, or none (none is possible as a child of a
+ // block or loop, etc.); in both cases we do not need a drop.
+ contents.push_back(child);
+ }
+ }
+ contents.push_back(last);
+ if (contents.size() == 1) {
+ return contents[0];
+ }
+ return builder.makeBlock(contents);
+}
+
+} // namespace wasm
+
+#endif // wasm_ir_drop_h