/*
 * Copyright 2015 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.
 */

//
// Removes branches for which we go to where they go anyhow
//

#include "ir/branch-utils.h"
#include "ir/cost.h"
#include "ir/drop.h"
#include "ir/effects.h"
#include "ir/gc-type-utils.h"
#include "ir/literal-utils.h"
#include "ir/utils.h"
#include "parsing.h"
#include "pass.h"
#include "support/small_set.h"
#include "wasm-builder.h"
#include "wasm.h"

namespace wasm {

// Grab a slice out of a block, replacing it with nops, and returning
// either another block with the contents (if more than 1) or a single
// expression.
// This does not finalize the input block; it leaves that for the caller.
static Expression*
stealSlice(Builder& builder, Block* input, Index from, Index to) {
  Expression* ret;
  if (to == from + 1) {
    // just one
    ret = input->list[from];
  } else {
    auto* block = builder.makeBlock();
    for (Index i = from; i < to; i++) {
      block->list.push_back(input->list[i]);
    }
    block->finalize();
    ret = block;
  }
  if (to == input->list.size()) {
    input->list.resize(from);
  } else {
    for (Index i = from; i < to; i++) {
      input->list[i] = builder.makeNop();
    }
  }
  return ret;
}

// to turn an if into a br-if, we must be able to reorder the
// condition and possible value, and the possible value must
// not have side effects (as they would run unconditionally)
static bool canTurnIfIntoBrIf(Expression* ifCondition,
                              Expression* brValue,
                              PassOptions& options,
                              Module& wasm) {
  // if the if isn't even reached, this is all dead code anyhow
  if (ifCondition->type == Type::unreachable) {
    return false;
  }
  if (!brValue) {
    return true;
  }
  EffectAnalyzer value(options, wasm, brValue);
  if (value.hasSideEffects()) {
    return false;
  }
  return !EffectAnalyzer(options, wasm, ifCondition).invalidates(value);
}

// This leads to similar choices as LLVM does in some cases, by balancing the
// extra work of code that is run unconditionally with the speedup from not
// branching to decide whether to run it or not.
// See:
//  * https://github.com/WebAssembly/binaryen/pull/4228
//  * https://github.com/WebAssembly/binaryen/issues/5983
const Index TooCostlyToRunUnconditionally = 8;

// Some costs are known to be too high to move from conditional to unconditional
// execution.
static_assert(CostAnalyzer::AtomicCost >= TooCostlyToRunUnconditionally,
              "We never run atomics unconditionally");
static_assert(CostAnalyzer::ThrowCost >= TooCostlyToRunUnconditionally,
              "We never run throws unconditionally");
static_assert(CostAnalyzer::CastCost > TooCostlyToRunUnconditionally / 2,
              "We only run casts unconditionally when optimizing for size");

static bool tooCostlyToRunUnconditionally(const PassOptions& passOptions,
                                          Index cost) {
  if (passOptions.shrinkLevel == 0) {
    // We are focused on speed. Any extra cost is risky, but allow a small
    // amount.
    return cost > TooCostlyToRunUnconditionally / 2;
  } else if (passOptions.shrinkLevel == 1) {
    // We are optimizing for size in a balanced manner. Allow some extra
    // overhead here.
    return cost >= TooCostlyToRunUnconditionally;
  } else {
    // We should have already decided what to do if shrink_level=2 and not
    // gotten here, and other values are invalid.
    WASM_UNREACHABLE("bad shrink level");
  }
}

// As above, but a single expression that we are considering moving to a place
// where it executes unconditionally.
static bool tooCostlyToRunUnconditionally(const PassOptions& passOptions,
                                          Expression* curr) {
  // If we care entirely about code size, just do it for that reason (early
  // exit to avoid work).
  if (passOptions.shrinkLevel >= 2) {
    return false;
  }
  auto cost = CostAnalyzer(curr).cost;
  return tooCostlyToRunUnconditionally(passOptions, cost);
}

// Check if it is not worth it to run code unconditionally. This
// assumes we are trying to run two expressions where previously
// only one of the two might have executed. We assume here that
// executing both is good for code size.
static bool tooCostlyToRunUnconditionally(const PassOptions& passOptions,
                                          Expression* one,
                                          Expression* two) {
  // If we care entirely about code size, just do it for that reason (early
  // exit to avoid work).
  if (passOptions.shrinkLevel >= 2) {
    return false;
  }

  // Consider the cost of executing all the code unconditionally, which adds
  // either the cost of running one or two, so the maximum is the worst case.
  auto max = std::max(CostAnalyzer(one).cost, CostAnalyzer(two).cost);
  return tooCostlyToRunUnconditionally(passOptions, max);
}

struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
  bool isFunctionParallel() override { return true; }

  std::unique_ptr<Pass> create() override {
    return std::make_unique<RemoveUnusedBrs>();
  }

  bool anotherCycle;

  using Flows = std::vector<Expression**>;

  // list of breaks that are currently flowing. if they reach their target
  // without interference, they can be removed (or their value forwarded TODO)
  Flows flows;

  // a stack for if-else contents, we merge their outputs
  std::vector<Flows> ifStack;

  // list of all loops, so we can optimize them
  std::vector<Loop*> loops;

  static void visitAny(RemoveUnusedBrs* self, Expression** currp) {
    auto* curr = *currp;
    auto& flows = self->flows;

    if (curr->is<Break>()) {
      flows.clear();
      auto* br = curr->cast<Break>();
      if (!br->condition) { // TODO: optimize?
        // a break, let's see where it flows to
        flows.push_back(currp);
      } else {
        self->stopValueFlow();
      }
    } else if (curr->is<Return>()) {
      flows.clear();
      flows.push_back(currp);
    } else if (curr->is<If>()) {
      auto* iff = curr->cast<If>();
      if (iff->condition->type == Type::unreachable) {
        // avoid trying to optimize this, we never reach it anyhow
        self->stopFlow();
        return;
      }
      if (iff->ifFalse) {
        assert(self->ifStack.size() > 0);
        auto ifTrueFlows = std::move(self->ifStack.back());
        self->ifStack.pop_back();
        // we can flow values out in most cases, except if one arm
        // has the none type - we will update the types later, but
        // there is no way to emit a proper type for one arm being
        // none and the other flowing a value; and there is no way
        // to flow a value from a none.
        if (iff->ifTrue->type == Type::none ||
            iff->ifFalse->type == Type::none) {
          self->removeValueFlow(ifTrueFlows);
          self->stopValueFlow();
        }
        for (auto* flow : ifTrueFlows) {
          flows.push_back(flow);
        }
      } else {
        // if without else stops the flow of values
        self->stopValueFlow();
      }
    } else if (auto* block = curr->dynCast<Block>()) {
      // any breaks flowing to here are unnecessary, as we get here anyhow
      auto name = block->name;
      auto& list = block->list;
      if (name.is()) {
        Index size = flows.size();
        Index skip = 0;
        for (Index i = 0; i < size; i++) {
          auto* flow = (*flows[i])->dynCast<Break>();
          if (flow && flow->name == name) {
            if (!flow->value) {
              // br => nop
              ExpressionManipulator::nop<Break>(flow);
            } else {
              // br with value => value
              *flows[i] = flow->value;
            }
            skip++;
            self->anotherCycle = true;
          } else if (skip > 0) {
            flows[i - skip] = flows[i];
          }
        }
        if (skip > 0) {
          flows.resize(size - skip);
        }
      }
      // Drop a nop at the end of a block, which prevents a value flowing. Note
      // that this is worth doing regardless of whether we have a name on this
      // block or not (which the if right above us checks) - such a nop is
      // always unneeded and can limit later optimizations.
      while (list.size() > 0 && list.back()->is<Nop>()) {
        list.resize(list.size() - 1);
        self->anotherCycle = true;
      }
      // A value flowing is only valid if it is a value that the block actually
      // flows out. If it is never reached, it does not flow out, and may be
      // invalid to represent as such.
      auto size = list.size();
      for (Index i = 0; i < size; i++) {
        if (i != size - 1 && list[i]->type == Type::unreachable) {
          // No value flows out of this block.
          self->stopValueFlow();
          break;
        }
      }
    } else if (curr->is<Nop>()) {
      // Ignore (could be result of a previous cycle).
      self->stopValueFlow();
    } else if (curr->is<Loop>() || curr->is<TryTable>()) {
      // Do nothing - it's ok for values to flow out.
      // TODO: Legacy Try as well?
    } else if (auto* sw = curr->dynCast<Switch>()) {
      self->stopFlow();
      self->optimizeSwitch(sw);
    } else {
      // Anything else stops the flow.
      self->stopFlow();
    }
  }

