summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-09-13 14:27:10 -0700
committerGitHub <noreply@github.com>2021-09-13 14:27:10 -0700
commit181b0e7037bc2999a24cb45a02523f3da04b254d (patch)
tree6f03f5577b2b819cd6bcfd03f6533f146e05f8bd /src
parentec2c5df877c479855bd13d280b98220e50bb99f9 (diff)
downloadbinaryen-181b0e7037bc2999a24cb45a02523f3da04b254d.tar.gz
binaryen-181b0e7037bc2999a24cb45a02523f3da04b254d.tar.bz2
binaryen-181b0e7037bc2999a24cb45a02523f3da04b254d.zip
RemoveUnusedBrs::tablify() improvements: handle EqZ and tee (#4144)
tablify() attempts to turns a sequence of br_ifs into a single br_table. This PR adds some flexibility to the specific pattern it looks for, specifically: * Accept i32.eqz as a comparison to zero, and not just to look for i32.eq against a constant. * Allow the first condition to be a tee. If it is, compare later conditions to local.get of that local. This will allow more br_tables to be emitted in j2cl output.
Diffstat (limited to 'src')
-rw-r--r--src/passes/RemoveUnusedBrs.cpp49
1 files changed, 40 insertions, 9 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index ea8a66612..9861695e0 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -1316,7 +1316,15 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// dce will clean it up
return nullptr;
}
- auto* binary = br->condition->dynCast<Binary>();
+ auto* condition = br->condition;
+ // Also support eqz, which is the same as == 0.
+ if (auto* unary = condition->dynCast<Unary>()) {
+ if (unary->op == EqZInt32) {
+ return br;
+ }
+ return nullptr;
+ }
+ auto* binary = condition->dynCast<Binary>();
if (!binary) {
return nullptr;
}
@@ -1342,16 +1350,29 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
if (!br) {
return nullptr;
}
- return br->condition->cast<Binary>()->left;
+ auto* condition = br->condition;
+ if (auto* binary = condition->dynCast<Binary>()) {
+ return binary->left;
+ } else if (auto* unary = condition->dynCast<Unary>()) {
+ assert(unary->op == EqZInt32);
+ return unary->value;
+ } else {
+ WASM_UNREACHABLE("invalid br_if condition");
+ }
};
// returns the constant value, as a uint32_t
auto getProperBrIfConstant =
[&getProperBrIf](Expression* curr) -> uint32_t {
- return getProperBrIf(curr)
- ->condition->cast<Binary>()
- ->right->cast<Const>()
- ->value.geti32();
+ auto* condition = getProperBrIf(curr)->condition;
+ if (auto* binary = condition->dynCast<Binary>()) {
+ return binary->right->cast<Const>()->value.geti32();
+ } else if (auto* unary = condition->dynCast<Unary>()) {
+ assert(unary->op == EqZInt32);
+ return 0;
+ } else {
+ WASM_UNREACHABLE("invalid br_if condition");
+ }
};
Index start = 0;
while (start < list.size() - 1) {
@@ -1360,6 +1381,14 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
start++;
continue;
}
+ // If the first condition value is a tee, that is ok, so long as the
+ // others afterwards are gets of the value that is tee'd.
+ LocalGet get;
+ if (auto* tee = conditionValue->dynCast<LocalSet>()) {
+ get.index = tee->index;
+ get.type = getFunction()->getLocalType(get.index);
+ conditionValue = &get;
+ }
// if the condition has side effects, we can't replace many
// appearances of it with a single one
if (EffectAnalyzer(passOptions, *getModule(), conditionValue)
@@ -1427,13 +1456,15 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
Builder builder(*getModule());
// the table and condition are offset by the min
+ auto* newCondition = getProperBrIfConditionValue(list[start]);
+
if (min != 0) {
- conditionValue = builder.makeBinary(
- SubInt32, conditionValue, builder.makeConst(int32_t(min)));
+ newCondition = builder.makeBinary(
+ SubInt32, newCondition, builder.makeConst(int32_t(min)));
}
list[end - 1] = builder.makeBlock(
defaultName,
- builder.makeSwitch(table, defaultName, conditionValue));
+ builder.makeSwitch(table, defaultName, newCondition));
for (Index i = start; i < end - 1; i++) {
ExpressionManipulator::nop(list[i]);
}