From 181b0e7037bc2999a24cb45a02523f3da04b254d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Sep 2021 14:27:10 -0700 Subject: 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. --- src/passes/RemoveUnusedBrs.cpp | 49 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) (limited to 'src') 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> { // dce will clean it up return nullptr; } - auto* binary = br->condition->dynCast(); + auto* condition = br->condition; + // Also support eqz, which is the same as == 0. + if (auto* unary = condition->dynCast()) { + if (unary->op == EqZInt32) { + return br; + } + return nullptr; + } + auto* binary = condition->dynCast(); if (!binary) { return nullptr; } @@ -1342,16 +1350,29 @@ struct RemoveUnusedBrs : public WalkerPass> { if (!br) { return nullptr; } - return br->condition->cast()->left; + auto* condition = br->condition; + if (auto* binary = condition->dynCast()) { + return binary->left; + } else if (auto* unary = condition->dynCast()) { + 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() - ->right->cast() - ->value.geti32(); + auto* condition = getProperBrIf(curr)->condition; + if (auto* binary = condition->dynCast()) { + return binary->right->cast()->value.geti32(); + } else if (auto* unary = condition->dynCast()) { + 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> { 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()) { + 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> { } 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]); } -- cgit v1.2.3