  void stopFlow() { flows.clear(); }

  void removeValueFlow(Flows& currFlows) {
    currFlows.erase(std::remove_if(currFlows.begin(),
                                   currFlows.end(),
                                   [&](Expression** currp) {
                                     auto* curr = *currp;
                                     if (auto* ret = curr->dynCast<Return>()) {
                                       return ret->value;
                                     }
                                     return curr->cast<Break>()->value;
                                   }),
                    currFlows.end());
  }

  void stopValueFlow() { removeValueFlow(flows); }

  static void clear(RemoveUnusedBrs* self, Expression** currp) {
    self->flows.clear();
  }

  static void saveIfTrue(RemoveUnusedBrs* self, Expression** currp) {
    self->ifStack.push_back(std::move(self->flows));
  }

  void visitLoop(Loop* curr) { loops.push_back(curr); }

  void optimizeSwitch(Switch* curr) {
    // if the final element is the default, we don't need it
    while (!curr->targets.empty() && curr->targets.back() == curr->default_) {
      curr->targets.pop_back();
    }
    // if the first element is the default, we can remove it by shifting
    // everything (which does add a subtraction of a constant, but often that is
    // worth it as the constant can be folded away and/or we remove multiple
    // elements here)
    Index removable = 0;
    while (removable < curr->targets.size() &&
           curr->targets[removable] == curr->default_) {
      removable++;
    }
    if (removable > 0) {
      for (Index i = removable; i < curr->targets.size(); i++) {
        curr->targets[i - removable] = curr->targets[i];
      }
      curr->targets.resize(curr->targets.size() - removable);
      Builder builder(*getModule());
      curr->condition = builder.makeBinary(
        SubInt32, curr->condition, builder.makeConst(int32_t(removable)));
    }
    // when there isn't a value, we can do some trivial optimizations without
    // worrying about the value being executed before the condition
    if (curr->value) {
      return;
    }
    if (curr->targets.size() == 0) {
      // a switch with just a default always goes there
      Builder builder(*getModule());
      replaceCurrent(builder.makeSequence(builder.makeDrop(curr->condition),
                                          builder.makeBreak(curr->default_)));
    } else if (curr->targets.size() == 1) {
      // a switch with two options is basically an if
      Builder builder(*getModule());
      replaceCurrent(builder.makeIf(curr->condition,
                                    builder.makeBreak(curr->default_),
                                    builder.makeBreak(curr->targets.front())));
    } else {
      // there are also some other cases where we want to convert a switch into
      // ifs, especially if the switch is large and we are focusing on size. an
      // especially egregious case is a switch like this: [a b b [..] b b c]
      // with default b (which may be arrived at after we trim away excess
      // default values on both sides). in this case, we really have 3 values in
      // a simple form, so it is the next logical case after handling 1 and 2
      // values right above here. to optimize this, we must add a local + a
      // bunch of nodes (if*2, tee, eq, get, const, break*3), so the table must
      // be big enough for it to make sense

      // How many targets we need when shrinking. This is literally the size at
      // which the transformation begins to be smaller.
      const uint32_t MIN_SHRINK = 13;
      // How many targets we need when not shrinking, in which case, 2 ifs may
      // be slower, so we do this when the table is ridiculously large for one
      // with just 3 values in it.
      const uint32_t MIN_GENERAL = 128;

      auto shrink = getPassRunner()->options.shrinkLevel > 0;
      if ((curr->targets.size() >= MIN_SHRINK && shrink) ||
          (curr->targets.size() >= MIN_GENERAL && !shrink)) {
        for (Index i = 1; i < curr->targets.size() - 1; i++) {
          if (curr->targets[i] != curr->default_) {
            return;
          }
        }
        // great, we are in that case, optimize
        Builder builder(*getModule());
        auto temp = builder.addVar(getFunction(), Type::i32);
        Expression* z;
        replaceCurrent(z = builder.makeIf(
                         builder.makeLocalTee(temp, curr->condition, Type::i32),
                         builder.makeIf(builder.makeBinary(
                                          EqInt32,
                                          builder.makeLocalGet(temp, Type::i32),
                                          builder.makeConst(
                                            int32_t(curr->targets.size() - 1))),
                                        builder.makeBreak(curr->targets.back()),
                                        builder.makeBreak(curr->default_)),
                         builder.makeBreak(curr->targets.front())));
      }
    }
  }

  void visitIf(If* curr) {
    if (!curr->ifFalse) {
      // if without an else. try to reduce
      //    if (condition) br  =>  br_if (condition)
      if (Break* br = curr->ifTrue->dynCast<Break>()) {
        if (canTurnIfIntoBrIf(
              curr->condition, br->value, getPassOptions(), *getModule())) {
          if (!br->condition) {
            br->condition = curr->condition;
          } else {
            // In this case we can replace
            //   if (condition1) br_if (condition2)
            // =>
            //   br_if select (condition1) (condition2) (i32.const 0)
            // In other words, we replace an if (3 bytes) with a select and a
            // zero (also 3 bytes). The size is unchanged, but the select may
            // be further optimizable, and if select does not branch we also
            // avoid one branch.
            // Multivalue selects are not supported
            if (br->value && br->value->type.isTuple()) {
              return;
            }
            // If running the br's condition unconditionally is too expensive,
            // give up.
            auto* zero = LiteralUtils::makeZero(Type::i32, *getModule());
            if (tooCostlyToRunUnconditionally(
                  getPassOptions(), br->condition, zero)) {
              return;
            }
            // Of course we can't do this if the br's condition has side
            // effects, as we would then execute those unconditionally.
            if (EffectAnalyzer(getPassOptions(), *getModule(), br->condition)
                  .hasSideEffects()) {
              return;
            }
            Builder builder(*getModule());
            // Note that we use the br's condition as the select condition.
            // That keeps the order of the two conditions as it was originally.
            br->condition =
              builder.makeSelect(br->condition, curr->condition, zero);
          }
          br->finalize();
          replaceCurrent(Builder(*getModule()).dropIfConcretelyTyped(br));
          anotherCycle = true;
        }
      }

      // if (condition-A) { if (condition-B) .. }
      //   =>
      // if (condition-A ? condition-B : 0) { .. }
      //
      // This replaces an if, which is 3 bytes, with a select plus a zero, which
      // is also 3 bytes. The benefit is that the select may be faster, and also
      // further optimizations may be possible on the select.
      if (auto* child = curr->ifTrue->dynCast<If>()) {
        if (child->ifFalse) {
          return;
        }
        // If running the child's condition unconditionally is too expensive,
        // give up.
        if (tooCostlyToRunUnconditionally(getPassOptions(), child->condition)) {
          return;
        }
        // Of course we can't do this if the inner if's condition has side
        // effects, as we would then execute those unconditionally.
        if (EffectAnalyzer(getPassOptions(), *getModule(), child->condition)
              .hasSideEffects()) {
          return;
        }
        Builder builder(*getModule());
        curr->condition = builder.makeSelect(
          child->condition, curr->condition, builder.makeConst(int32_t(0)));
        curr->ifTrue = child->ifTrue;
      }
    }
    // TODO: if-else can be turned into a br_if as well, if one of the sides is
    //       a dead end we handle the case of a returned value to a local.set
    //       later down, see visitLocalSet.
  }

  // A stack of catching expressions that are parents of the current expression,
  // that is, Try and TryTable.
  std::vector<Expression*> catchers;

  static void popCatcher(RemoveUnusedBrs* self, Expression** currp) {
    assert(!self->catchers.empty() && self->catchers.back() == *currp);
    self->catchers.pop_back();
  }

  void visitThrow(Throw* curr) {
    // If a throw will definitely be caught, and it is not a catch with a
    // reference, then it is just a branch (i.e. the code is using exceptions as
    // control flow). Turn it into a branch here so that the rest of the pass
    // can optimize it with all other branches.
    //
    // To do so, look at the closest try and see if it will catch us, and
    // proceed outwards if not.
    auto thrownTag = curr->tag;
    for (int i = catchers.size() - 1; i >= 0; i--) {
      auto* tryy = catchers[i]->dynCast<TryTable>();
      if (!tryy) {
        // We do not handle mixtures of Try and TryTable.
        return;
      }
      for (Index j = 0; j < tryy->catchTags.size(); j++) {
        auto tag = tryy->catchTags[j];
        // The tag must match, or be a catch_all.
        if (tag == thrownTag || tag.isNull()) {
          // This must not be a catch with exnref.
          if (!tryy->catchRefs[j]) {
            // Success! Create a break to replace the throw.
            auto dest = tryy->catchDests[j];
            auto& wasm = *getModule();
            Builder builder(wasm);
            if (!tag.isNull()) {
              // We are catching a specific tag, so values might be sent.
              Expression* value = nullptr;
              if (curr->operands.size() == 1) {
                value = curr->operands[0];
              } else if (curr->operands.size() > 1) {
                value = builder.makeTupleMake(curr->operands);
              }
              auto* br = builder.makeBreak(dest, value);
              replaceCurrent(br);
              return;
            }

            // catch_all: no values are sent. Drop the throw's children (while
            // ignoring parent effects: the parent is a throw, but we have
            // proven we can remove that effect).
            auto* br = builder.makeBreak(dest);
            auto* rep = getDroppedChildrenAndAppend(
              curr, wasm, getPassOptions(), br, DropMode::IgnoreParentEffects);
            replaceCurrent(rep);
            // We modified the code here and may have added a drop, etc., so
            // stop the flow (rather than re-scan it somehow). We leave
            // optimizing anything that flows out for later iterations.
            stopFlow();
          }

          // Return even if we did not optimize: we found our tag was caught.
          return;
        }
      }
    }
  }

  // override scan to add a pre and a post check task to all nodes
  static void scan(RemoveUnusedBrs* self, Expression** currp) {
    self->pushTask(visitAny, currp);

    if (auto* iff = (*currp)->dynCast<If>()) {
      if (iff->condition->type == Type::unreachable) {
        // avoid trying to optimize this, we never reach it anyhow
        return;
      }
      self->pushTask(doVisitIf, currp);
      if (iff->ifFalse) {
        // we need to join up if-else control flow, and clear after the
        // condition
        self->pushTask(scan, &iff->ifFalse);
        // safe the ifTrue flow, we'll join it later
        self->pushTask(saveIfTrue, currp);
      }
      self->pushTask(scan, &iff->ifTrue);
      self->pushTask(clear, currp); // clear all flow after the condition
      self->pushTask(scan, &iff->condition);
      return;
    }
    if ((*currp)->is<TryTable>() || (*currp)->is<Try>()) {
      // Push the try we are reaching, and add a task to pop it, after all the
      // tasks that Super::scan will push for its children.
      self->catchers.push_back(*currp);
      self->pushTask(popCatcher, currp);
    }

    Super::scan(self, currp);
  }

  // optimizes a loop. returns true if we made changes
  bool optimizeLoop(Loop* loop) {
    // if a loop ends in
    // (loop $in
    //   (block $out
    //     if (..) br $in; else br $out;
    //   )
    // )
    // then our normal opts can remove the break out since it flows directly out
    // (and later passes make the if one-armed). however, the simple analysis
    // fails on patterns like
    //     if (..) br $out;
    //     br $in;
    // which is a common way to do a while (1) loop (end it with a jump to the
    // top), so we handle that here. Specifically we want to conditionalize
    // breaks to the loop top, i.e., put them behind a condition, so that other
    // code can flow directly out and thus brs out can be removed. (even if
    // the change is to let a break somewhere else flow out, that can still be
    // helpful, as it shortens the logical loop. it is also good to generate
    // an if-else instead of an if, as it might allow an eqz to be removed
    // by flipping arms)
    if (!loop->name.is()) {
      return false;
    }
    auto* block = loop->body->dynCast<Block>();
    if (!block) {
      return false;
    }
    // does the last element break to the top of the loop?
    auto& list = block->list;
    if (list.size() <= 1) {
      return false;
    }
    auto* last = list.back()->dynCast<Break>();
    if (!last || !ExpressionAnalyzer::isSimple(last) ||
        last->name != loop->name) {
      return false;
    }
    // last is a simple break to the top of the loop. if we can conditionalize
    // it, it won't block things from flowing out and not needing breaks to do
    // so.
    Index i = list.size() - 2;
    Builder builder(*getModule());
    while (1) {
      auto* curr = list[i];
      if (auto* iff = curr->dynCast<If>()) {
        // let's try to move the code going to the top of the loop into the
        // if-else
        if (!iff->ifFalse) {
          // we need the ifTrue to break, so it cannot reach the code we want to
          // move
          if (iff->ifTrue->type == Type::unreachable) {
            iff->ifFalse = stealSlice(builder, block, i + 1, list.size());
            iff->finalize();
            block->finalize();
            return true;
          }
        } else if (iff->condition->type != Type::unreachable) {
          // This is already an if-else. If one side is a dead end, we can
          // append to the other, if there is no returned value to concern us.
          // Note that we skip ifs with unreachable conditions, as they are dead
          // code that DCE can remove, and modifying them can lead to errors
          // (one of the arms may still be concrete, in which case appending to
          // it would be invalid).

          // can't be, since in the middle of a block
          assert(!iff->type.isConcrete());

          // ensures the first node is a block, if it isn't already, and merges
          // in the second, either as a single element or, if a block, by
          // appending to the first block. this keeps the order of operations in
          // place, that is, the appended element will be executed after the
          // first node's elements
          auto blockifyMerge = [&](Expression* any,
                                   Expression* append) -> Block* {
            Block* block = nullptr;
            if (any) {
              block = any->dynCast<Block>();
            }
            // if the first isn't a block, or it's a block with a name (so we
            // might branch to the end, and so can't append to it, we might skip
            // that code!) then make a new block
            if (!block || block->name.is()) {
              block = builder.makeBlock(any);
            } else {
              assert(!block->type.isConcrete());
            }
            auto* other = append->dynCast<Block>();
            if (!other) {
              block->list.push_back(append);
            } else {
              for (auto* item : other->list) {
                block->list.push_back(item);
              }
            }
            block->finalize();
            return block;
          };

          if (iff->ifTrue->type == Type::unreachable) {
            iff->ifFalse = blockifyMerge(
              iff->ifFalse, stealSlice(builder, block, i + 1, list.size()));
            iff->finalize();
            block->finalize();
            return true;
          } else if (iff->ifFalse->type == Type::unreachable) {
            iff->ifTrue = blockifyMerge(
              iff->ifTrue, stealSlice(builder, block, i + 1, list.size()));
            iff->finalize();
            block->finalize();
            return true;
          }
        }
        return false;
      } else if (auto* brIf = curr->dynCast<Break>()) {
        // br_if is similar to if.
        if (brIf->condition && !brIf->value && brIf->name != loop->name) {
          if (i == list.size() - 2) {
            // there is the br_if, and then the br to the top, so just flip them
            // and the condition
            brIf->condition = builder.makeUnary(EqZInt32, brIf->condition);
            last->name = brIf->name;
            brIf->name = loop->name;
            return true;
          } else {
            // there are elements in the middle,
            //   br_if $somewhere (condition)
            //   (..more..)
            //   br $in
            // we can convert the br_if to an if. this has a cost, though,
            // so only do it if it looks useful, which it definitely is if
            //  (a) $somewhere is straight out (so the br out vanishes), and
            //  (b) this br_if is the only branch to that block (so the block
            //      will vanish)
            if (brIf->name == block->name &&
                BranchUtils::BranchSeeker::count(block, block->name) == 1) {
              // note that we could drop the last element here, it is a br we
              // know for sure is removable, but telling stealSlice to steal all
              // to the end is more efficient, it can just truncate.
              list[i] =
                builder.makeIf(brIf->condition,
                               builder.makeBreak(brIf->name),
                               stealSlice(builder, block, i + 1, list.size()));
              block->finalize();
              return true;
            }
          }
        }
        return false;
      }
      // if there is control flow, we must stop looking
      if (EffectAnalyzer(getPassOptions(), *getModule(), curr)
            .transfersControlFlow()) {
        return false;
      }
      if (i == 0) {
        return false;
      }
      i--;
    }
  }

  bool sinkBlocks(Function* func) {
    struct Sinker : public PostWalker<Sinker> {
      bool worked = false;

      void visitBlock(Block* curr) {
        // If the block has a single child which is a loop, and the block is
        // named, then it is the exit for the loop. It's better to move it into
        // the loop, where it can be better optimized by other passes. Similar
        // logic for ifs: if the block is an exit for the if, we can move the
        // block in, consider for example:
        //    (block $label
        //     (if (..condition1..)
        //      (block
        //       (br_if $label (..condition2..))
        //       (..code..)
        //      )
        //     )
        //    )
        // After also merging the blocks, we have
        //    (if (..condition1..)
        //     (block $label
        //      (br_if $label (..condition2..))
        //      (..code..)
        //     )
        //    )
        // which can be further optimized later.
        if (curr->name.is() && curr->list.size() == 1) {
          if (auto* loop = curr->list[0]->dynCast<Loop>()) {
            curr->list[0] = loop->body;
            loop->body = curr;
            curr->finalize(curr->type);
            loop->finalize();
            replaceCurrent(loop);
            worked = true;
          } else if (auto* iff = curr->list[0]->dynCast<If>()) {
            if (iff->condition->type == Type::unreachable) {
              // The block result type may not be compatible with the arm result
              // types since the unreachable If can satisfy any type of block.
              // Just leave this for DCE.
              return;
            }
            // The label can't be used in the condition.
            if (BranchUtils::BranchSeeker::count(iff->condition, curr->name) ==
                0) {
              // We can move the block into either arm, if there are no uses in
              // the other.
              Expression** target = nullptr;
              if (!iff->ifFalse || BranchUtils::BranchSeeker::count(
                                     iff->ifFalse, curr->name) == 0) {
                target = &iff->ifTrue;
              } else if (BranchUtils::BranchSeeker::count(iff->ifTrue,
                                                          curr->name) == 0) {
                target = &iff->ifFalse;
              }
              if (target) {
                curr->list[0] = *target;
                *target = curr;
                // The block used to contain the if, and may have changed type
                // from unreachable to none, for example, if the if has an
                // unreachable condition but the arm is not unreachable.
                curr->finalize();
                iff->finalize();
                replaceCurrent(iff);
                worked = true;
                // Note that the type might change, e.g. if the if condition is
                // unreachable but the block that was on the outside had a
                // break.
              }
            }
          }
        }
      }
    } sinker;

    sinker.doWalkFunction(func);
    if (sinker.worked) {
      ReFinalize().walkFunctionInModule(func, getModule());
      return true;
    }
    return false;
  }

  // GC-specific optimizations. These are split out from the main code to keep
  // things as simple as possible.
  bool optimizeGC(Function* func) {
    if (!getModule()->features.hasGC()) {
      return false;
    }

    struct Optimizer : public PostWalker<Optimizer> {
      PassOptions& passOptions;
      bool worked = false;

      Optimizer(PassOptions& passOptions) : passOptions(passOptions) {}

      void visitBrOn(BrOn* curr) {
        // Ignore unreachable BrOns which we cannot improve anyhow. Note that
        // we must check the ref field manually, as we may be changing types as
        // we go here. (Another option would be to use a TypeUpdater here
        // instead of calling ReFinalize at the very end, but that would be more
        // complex and slower.)
        if (curr->type == Type::unreachable ||
            curr->ref->type == Type::unreachable) {
          return;
        }

        Builder builder(*getModule());

        Type refType =
          Properties::getFallthroughType(curr->ref, passOptions, *getModule());
        if (refType == Type::unreachable) {
          // Leave this to DCE.
          return;
        }
        assert(refType.isRef());

        // When we optimize based on all the fallthrough type information
        // available, we may need to insert a cast to maintain validity. For
        // example, in this case we know the cast will succeed, but it would be
        // invalid to send curr->ref directly:
        //
        //   (br_on_cast $l anyref i31ref
        //     (block (result anyref)
        //       (ref.i31 ...)))
        //
        // We could just always do the cast and leave removing the casts to
        // OptimizeInstructions, but it's simple enough to avoid unnecessary
        // casting here.
        auto maybeCast = [&](Expression* expr, Type type) -> Expression* {
          assert(expr->type.isRef() && type.isRef());
          if (Type::isSubType(expr->type, type)) {
            return expr;
          }
          if (type.isNonNullable() && expr->type.isNullable() &&
              Type::isSubType(expr->type.with(NonNullable), type)) {
            return builder.makeRefAs(RefAsNonNull, expr);
          }
          return builder.makeRefCast(expr, type);
        };

        if (curr->op == BrOnNull) {
          if (refType.isNull()) {
            // The branch will definitely be taken.
            replaceCurrent(builder.makeSequence(builder.makeDrop(curr->ref),
                                                builder.makeBreak(curr->name)));
            worked = true;
            return;
          }
          if (refType.isNonNullable()) {
            // The branch will definitely not be taken.
            replaceCurrent(maybeCast(curr->ref, curr->type));
            worked = true;
            return;
          }
          return;
        }

        if (curr->op == BrOnNonNull) {
          if (refType.isNull()) {
            // Definitely not taken.
            replaceCurrent(builder.makeDrop(curr->ref));
            worked = true;
            return;
          }
          if (refType.isNonNullable()) {
            // Definitely taken.
            replaceCurrent(builder.makeBreak(
              curr->name, maybeCast(curr->ref, curr->getSentType())));
            worked = true;
            return;
          }
          return;
        }

        // Improve the cast target type as much as possible given what we know
        // about the input. Unlike in BrOn::finalize(), we consider type
        // information from all the fallthrough values here. We can continue to
        // further optimizations after this, and those optimizations might even
        // benefit from this improvement.
        auto glb = Type::getGreatestLowerBound(curr->castType, refType);
        if (glb != Type::unreachable && glb != curr->castType) {
          curr->castType = glb;
          auto oldType = curr->type;
          curr->finalize();
          worked = true;

          // We refined the castType, which may *un*-refine the BrOn itself.
          // Imagine the castType was nullable before, then nulls would go on
          // the branch, and so the BrOn could only flow out a non-nullable
          // value, and that was its type. If we refine the castType to be
          // non-nullable then nulls no longer go through, making the BrOn
          // itself nullable. This should not normally happen, but can occur
          // because we look at the fallthrough of the ref:
          //
          //   (br_on_cast
          //     (local.tee $unrefined
          //       (refined
          //
          // That is, we may see a more refined type for our GLB computation
          // than the wasm type system does, if a local.tee or such ends up
          // unrefining the type.
          //
          // To check for this and fix it, see if we need a cast in order to be
          // a subtype of the old type.
          auto* rep = maybeCast(curr, oldType);
          if (rep != curr) {
            replaceCurrent(rep);
            // Exit after doing so, leaving further work for other cycles.
            return;
          }
        }

        // Depending on what we know about the cast results, we may be able to
        // optimize.
        auto result = GCTypeUtils::evaluateCastCheck(refType, curr->castType);
        if (curr->op == BrOnCastFail) {
          result = GCTypeUtils::flipEvaluationResult(result);
        }

        switch (result) {
          case GCTypeUtils::Unknown:
            // Anything could happen, so we cannot optimize.
            return;
          case GCTypeUtils::Success: {
            replaceCurrent(builder.makeBreak(
              curr->name, maybeCast(curr->ref, curr->getSentType())));
            worked = true;
            return;
          }
          case GCTypeUtils::Failure: {
            replaceCurrent(maybeCast(curr->ref, curr->type));
            worked = true;
            return;
          }
          case GCTypeUtils::SuccessOnlyIfNull: {
            // TODO: optimize this case using the following replacement, which
            // avoids using any scratch locals and only does a single null
            // check, but does require generating a fresh label:
            //
            //   (br_on_cast $l (ref null $X) (ref null $Y)
            //     (...)
            //   )
            //     =>
            //   (block $l' (result (ref $X))
            //     (br_on_non_null $l' ;; reuses `curr`
            //       (...)
            //     )
            //     (br $l
            //       (ref.null bot<X>)
            //     )
            //   )
            return;
          }
          case GCTypeUtils::SuccessOnlyIfNonNull: {
            // Perform this replacement:
            //
            //   (br_on_cast $l (ref null $X') (ref $X))
            //     (...)
            //   )
            //     =>
            //   (block (result (ref bot<X>))
            //     (br_on_non_null $l ;; reuses `curr`
            //       (...)
            //     (ref.null bot<X>)
            //   )
            curr->ref = maybeCast(
              curr->ref, Type(curr->getSentType().getHeapType(), Nullable));
            curr->op = BrOnNonNull;
            curr->castType = Type::none;
            curr->type = Type::none;

            assert(curr->ref->type.isRef());
            auto* refNull = builder.makeRefNull(curr->ref->type.getHeapType());
            replaceCurrent(builder.makeBlock({curr, refNull}, refNull->type));
            worked = true;
            return;
          }
          case GCTypeUtils::Unreachable: {
            // The cast is never executed, possibly because its input type is
            // uninhabitable. Replace it with unreachable.
            auto* drop = builder.makeDrop(curr->ref);
            auto* unreachable = ExpressionManipulator::unreachable(curr);
            replaceCurrent(builder.makeBlock({drop, unreachable}));
            worked = true;
            return;
          }
        }
      }
    } optimizer(getPassOptions());

    optimizer.setModule(getModule());
    optimizer.doWalkFunction(func);

    // If we removed any BrOn instructions, that might affect the reachability
    // of the things they used to break to, so update types.
    if (optimizer.worked) {
      ReFinalize().walkFunctionInModule(func, getModule());
      return true;
    }
    return false;
  }

  void doWalkFunction(Function* func) {
    // multiple cycles may be needed
    do {
      anotherCycle = false;
      Super::doWalkFunction(func);
      assert(ifStack.empty());
      // flows may contain returns, which are flowing out and so can be
      // optimized
      for (Index i = 0; i < flows.size(); i++) {
        auto* flow = (*flows[i])->dynCast<Return>();
        if (!flow) {
          continue;
        }
        if (!flow->value) {
          // return => nop
          ExpressionManipulator::nop(flow);
        } else {
          // return with value => value
          *flows[i] = flow->value;
        }
        anotherCycle = true;
      }
      flows.clear();
      // optimize loops (we don't do it while tracking flows, as they can
      // interfere)
      for (auto* loop : loops) {
        anotherCycle |= optimizeLoop(loop);
      }
      loops.clear();
      if (anotherCycle) {
        ReFinalize().walkFunctionInModule(func, getModule());
      }
      if (sinkBlocks(func)) {
        anotherCycle = true;
      }
      if (optimizeGC(func)) {
        anotherCycle = true;
      }
    } while (anotherCycle);

    // Thread trivial jumps.
    struct JumpThreader
      : public PostWalker<JumpThreader,
                          UnifiedExpressionVisitor<JumpThreader>> {
      // Map of all labels (branch targets) to the branches going to them. (We
      // only care about blocks here, and not loops, but for simplicitly we
      // store all branch targets since blocks are 99% of that set anyhow. Any
      // loops are ignored later.)
      std::unordered_map<Name, std::vector<Expression*>> labelToBranches;

      bool worked = false;

      void visitExpression(Expression* curr) {
        // Find the relevant targets: targets that (as mentioned above) have no
        // value sent to them.
        SmallSet<Name, 2> relevantTargets;
        BranchUtils::operateOnScopeNameUsesAndSentTypes(
          curr, [&](Name name, Type sent) {
            if (sent == Type::none) {
              relevantTargets.insert(name);
            }
          });

        // Note ourselves on all relevant targets.
        for (auto target : relevantTargets) {
          labelToBranches[target].push_back(curr);
        }
      }

      void visitBlock(Block* curr) {
        auto& list = curr->list;
        if (list.size() == 1 && curr->name.is()) {
          // if this block has just one child, a sub-block, then jumps to the
          // former are jumps to us, really
          if (auto* child = list[0]->dynCast<Block>()) {
            // the two blocks must have the same type for us to update the
            // branch, as otherwise one block may be unreachable and the other
            // concrete, so one might lack a value
            if (child->name.is() && child->name != curr->name &&
                child->type == curr->type) {
              redirectBranches(child, curr->name);
            }
          }
        } else if (list.size() == 2) {
          // if this block has two children, a child-block and a simple jump,
          // then jumps to child-block can be replaced with jumps to the new
          // target
          auto* child = list[0]->dynCast<Block>();
          auto* jump = list[1]->dynCast<Break>();
          if (child && child->name.is() && jump &&
              ExpressionAnalyzer::isSimple(jump)) {
            redirectBranches(child, jump->name);
          }
        }
      }

      void redirectBranches(Block* from, Name to) {
        auto& branches = labelToBranches[from->name];
        for (auto* branch : branches) {
          if (BranchUtils::replacePossibleTarget(branch, from->name, to)) {
            worked = true;
          }
        }
        // if the jump is to another block then we can update the list, and
        // maybe push it even more later
        for (auto* branch : branches) {
          labelToBranches[to].push_back(branch);
        }
      }

      void finish(Function* func) {
        if (worked) {
          // by changing where brs go, we may change block types etc.
          ReFinalize().walkFunctionInModule(func, getModule());
        }
      }
    };
    JumpThreader jumpThreader;
    jumpThreader.setModule(getModule());
    jumpThreader.walkFunction(func);
    jumpThreader.finish(func);

    // perform some final optimizations
    struct FinalOptimizer : public PostWalker<FinalOptimizer> {
      bool shrink;
      PassOptions& passOptions;

      bool needUniqify = false;
      bool refinalize = false;

      FinalOptimizer(PassOptions& passOptions) : passOptions(passOptions) {}

      void visitBlock(Block* curr) {
        // if a block has an if br else br, we can un-conditionalize the latter,
        // allowing the if to become a br_if.
        // * note that if not in a block already, then we need to create a block
        //   for this, so not useful otherwise
        // * note that this only happens at the end of a block, as code after
        //   the if is dead
        // * note that we do this at the end, because un-conditionalizing can
        //   interfere with optimizeLoop()ing.
        auto& list = curr->list;
        for (Index i = 0; i < list.size(); i++) {
          auto* iff = list[i]->dynCast<If>();
          if (!iff || !iff->ifFalse) {
            // if it lacked an if-false, it would already be a br_if, as that's
            // the easy case
            continue;
          }
          auto* ifTrueBreak = iff->ifTrue->dynCast<Break>();
          if (ifTrueBreak && !ifTrueBreak->condition &&
              canTurnIfIntoBrIf(iff->condition,
                                ifTrueBreak->value,
                                passOptions,
                                *getModule())) {
            // we are an if-else where the ifTrue is a break without a
            // condition, so we can do this
            ifTrueBreak->condition = iff->condition;
            ifTrueBreak->finalize();
            list[i] = Builder(*getModule()).dropIfConcretelyTyped(ifTrueBreak);
            ExpressionManipulator::spliceIntoBlock(curr, i + 1, iff->ifFalse);
            continue;
          }
          // otherwise, perhaps we can flip the if
          auto* ifFalseBreak = iff->ifFalse->dynCast<Break>();
          if (ifFalseBreak && !ifFalseBreak->condition &&
              canTurnIfIntoBrIf(iff->condition,
                                ifFalseBreak->value,
                                passOptions,
                                *getModule())) {
            ifFalseBreak->condition =
              Builder(*getModule()).makeUnary(EqZInt32, iff->condition);
            ifFalseBreak->finalize();
            list[i] = Builder(*getModule()).dropIfConcretelyTyped(ifFalseBreak);
            ExpressionManipulator::spliceIntoBlock(curr, i + 1, iff->ifTrue);
            continue;
          }
        }
        if (list.size() >= 2) {
          // combine/optimize adjacent br_ifs + a br (maybe _if) right after it
          for (Index i = 0; i < list.size() - 1; i++) {
            auto* br1 = list[i]->dynCast<Break>();
            // avoid unreachable brs, as they are dead code anyhow, and after
            // merging them the outer scope could need type changes
            if (!br1 || !br1->condition || br1->type == Type::unreachable) {
              continue;
            }
            assert(!br1->value);
            auto* br2 = list[i + 1]->dynCast<Break>();
            if (!br2 || br1->name != br2->name) {
              continue;
            }
            assert(!br2->value); // same target as previous, which has no value
            // a br_if and then a br[_if] with the same target right after it
            if (br2->condition) {
              if (shrink && br2->type != Type::unreachable) {
                // Join adjacent br_ifs to the same target, making one br_if
                // with a "selectified" condition that executes both.
                if (!EffectAnalyzer(passOptions, *getModule(), br2->condition)
                       .hasSideEffects()) {
                  // it's ok to execute them both, do it
                  Builder builder(*getModule());
                  br1->condition =
                    builder.makeBinary(OrInt32, br1->condition, br2->condition);
                  ExpressionManipulator::nop(br2);
                }
              }
            } else {
              // merge, we go there anyhow
              Builder builder(*getModule());
              list[i] = builder.makeDrop(br1->condition);
            }
          }
          // Combine adjacent br_ifs that test the same value into a br_table,
          // when that makes sense.
          tablify(curr);
          // Pattern-patch ifs, recreating them when it makes sense.
          restructureIf(curr);
        }
      }

      void visitSwitch(Switch* curr) {
        if (BranchUtils::getUniqueTargets(curr).size() == 1) {
          // This switch has just one target no matter what; replace with a br
          // if we can (to do so, we must put the condition before a possible
          // value).
          if (!curr->value ||
              EffectAnalyzer::canReorder(
                passOptions, *getModule(), curr->condition, curr->value)) {
            Builder builder(*getModule());
            replaceCurrent(builder.makeSequence(
              builder.makeDrop(curr->condition), // might have side effects
              builder.makeBreak(curr->default_, curr->value)));
          }
        }
      }

      // Restructuring of ifs: if we have
      //   (block $x
      //     (drop (br_if $x (cond)))
      //     .., no other references to $x
      //   )
      // then we can turn that into (if (!cond) ..).
      // Code size wise, we turn the block into an if (no change), and
      // lose the br_if (-2). .. turns into the body of the if in the binary
      // format. We need to flip the condition, which at worst adds 1.
      // If the block has a return value, we can do something similar, removing
      // the drop from the br_if and putting the if on the outside,
      //   (block $x
      //     (drop (br_if $x (value) (cond)))
      //     .., no other references to $x
      //     ..final element..
      //   )
      // =>
      //   (if
      //     (cond)
      //     (value) ;; must not have side effects!
      //     (block
      //       .., no other references to $x
      //       ..final element..
      //     )
      //   )
      // This is beneficial as the block will likely go away in the binary
      // format (the if arm is an implicit block), and the drop is removed.
      void restructureIf(Block* curr) {
        auto& list = curr->list;
        // We should be called only on potentially-interesting lists.
        assert(list.size() >= 2);
        if (curr->name.is()) {
          Break* br = nullptr;
          Drop* drop = list[0]->dynCast<Drop>();
          if (drop) {
            br = drop->value->dynCast<Break>();
          } else {
            br = list[0]->dynCast<Break>();
          }
          // Check if the br is conditional and goes to the block. It may or may
          // not have a value, depending on if it was dropped or not. If the
          // type is unreachable that means it is not actually reached, which we
          // can ignore.
          Builder builder(*getModule());
          if (br && br->condition && br->name == curr->name &&
              br->type != Type::unreachable) {
            if (BranchUtils::BranchSeeker::count(curr, curr->name) == 1) {
              // no other breaks to that name, so we can do this
              if (!drop) {
                assert(!br->value);
                replaceCurrent(builder.makeIf(
                  builder.makeUnary(EqZInt32, br->condition), curr));
                ExpressionManipulator::nop(br);
                curr->finalize(curr->type);
              } else {
                // To use an if, the value must have no side effects, as in the
                // if it may not execute.
                if (!EffectAnalyzer(passOptions, *getModule(), br->value)
                       .hasSideEffects()) {
                  // We also need to reorder the condition and the value.
                  if (EffectAnalyzer::canReorder(
                        passOptions, *getModule(), br->condition, br->value)) {
                    ExpressionManipulator::nop(list[0]);
                    replaceCurrent(
                      builder.makeIf(br->condition, br->value, curr));
                  }
                } else {
                  // The value has side effects, so it must always execute. We
                  // may still be able to optimize this, however, by using a
                  // select:
                  //   (block $x
                  //     (drop (br_if $x (value) (cond)))
                  //     ..., no other references to $x
                  //     ..final element..
                  //   )
                  // =>
                  //   (select
                  //     (value)
                  //     (block $x
                  //       ..., no other references to $x
                  //       ..final element..
                  //     )
                  //     (cond)
                  //   )
                  // To do this we must be able to reorder the condition with
                  // the rest of the block (but not the value), and we must be
                  // able to make the rest of the block always execute, so it
                  // must not have side effects.
                  // TODO: we can do this when there *are* other refs to $x,
                  //       with a larger refactoring here.

                  // Test for the conditions with a temporary nop instead of the
                  // br_if.
                  Expression* old = list[0];
                  Nop nop;
                  // After this assignment, curr is what is left in the block
                  // after ignoring the br_if.
                  list[0] = &nop;
                  auto canReorder = EffectAnalyzer::canReorder(
                    passOptions, *getModule(), br->condition, curr);
                  auto hasSideEffects =
                    EffectAnalyzer(passOptions, *getModule(), curr)
                      .hasSideEffects();
                  list[0] = old;
                  if (canReorder && !hasSideEffects &&
                      Properties::canEmitSelectWithArms(br->value, curr)) {
                    ExpressionManipulator::nop(list[0]);
                    replaceCurrent(
                      builder.makeSelect(br->condition, br->value, curr));
                  }
                }
              }
            }
          }
        }
      }

      void visitIf(If* curr) {
        // we may have simplified ifs enough to turn them into selects
        if (auto* select = selectify(curr)) {
          replaceCurrent(select);
        }
      }

      // Convert an if into a select, if possible and beneficial to do so.
      Select* selectify(If* iff) {
        // Only an if-else can be turned into a select.
        if (!iff->ifFalse) {
          return nullptr;
        }
        if (!Properties::canEmitSelectWithArms(iff->ifTrue, iff->ifFalse)) {
          return nullptr;
        }
        if (iff->condition->type == Type::unreachable) {
          // An if with an unreachable condition may nonetheless have a type
          // that is not unreachable,
          //
          // (if (result i32) (unreachable) ..)
          //
          // Turning such an if into a select would change the type of the
          // expression, which would require updating types further up. Avoid
          // that, leaving dead code elimination to that dedicated pass.
          return nullptr;
        }
        // This is always helpful for code size, but can be a tradeoff with
        // performance as we run both code paths. So when shrinking we always
        // try to do this, but otherwise must consider more carefully.
        if (tooCostlyToRunUnconditionally(
              passOptions, iff->ifTrue, iff->ifFalse)) {
          return nullptr;
        }
        // Check if side effects allow this: we need to execute the two arms
        // unconditionally, and also to make the condition run last.
        EffectAnalyzer ifTrue(passOptions, *getModule(), iff->ifTrue);
        if (ifTrue.hasSideEffects()) {
          return nullptr;
        }
        EffectAnalyzer ifFalse(passOptions, *getModule(), iff->ifFalse);
        if (ifFalse.hasSideEffects()) {
          return nullptr;
        }
        EffectAnalyzer condition(passOptions, *getModule(), iff->condition);
        if (condition.invalidates(ifTrue) || condition.invalidates(ifFalse)) {
          return nullptr;
        }
        auto* select = Builder(*getModule())
                         .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse);
        if (select->type != iff->type) {
          // If the select is more refined than the if it replaces, we must
          // propagate that outwards.
          refinalize = true;
        }
        return select;
      }

      void visitLocalSet(LocalSet* curr) {
        // Sets of an if can be optimized in various ways that remove part of
        // the if branching, or all of it.
        // The optimizations we can do here can recurse and call each
        // other, so pass around a pointer to the output.
        optimizeSetIf(getCurrentPointer());
      }

      void optimizeSetIf(Expression** currp) {
        if (optimizeSetIfWithBrArm(currp)) {
          return;
        }
        if (optimizeSetIfWithCopyArm(currp)) {
          return;
        }
      }

      // If one arm is a br, we prefer a br_if and the set later:
      //  (local.set $x
      //    (if (result i32)
      //      (..condition..)
      //      (br $somewhere)
      //      (..result)
      //    )
      //  )
      // =>
      //  (br_if $somewhere
      //    (..condition..)
      //  )
      //  (local.set $x
      //    (..result)
      //  )
      // TODO: handle a condition in the br? need to watch for side effects
      bool optimizeSetIfWithBrArm(Expression** currp) {
        auto* set = (*currp)->cast<LocalSet>();
        auto* iff = set->value->dynCast<If>();
        if (!iff || !iff->type.isConcrete() ||
            !iff->condition->type.isConcrete()) {
          return false;
        }
        auto tryToOptimize =
          [&](Expression* one, Expression* two, bool flipCondition) {
            if (one->type == Type::unreachable &&
                two->type != Type::unreachable) {
              if (auto* br = one->dynCast<Break>()) {
                if (ExpressionAnalyzer::isSimple(br)) {
                  // Wonderful, do it!
                  Builder builder(*getModule());
                  if (flipCondition) {
                    builder.flip(iff);
                  }
                  br->condition = iff->condition;
                  br->finalize();
                  set->value = two;
                  auto* block = builder.makeSequence(br, set);
                  *currp = block;
                  // Recurse on the set, which now has a new value.
                  optimizeSetIf(&block->list[1]);
                  return true;
                }
              }
            }
            return false;
          };
        return tryToOptimize(iff->ifTrue, iff->ifFalse, false) ||
               tryToOptimize(iff->ifFalse, iff->ifTrue, true);
      }

      // If one arm is a get of the same outer set, it is a copy which
      // we can remove. If this is not a tee, then we remove the get
      // as well as the if-else opcode in the binary format, which is
      // great:
      //  (local.set $x
      //    (if (result i32)
      //      (..condition..)
      //      (..result)
      //      (local.get $x)
      //    )
      //  )
      // =>
      //  (if
      //    (..condition..)
      //    (local.set $x
      //      (..result)
      //    )
      //  )
      // If this is a tee, then we can do the same operation but
      // inside a block, and keep the get:
      //  (local.tee $x
      //    (if (result i32)
      //      (..condition..)
      //      (..result)
      //      (local.get $x)
      //    )
      //  )
      // =>
      //  (block (result i32)
      //    (if
      //      (..condition..)
      //      (local.set $x
      //        (..result)
      //      )
      //    )
      //    (local.get $x)
      //  )
      // We save the if-else opcode, and add the block's opcodes.
      // This may be detrimental, however, often the block can be
      // merged or eliminated given the outside scope, and we
      // removed one of the if branches.
      bool optimizeSetIfWithCopyArm(Expression** currp) {
        auto* set = (*currp)->cast<LocalSet>();
        auto* iff = set->value->dynCast<If>();
        if (!iff || !iff->type.isConcrete() ||
            !iff->condition->type.isConcrete()) {
          return false;
        }
        Builder builder(*getModule());
        LocalGet* get = iff->ifTrue->dynCast<LocalGet>();
        if (get && get->index == set->index) {
          builder.flip(iff);
        } else {
          get = iff->ifFalse->dynCast<LocalGet>();
          if (get && get->index != set->index) {
            get = nullptr;
          }
        }
        if (!get) {
          return false;
        }
        // We can do it!
        bool tee = set->isTee();
        assert(set->index == get->index);
        assert(iff->ifFalse == get);
        set->value = iff->ifTrue;
        set->finalize();
        iff->ifTrue = set;
        iff->ifFalse = nullptr;
        iff->finalize();
        Expression* replacement = iff;
        if (tee) {
          set->makeSet();
          // We need a block too.
          replacement = builder.makeSequence(iff,
                                             get // reuse the get
          );
        }
        *currp = replacement;
        // Recurse on the set, which now has a new value.
        optimizeSetIf(&iff->ifTrue);
        return true;
      }

      // (br_if)+ => br_table
      // we look for the specific pattern of
      //  (br_if ..target1..
      //    (i32.eq
      //      (..input..)
      //      (i32.const ..value1..)
      //    )
      //  )
      //  (br_if ..target2..
      //    (i32.eq
      //      (..input..)
      //      (i32.const ..value2..)
      //    )
      //  )
      // TODO: consider also looking at <= etc. and not just eq
      void tablify(Block* block) {
        auto& list = block->list;
        if (list.size() <= 1) {
          return;
        }

        // Heuristics. These are slightly inspired by the constants from the
        // asm.js backend.

        // How many br_ifs we need to see to consider doing this
        const uint32_t MIN_NUM = 3;
        // How much of a range of values is definitely too big
        const uint32_t MAX_RANGE = 1024;
        // Multiplied by the number of br_ifs, then compared to the range. When
        // this is high, we allow larger ranges.
        const uint32_t NUM_TO_RANGE_FACTOR = 3;

        // check if the input is a proper br_if on an i32.eq of a condition
        // value to a const, and the const is in the proper range,
        // [0-int32_max), to avoid overflow concerns. returns the br_if if so,
        // or nullptr otherwise
        auto getProperBrIf = [](Expression* curr) -> Break* {
          auto* br = curr->dynCast<Break>();
          if (!br) {
            return nullptr;
          }
          if (!br->condition || br->value) {
            return nullptr;
          }
          if (br->type != Type::none) {
            // no value, so can be unreachable or none. ignore unreachable ones,
            // dce will clean it up
            return nullptr;
          }
          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;
          }
          if (binary->op != EqInt32) {
            return nullptr;
          }
          auto* c = binary->right->dynCast<Const>();
          if (!c) {
            return nullptr;
          }
          uint32_t value = c->value.geti32();
          if (value >= uint32_t(std::numeric_limits<int32_t>::max())) {
            return nullptr;
          }
          return br;
        };

        // check if the input is a proper br_if
        // and returns the condition if so, or nullptr otherwise
        auto getProperBrIfConditionValue =
          [&getProperBrIf](Expression* curr) -> Expression* {
          auto* br = getProperBrIf(curr);
          if (!br) {
            return nullptr;
          }
          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 {
          auto* condition = getProperBrIf(curr)->condition;
          if (auto* binary = condition->dynCast<Binary>()) {
            return binary->right->cast<Const>()->value.geti32();
          } else if ([[maybe_unused]] 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) {
          auto* conditionValue = getProperBrIfConditionValue(list[start]);
          if (!conditionValue) {
            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)
                .hasSideEffects()) {
            start++;
            continue;
          }
          // look for a "run" of br_ifs with all the same conditionValue, and
          // having unique constants (an overlapping constant could be handled,
          // just the first branch is taken, but we can't remove the other br_if
          // (it may be the only branch keeping a block reachable), which may
          // make this bad for code size.
          Index end = start + 1;
          std::unordered_set<uint32_t> usedConstants;
          usedConstants.insert(getProperBrIfConstant(list[start]));
          while (end < list.size() &&
                 ExpressionAnalyzer::equal(
                   getProperBrIfConditionValue(list[end]), conditionValue)) {
            if (!usedConstants.insert(getProperBrIfConstant(list[end]))
                   .second) {
              // this constant already appeared
              break;
            }
            end++;
          }
          auto num = end - start;
          if (num >= 2 && num >= MIN_NUM) {
            // we found a suitable range, [start, end), containing more than 1
            // element. let's see if it's worth it
            auto min = getProperBrIfConstant(list[start]);
            auto max = min;
            for (Index i = start + 1; i < end; i++) {
              auto* curr = list[i];
              min = std::min(min, getProperBrIfConstant(curr));
              max = std::max(max, getProperBrIfConstant(curr));
            }
            uint32_t range = max - min;
            // decision time
            if (range <= MAX_RANGE && range <= num * NUM_TO_RANGE_FACTOR) {
              // great! let's do this
              std::unordered_set<Name> usedNames;
              for (Index i = start; i < end; i++) {
                usedNames.insert(getProperBrIf(list[i])->name);
              }
              // we need a name for the default too
              Name defaultName;
              Index i = 0;
              while (1) {
                defaultName = "tablify|" + std::to_string(i++);
                if (usedNames.count(defaultName) == 0) {
                  break;
                }
              }
              std::vector<Name> table;
              for (Index i = start; i < end; i++) {
                auto name = getProperBrIf(list[i])->name;
                auto index = getProperBrIfConstant(list[i]);
                index -= min;
                while (table.size() <= index) {
                  table.push_back(defaultName);
                }
                // we should have made sure there are no overlaps
                assert(table[index] == defaultName);
                table[index] = name;
              }
              Builder builder(*getModule());
              // the table and condition are offset by the min
              auto* newCondition = getProperBrIfConditionValue(list[start]);

              if (min != 0) {
                newCondition = builder.makeBinary(
                  SubInt32, newCondition, builder.makeConst(int32_t(min)));
              }
              list[end - 1] = builder.makeBlock(
                defaultName,
                builder.makeSwitch(table, defaultName, newCondition));
              for (Index i = start; i < end - 1; i++) {
                ExpressionManipulator::nop(list[i]);
              }
              // the defaultName may exist elsewhere in this function,
              // uniquify it later
              needUniqify = true;
            }
          }
          start = end;
        }
      }
    };
    FinalOptimizer finalOptimizer(getPassOptions());
    finalOptimizer.setModule(getModule());
    finalOptimizer.shrink = getPassRunner()->options.shrinkLevel > 0;
    finalOptimizer.walkFunction(func);
    if (finalOptimizer.needUniqify) {
      wasm::UniqueNameMapper::uniquify(func->body);
    }
    if (finalOptimizer.refinalize) {
      ReFinalize().walkFunctionInModule(func, getModule());
    }
  }
};

Pass* createRemoveUnusedBrsPass() { return new RemoveUnusedBrs(); }

} // namespace wasm
