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

//
// Computes code at compile time where possible, replacing it with the
// computed constant.
//
// The "propagate" variant of this pass also propagates constants across
// sets and gets, which implements a standard constant propagation.
//
// Possible nondeterminism: WebAssembly NaN signs are nondeterministic,
// and this pass may optimize e.g. a float 0 / 0 into +nan while a VM may
// emit -nan, which can be a noticeable difference if the bits are
// looked at.
//

#include "ir/iteration.h"
#include "ir/literal-utils.h"
#include "ir/local-graph.h"
#include "ir/manipulation.h"
#include "ir/properties.h"
#include "ir/utils.h"
#include "pass.h"
#include "support/insert_ordered.h"
#include "support/small_vector.h"
#include "wasm-builder.h"
#include "wasm-interpreter.h"
#include "wasm.h"

namespace wasm {

// A map of gets to their constant values. If a get does not have a constant
// value then it does not appear in the map (that avoids allocating for the
// majority of gets).
using GetValues = std::unordered_map<LocalGet*, Literals>;

// A map of values on the heap. This maps the expressions that create the
// heap data (struct.new, array.new, etc.) to the data they are created with.
// Each such expression gets its own GCData created for it. This allows
// computing identity between locals referring to the same GCData, by seeing
// if they point to the same thing.
//
// Note that a source expression may create different data each time it is
// reached in a loop,
//
// (loop
//  (if ..
//   (local.set $x
//    (struct.new ..
//   )
//  )
//  ..compare $x to something..
// )
//
// Just like in SSA form, this is not a problem because the loop entry must
// have a merge, if a value entering the loop might be noticed. In SSA form
// that means a phi is created, and identity is set there. In our
// representation, the merge will cause a local.get of $x to have more
// possible input values than that struct.new, which means we will not infer
// a value for it, and not attempt to say anything about comparisons of $x.
struct HeapValues {
  struct Entry {
    // The GC data for an expression.
    std::shared_ptr<GCData> data;
    // Whether the expression has effects. If it does then we must recompute it
    // each time we see it, even though we return |data| to represent it.
    // (Recomputing will apply those effects each time, so we don't forget them
    // when we read from the cache. This recomputing is rare, and doesn't happen
    // e.g. in global GC objects, where most of the work happens, so this cache
    // still saves a lot.)
    bool hasEffects;
  };

  std::unordered_map<Expression*, Entry> map;
};

// Precomputes an expression. Errors if we hit anything that can't be
// precomputed. Inherits most of its functionality from
// ConstantExpressionRunner, which it shares with the C-API, but adds handling
// of GetValues computed during the precompute pass.
class PrecomputingExpressionRunner
  : public ConstantExpressionRunner<PrecomputingExpressionRunner> {

  using Super = ConstantExpressionRunner<PrecomputingExpressionRunner>;

  // Concrete values of gets computed during the pass, which the runner does not
  // know about since it only records values of sets it visits.
  const GetValues& getValues;

  HeapValues& heapValues;

  // Limit evaluation depth for 2 reasons: first, it is highly unlikely
  // that we can do anything useful to precompute a hugely nested expression
  // (we should succeed at smaller parts of it first). Second, a low limit is
  // helpful to avoid platform differences in native stack sizes.
  static const Index MAX_DEPTH = 50;

  // Limit loop iterations since loops might be infinite. Since we are going to
  // replace the expression and must preserve side effects, we limit this to the
  // very first iteration because a side effect would be necessary to achieve
  // more than one iteration before becoming concrete.
  static const Index MAX_LOOP_ITERATIONS = 1;

public:
  PrecomputingExpressionRunner(Module* module,
                               const GetValues& getValues,
                               HeapValues& heapValues,
                               bool replaceExpression)
    : ConstantExpressionRunner<PrecomputingExpressionRunner>(
        module,
        replaceExpression ? FlagValues::PRESERVE_SIDEEFFECTS
                          : FlagValues::DEFAULT,
        MAX_DEPTH,
        MAX_LOOP_ITERATIONS),
      getValues(getValues), heapValues(heapValues) {}

  Flow visitLocalGet(LocalGet* curr) {
    auto iter = getValues.find(curr);
    if (iter != getValues.end()) {
      auto values = iter->second;
      assert(values.isConcrete());
      return Flow(values);
    }
    return ConstantExpressionRunner<
      PrecomputingExpressionRunner>::visitLocalGet(curr);
  }

  // TODO: Use immutability for values
  Flow visitStructNew(StructNew* curr) {
    return getGCAllocation(curr, [&]() { return Super::visitStructNew(curr); });
  }
  Flow visitStructSet(StructSet* curr) { return Flow(NONCONSTANT_FLOW); }
  Flow visitStructRMW(StructRMW* curr) { return Flow(NONCONSTANT_FLOW); }
  Flow visitStructCmpxchg(StructCmpxchg* curr) {
    return Flow(NONCONSTANT_FLOW);
  }
  Flow visitStructGet(StructGet* curr) {
    if (curr->ref->type == Type::unreachable || curr->ref->type.isNull()) {
      return Flow(NONCONSTANT_FLOW);
    }
    switch (curr->order) {
      case MemoryOrder::Unordered:
        // This can always be precomputed.
        break;
      case MemoryOrder::SeqCst:
        // This can never be precomputed away because it synchronizes with other
        // threads.
        return Flow(NONCONSTANT_FLOW);
      case MemoryOrder::AcqRel:
        // This synchronizes only with writes to the same data, so it can still
        // be precomputed if the data is not shared with other threads.
        if (curr->ref->type.getHeapType().isShared()) {
          return Flow(NONCONSTANT_FLOW);
        }
        break;
    }
    // If this field is immutable then we may be able to precompute this, as
    // if we also created the data in this function (or it was created in an
    // immutable global) then we know the value in the field. If it is
    // immutable, call the super method which will do the rest here. That
    // includes checking for the data being properly created, as if it was
    // not then we will not have a constant value for it, which means the
    // local.get of that value will stop us.
    auto& field = curr->ref->type.getHeapType().getStruct().fields[curr->index];
    if (field.mutable_ == Mutable) {
      return Flow(NONCONSTANT_FLOW);
    }
    return Super::visitStructGet(curr);
  }
  Flow visitArrayNew(ArrayNew* curr) {
    return getGCAllocation(curr, [&]() { return Super::visitArrayNew(curr); });
  }
  Flow visitArrayNewFixed(ArrayNewFixed* curr) {
    return getGCAllocation(curr,
                           [&]() { return Super::visitArrayNewFixed(curr); });
  }
  Flow visitArraySet(ArraySet* curr) { return Flow(NONCONSTANT_FLOW); }
  Flow visitArrayRMW(ArrayRMW* curr) { return Flow(NONCONSTANT_FLOW); }
  Flow visitArrayCmpxchg(ArrayCmpxchg* curr) { return Flow(NONCONSTANT_FLOW); }
  Flow visitArrayGet(ArrayGet* curr) {
    if (curr->ref->type == Type::unreachable || curr->ref->type.isNull()) {
      return Flow(NONCONSTANT_FLOW);
    }
    switch (curr->order) {
      case MemoryOrder::Unordered:
        // This can always be precomputed.
        break;
      case MemoryOrder::SeqCst:
        // This can never be precomputed away because it synchronizes with other
        // threads.
        return Flow(NONCONSTANT_FLOW);
      case MemoryOrder::AcqRel:
        // This synchronizes only with writes to the same data, so it can still
        // be precomputed if the data is not shared with other threads.
        if (curr->ref->type.getHeapType().isShared()) {
          return Flow(NONCONSTANT_FLOW);
        }
        break;
    }
    // See above with struct.get
    auto element = curr->ref->type.getHeapType().getArray().element;
    if (element.mutable_ == Immutable) {
      return Super::visitArrayGet(curr);
    }

    // Otherwise, we've failed to precompute.
    return Flow(NONCONSTANT_FLOW);
  }
  // ArrayLen is not disallowed here as it is an immutable property.
  Flow visitArrayCopy(ArrayCopy* curr) { return Flow(NONCONSTANT_FLOW); }
  Flow visitArrayLoad(ArrayLoad* curr) {
    // TODO: We could optimize loads from immutable data, like ArrayGet.
    return Flow(NONCONSTANT_FLOW);
  }
  Flow visitArrayStore(ArrayStore* curr) { return Flow(NONCONSTANT_FLOW); }

  // Generates heap info for a heap-allocating expression.
  Flow getGCAllocation(Expression* curr, std::function<Flow()> visitFunc) {
    // We must return a literal that refers to the canonical location for this
    // source expression, so that each time we compute a specific *.new then
    // we get the same identity.
    auto iter = heapValues.map.find(curr);
    if (iter != heapValues.map.end()) {
      auto& [data, hasEffects] = iter->second;
      if (hasEffects) {
        // Visit, so we recompute the effects. (This is rare, see comment
        // above.)
        auto flow = visitFunc();
        // Also check the result of the effects - if it is non-constant, we
        // cannot use it. (This can happen during propagation, when we see that
        // other inputs exist to something we depend on.)
        if (flow.breaking()) {
          return flow;
        }
      }
      // Refer to the same canonical GCData that we already created.
      return Literal(data, curr->type.getHeapType());
    }
    // Only call the visitor function here, so we do it once per allocation. See
    // if we have effects while doing so.
    auto flow = visitFunc();
    if (flow.breaking()) {
      return flow;
    }
    heapValues.map[curr] =
      HeapValues::Entry{flow.getSingleValue().getGCData(), hasEffectfulSets()};
    return flow;
  }

  Flow visitStringNew(StringNew* curr) {
    if (curr->op != StringNewWTF16Array) {
      // TODO: handle other string ops. For now we focus on JS-like strings.
      return Flow(NONCONSTANT_FLOW);
    }

    // string.new_wtf16_array is effectively an Array read operation, so
    // we cannot optimize mutable arrays. Unfortunately, it is only valid with
    // mutable arrays, so we cannot generally precompute it. As a special
    // exception, we can precompute if the child is an array allocation because
    // then we know the allocation will not escape anywhere else.
    auto refType = curr->ref->type;
    if (refType.isRef() &&
        (curr->ref->is<ArrayNew>() || curr->ref->is<ArrayNewData>() ||
         curr->ref->is<ArrayNewFixed>())) {
      return Super::visitStringNew(curr);
    }

    // TODO: Handle more general cases as well.
    return Flow(NONCONSTANT_FLOW);
  }

  Flow visitStringEncode(StringEncode* curr) {
    // string.encode_wtf16_array is effectively an Array write operation, so
    // just like ArraySet and ArrayCopy above we must mark it as disallowed
    // (due to side effects). (And we do not support other operations than
    // string.encode_wtf16_array anyhow.)
    return Flow(NONCONSTANT_FLOW);
  }
};

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

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

  bool propagate = false;

  Precompute(bool propagate) : propagate(propagate) {}

  GetValues getValues;
  HeapValues heapValues;

  bool canPartiallyPrecompute;

  void doWalkFunction(Function* func) {
    // Perform partial precomputing only when the optimization level is non-
    // trivial, as it is slower and less likely to help.
    canPartiallyPrecompute = getPassOptions().optimizeLevel >= 2;

    // Walk the function and precompute things.
    Super::doWalkFunction(func);
    partiallyPrecompute(func);
    if (!propagate) {
      return;
    }
    // When propagating, we can utilize the graph of local operations to
    // precompute the values from a local.set to a local.get. This populates
    // getValues which is then used by a subsequent walk that applies those
    // values.
    bool propagated = propagateLocals(func);
    if (propagated) {
      // We found constants to propagate and entered them in getValues. Do
      // another walk to apply them and perhaps other optimizations that are
      // unlocked.
      Super::doWalkFunction(func);
      // We could also try to partially precompute again, but that is a somewhat
      // heavy operation, so we only do it the first time, and leave such things
      // for later runs of this pass and for --converge.
    }
    // Note that in principle even more cycles could find further work here, in
    // very rare cases. To avoid constructing a LocalGraph again just for that
    // unlikely chance, we leave such things for later.
  }

  void visitExpression(Expression* curr) {
    // Ignore trivial things like constants, nops, local/global.set (which have
    // an effect we cannot remove, and it is simpler to ignore them here than
    // later below), return (which we cannot improve), and loop (which it is
    // simpler to leave for other passes).
    if (Properties::isConstantExpression(curr) || curr->is<Nop>() ||
        curr->is<LocalSet>() || curr->is<GlobalSet>() || curr->is<Return>() ||
        curr->is<Loop>()) {
      return;
    }
    // Breaks with conditions can be simplified, but unconditional ones are like
    // returns, and we cannot improve.
    if (auto* br = curr->dynCast<Break>()) {
      if (!br->condition) {
        return;
      }
    }

    // See if we can precompute the value that flows out. We set
    // |replaceExpression| to false because we do not necessarily want to
    // replace it entirely, see below - we may keep parts, in some cases, if we
    // can still simplify it to a precomputed value.
    Flow flow;
    PrecomputingExpressionRunner runner(
      getModule(), getValues, heapValues, false /* replaceExpression */);
    try {
      flow = runner.visit(curr);
    } catch (NonconstantException&) {
      return;
    }
    // The resulting value must be of a type we can emit a constant for (or
    // there must be no value at all, in which case the value is a nop).
    if (!canEmitConstantFor(flow.values)) {
      return;
    }
    if (flow.breakTo == NONCONSTANT_FLOW) {
      // This cannot be turned into a constant, but perhaps we can partially
      // precompute it.
      considerPartiallyPrecomputing(curr);
      return;
    }
    // TODO: Handle suspends somehow?
    if (flow.suspendTag) {
      return;
    }

    // This looks like a promising precomputation: We have found that its value,
    // if any, can be emitted as a constant (or there is no value, and it is a
    // nop or break etc.). Build that value, so we can replace the expression
    // with it.
    Builder builder(*getModule());
    Expression* value = nullptr;
    if (flow.values.isConcrete()) {
      value = flow.getConstExpression(*getModule());
    }
    if (flow.breaking()) {
      if (flow.breakTo == RETURN_FLOW) {
        // We avoided trivial returns earlier (by doing so, we avoid wasted
        // work replacing a return with itself).
        assert(!curr->is<Return>());
        value = builder.makeReturn(value);
      } else {
        value = builder.makeBreak(flow.breakTo, value);
      }
      // Note we don't need to handle RETURN_CALL_FLOW, as the call there has
      // effects that would stop us earlier.
    }

    // We have something to replace the expression. While precomputing the
    // expression, we verified it has no effects that cause problems - no traps
    // or exceptions etc., as those things would lead to NONCONSTANT_FLOW. We
    // can therefore replace this with what flows out of it. The only exception
    // is that we set replaceExpression to false, above, which means we run the
    // interpreter without PRESERVE_SIDEEFFECTS. That allows local and global
    // sets to happen (to help optimize small code fragments with sets and
    // gets). To handle that, keep relevant children if we have such sets.
    if (runner.hasEffectfulSets()) {
      if (curr->is<Block>() || curr->is<If>() || curr->is<Try>()) {
        // These control flow structures have children that might not execute.
        // We know that some of the children have effectful sets, but not which,
        // and we can't just keep them all, so give up.
        // TODO: Check if this would be useful to improve, but other passes
        //       might do enough already.
        return;
      }

      // To keep things simple, stop here if we are precomputing to a break/
      // return. Handling that case requires ordering considerations:
      //
      //  (foo
      //    (br)
      //    (call)
      //  )
      //
      // Here we know we need to keep the call, and can remove foo, but this
      // would be wrong:
      //
      //  (block
      //    ;; removed br
      //    (call)
      //    (br) ;; the value we precompute to, added at the end
      //  )
      //
      // Instead we must keep the br, leaving this for later opts to improve:
      //
      //  (block
      //    (br)
      //    (call)
      //    (br)
      //  )
      //
      // That is, we cannot remove unneeded children easily in this case, where
      // control flow might transfer, so we need to keep all children when we
      // remove foo. In that case, it's not clear we are helping much, and other
      // passes can do better with the break/return anyhow. After dismissing
      // this situation, we know no transfer of control flow needs to be handled
      // in the code below (because we executed the code, and found it did not
      // do so).
      if (flow.breaking()) {
        return;
      }

      // Find the necessary children that we must keep.
      SmallVector<Expression*, 10> kept;
      for (auto* child : ChildIterator(curr)) {
        EffectAnalyzer effects(getPassOptions(), *getModule(), child);
        if (!effects.localsWritten.empty() || !effects.globalsWritten.empty()) {
          kept.push_back(builder.makeDrop(child));
        }
      }
      // Find all the things we must keep, which might include |value|.
      if (!kept.empty()) {
        if (value) {
          kept.push_back(value);
        }
        if (kept.size() == 1) {
          value = kept[0];
        } else {
          // We are returning a block with some kept children + some value. This
          // may seem to increase code size in some cases, but it cannot do so
          // monotonically: while doing all this we are definitely removing
          // |curr| itself, so we are making progress, even if we emit a new
          // constant that we weren't before. That is, we are not in this
          // situation:
          //
          //   (foo A B) => (block (foo A B) (value))
          //
          // We are in this one:
          //
          //   (foo A B) => (block A B (value))
          //
          // where foo vanishes.
          value = builder.makeBlock(kept);
        }
      }
    }
    if (!value) {
      // We don't need to replace this with anything: there is no value or other
      // code that we need. Just nop it.
      ExpressionManipulator::nop(curr);
      return;
    }
    replaceCurrent(value);
  }

  void visitBlock(Block* curr) {
    // When block precomputation fails, it can lead to quadratic slowness due to
    // the "tower of blocks" pattern used to implement switches:
    //
    //  (block
    //    (block
    //      ...
    //        (block
    //          (br_table ..
    //
    // If we try to precompute each block here, and fail on each, then we end up
    // doing quadratic work. This is also wasted work as once a nested block
    // fails to precompute there is not really a chance to succeed on the
    // parent. If we do *not* fail to precompute, however, then we do want to
    // precompute such nested blocks, e.g.:
    //
    //  (block $out
    //    (block
    //      (br $out)
    //    )
    //  )
    //
    // Here we *can* precompute the inner block, so when we get to the outer one
    // we see this:
    //
    //  (block $out
    //    (br $out)
    //  )
    //
    // And that precomputes to nothing. Therefore when we see a child of the
    // block that is another block (it failed to precompute to something
    // simpler) then we leave early here.
    //
    // Note that in theory we could still precompute here if wasm had
    // instructions that allow such things, e.g.:
    //
    //  (block $out
    //    (block
    //      (cause side effect1)
    //      (cause side effect2)
    //    )
    //    (undo those side effects exactly)
    //  )
    //
    // We are forced to invent a side effect that we can precisely undo (unlike,
    // say locals - a local.set would persist outside of the block, and even if
    // we did another set to the original value, this pass doesn't track values
    // that way). Only with that can we make the inner block un-precomputable
    // (because there are side effects) but the outer one is (because those
    // effects are undone). Note that it is critical that we have two things in
    // the block, so that we can't precompute it to one of them (which is what
    // we did to the br in the previous example). Note also that this is still
    // optimizable using other passes, as merge-blocks will fold the two blocks
    // together.
    if (!curr->list.empty() && curr->list[0]->is<Block>()) {
      // The first child is a block, that is, it could not be simplified, so
      // this looks like the "tower of blocks" pattern. Avoid quadratic time
      // here as explained above. (We could also look at other children of the
      // block, but the only real-world pattern identified so far is on the
      // first child, so keep things simple here.)
      return;
    }

    // Otherwise, precompute normally like all other expressions.
    visitExpression(curr);
  }

  // If we failed to precompute a constant, perhaps we can still precompute part
  // of an expression. Specifically, consider this case:
  //
  //  (A
  //    (select
  //      (B)
  //      (C)
  //      (condition)
  //    )
  //  )
  //
  // Perhaps we can compute A(B) and A(C). If so, we can emit a better select:
  //
  //  (select
  //    (constant result of A(B))
  //    (constant result of A(C))
  //    (condition)
  //  )
  //
  // Note that in general for code size we want to move operations *out* of
  // selects and ifs (OptimizeInstructions does that), but here we are
  // computing two constants which replace three expressions, so it is
  // worthwhile.
  //
  // To do such partial precomputing, in the main pass we note selects that look
  // promising. If we find any then we do a second pass later just for that (as
  // doing so requires walking up the stack in a manner that we want to avoid in
  // the main pass for overhead reasons; see below).
  //
  // Note that selects are all we really need here: Other passes would turn an
  // if into a select if the arms are simple enough, and only in those cases
  // (simple arms) do we have a chance at partially precomputing. For example,
  // if an arm is a constant then we can, but if it is a call then we can't.)
  // However, there are cases like an if with arms with side effects that end in
  // precomputable things, that are missed atm TODO
  std::unordered_set<Select*> partiallyPrecomputable;

  void considerPartiallyPrecomputing(Expression* curr) {
    if (!canPartiallyPrecompute) {
      return;
    }

    if (auto* select = curr->dynCast<Select>()) {
      // We only have a reasonable hope of success if the select arms are things
      // like constants or global gets. At a first approximation, allow the set
      // of things we allow in constant initializers (but we can probably allow
      // more here TODO).
      //
      // We also ignore selects with no parent (that are the entire function
      // body) as then there is nothing to optimize into their arms.
      auto& wasm = *getModule();
      if (Properties::isValidConstantExpression(wasm, select->ifTrue) &&
          Properties::isValidConstantExpression(wasm, select->ifFalse) &&
          getFunction()->body != select) {
        partiallyPrecomputable.insert(select);
      }
    }
  }

  // To partially precompute selects we walk up the stack from them, like this:
  //
  //  (A
  //    (B
  //      (select
  //        (C)
  //        (D)
  //        (condition)
  //      )
  //    )
  //  )
  //
  // First we try to apply B to C and D. If that works, we arrive at this:
  //
  //  (A
  //    (select
  //      (constant result of B(C))
  //      (constant result of B(D))
  //      (condition)
  //    )
  //  )
  //
  // We can then proceed to perhaps apply A. However, even if we failed to apply
  // B then we can try to apply A and B together, because that combination may
  // succeed where incremental work fails, for example:
  //
  //  (global $C
  //    (struct.new    ;; outer
  //      (struct.new  ;; inner
  //        (i32.const 10)
  //      )
  //    )
  //  )
  //
  //  (struct.get    ;; outer
  //    (struct.get  ;; inner
  //      (select
  //        (global.get $C)
  //        (global.get $D)
  //        (condition)
  //      )
  //    )
  //  )
  //
  // Applying the inner struct.get to $C leads us to the inner struct.new, but
  // that is an interior pointer in the global - it is not something we can
  // refer to using a global.get, so precomputing it fails. However, when we
  // apply both struct.gets at once we arrive at the outer struct.new, which is
  // in fact the global $C, and we succeed.
  void partiallyPrecompute(Function* func) {
    if (!canPartiallyPrecompute || partiallyPrecomputable.empty()) {
      // Nothing to do.
      return;
    }

    // Walk the function to find the parent stacks of the promising selects. We
    // copy the stacks and process them later. We do it like this because if we
    // wanted to process stacks as we reached them then we'd trip over
    // ourselves: when we optimize we replace a parent, but that parent is an
    // expression we'll reach later in the walk, so modifying it is unsafe.
    struct StackFinder : public ExpressionStackWalker<StackFinder> {
      Precompute& parent;

      StackFinder(Precompute& parent) : parent(parent) {}

      // We will later iterate on this in the order of insertion, which keeps
      // things deterministic, and also usually lets us do consecutive work
      // like a select nested in another select's condition, simply because we
      // will traverse the selects in postorder (however, because we cannot
      // always succeed in an incremental manner - see the comment on this
      // function - it is possible in theory that some work can happen only in a
      // later execution of the pass).
      InsertOrderedMap<Select*, ExpressionStack> stackMap;

      void visitSelect(Select* curr) {
        if (parent.partiallyPrecomputable.contains(curr)) {
          stackMap[curr] = expressionStack;
        }
      }
    } stackFinder(*this);
    stackFinder.walkFunction(func);

    // Note which expressions we've modified as we go, as it is invalid to
    // modify more than once. This could happen in theory in a situation like
    // this:
    //
    //  (ternary.f32.max  ;; fictional instruction for explanatory purposes
    //    (select ..)
    //    (select ..)
    //    (f32.infinity)
    //  )
    //
    // When we consider the first select we can see that the computation result
    // is always infinity, so we can optimize here and replace the ternary. Then
    // the same thing happens with the second select, causing the ternary to be
    // replaced again, which is unsafe because it no longer exists after we
    // precomputed it the first time. (Note that in this example the result is
    // the same either way, but at least in theory an instruction could exist
    // for whom there was a difference.) In practice it does not seem that wasm
    // has instructions capable of this atm but this code is still useful to
    // guard against future problems, and as a minor speedup (quickly skip code
    // if it was already modified).
    std::unordered_set<Expression*> modified;

    for (auto& [select, stack] : stackFinder.stackMap) {
      // Each stack ends in the select itself, and contains more than the select
      // itself (otherwise we'd have ignored the select), i.e., the select has a
      // parent that we can try to optimize into the arms.
      assert(stack.back() == select);
      assert(stack.size() >= 2);
      Index selectIndex = stack.size() - 1;
      assert(selectIndex >= 1);

      if (modified.contains(select)) {
        // This select was modified; go to the next one.
        continue;
      }

      // Go up through the parents, until we can't do any more work. At each
      // parent we'll try to execute it and all intermediate parents into the
      // select arms.
      for (Index parentIndex = selectIndex - 1; parentIndex != Index(-1);
           parentIndex--) {
        auto* parent = stack[parentIndex];
        if (modified.contains(parent)) {
          // This parent was modified; exit the loop on parents as no upper
          // parent is valid to try either.
          break;
        }

        // If the parent lacks a concrete type then we can't move it into the
        // select: the select needs a concrete (and non-tuple) type. For example
        // if the parent is a drop or is unreachable, those are things we don't
        // want to handle, and we stop here (once we see one such parent we
        // can't expect to make any more progress).
        if (!parent->type.isConcrete() || parent->type.isTuple()) {
          break;
        }

        // We are precomputing the select arms, but leaving the condition as-is.
        // If the condition breaks to the parent, then we can't move the parent
        // into the select arms:
        //
        //  (block $name ;; this must stay outside of the select
        //    (select
        //      (B)
        //      (C)
        //      (block ;; condition
        //        (br_if $target
        //
        // Ignore all control flow for simplicity, as they aren't interesting
        // for us, and other passes should have removed them anyhow.
        if (Properties::isControlFlowStructure(parent)) {
          break;
        }

        // This looks promising, so try to precompute here. What we do is
        // precompute twice, once with the select replaced with the left arm,
        // and once with the right. If both succeed then we can create a new
        // select (with the same condition as before) whose arms are the
        // precomputed values.
        auto isValidPrecomputation = [&](const Flow& flow) {
          // For now we handle simple concrete values. We could also handle
          // breaks in principle TODO
          return canEmitConstantFor(flow.values) && !flow.breaking() &&
                 flow.values.isConcrete();
        };

        // Find the pointer to the select in its immediate parent so that we can
        // replace it first with one arm and then the other.
        auto** pointerToSelect =
          getChildPointerInImmediateParent(stack, selectIndex, func);
        *pointerToSelect = select->ifTrue;
        // When we perform these speculative precomputations, we must not use
        // the normal heapValues, as we are testing modified versions of
        // |parent|. Results here must not be cached for later.
        HeapValues temp;
        auto ifTrue = precomputeExpression(parent, true, &temp);
        temp.map.clear();
        if (isValidPrecomputation(ifTrue)) {
          *pointerToSelect = select->ifFalse;
          auto ifFalse = precomputeExpression(parent, true, &temp);
          if (isValidPrecomputation(ifFalse)) {
            // Wonderful, we can precompute here! The select can now contain the
            // computed values in its arms.
            select->ifTrue = ifTrue.getConstExpression(*getModule());
            select->ifFalse = ifFalse.getConstExpression(*getModule());
            select->finalize();

            // The parent of the select is now replaced by the select.
            auto** pointerToParent =
              getChildPointerInImmediateParent(stack, parentIndex, func);
            *pointerToParent = select;

            // Update state for further iterations: Mark everything modified and
            // move the select to the parent's location.
            for (Index i = parentIndex; i <= selectIndex; i++) {
              modified.insert(stack[i]);
            }
            selectIndex = parentIndex;
            stack[selectIndex] = select;
            stack.resize(selectIndex + 1);
          }
        }

        // Whether we succeeded to precompute here or not, restore the parent's
        // pointer to its original state (if we precomputed, the parent is no
        // longer in use, but there is no harm in modifying it).
        *pointerToSelect = select;
      }
    }
  }

  void visitFunction(Function* curr) {
    // removing breaks can alter types
    ReFinalize().walkFunctionInModule(curr, getModule());
  }

private:
  // Precompute an expression, returning a flow, which may be a constant
  // (that we can replace the expression with if replaceExpression is set). When
  // |usedHeapValues| is provided, we use those values instead of the normal
  // |heapValues| (that is, we do not use the normal heap value cache).
  Flow precomputeExpression(Expression* curr,
                            bool replaceExpression = true,
                            HeapValues* usedHeapValues = nullptr) {
    if (!usedHeapValues) {
      usedHeapValues = &heapValues;
    }
    Flow flow;
    try {
      flow = PrecomputingExpressionRunner(
               getModule(), getValues, *usedHeapValues, replaceExpression)
               .visit(curr);
    } catch (NonconstantException&) {
      return Flow(NONCONSTANT_FLOW);
    }
    // If we are replacing the expression, then the resulting value must be of
    // a type we can emit a constant for.
    if (!flow.breaking() && replaceExpression &&
        !canEmitConstantFor(flow.values)) {
      return Flow(NONCONSTANT_FLOW);
    }
    return flow;
  }

  // Precomputes the value of an expression, as opposed to the expression
  // itself. This differs from precomputeExpression in that we care about
  // the value the expression will have, which we cannot necessary replace
  // the expression with. For example,
  //  (local.tee (i32.const 1))
  // will have value 1 which we can optimize here, but in precomputeExpression
  // we could not do anything.
  Literals precomputeValue(Expression* curr) {
    // Note that we set replaceExpression to false, as we just care about
    // the value here.
    Flow flow = precomputeExpression(curr, false /* replaceExpression */);
    if (flow.breaking()) {
      return {};
    }
    return flow.values;
  }

  // Propagates values around. Returns whether we propagated.
  bool propagateLocals(Function* func) {
    bool propagated = false;

    // Using the graph of get-set interactions, do a constant-propagation type
    // operation: note which sets are assigned locals, then see if that lets us
    // compute other sets as locals (since some of the gets they read may be
    // constant). We do this lazily as most locals do not end up with constant
    // values that we can propagate.
    LazyLocalGraph localGraph(func, getModule());

    // A map of sets to their constant values. If a set does not appear here
    // then it is not constant, like |getValues|.
    std::unordered_map<LocalSet*, Literals> setValues;

    // The work list, which will contain sets and gets that have just been
    // found to have a constant value. As we only add them to the list when they
    // are found to be constant, each can only be added once, and a simple
    // vector is enough here (which we can make a small vector to avoid any
    // allocation in small-enough functions).
    SmallVector<Expression*, 10> work;

    // Given a set, see if it has a constant value. If so, note that on
    // setValues and add to the work list.
    auto checkConstantSet = [&](LocalSet* set) {
      if (setValues.contains(set)) {
        // Already known to be constant.
        return;
      }

      // Precompute the value. Note that this executes the code from scratch
      // each time we reach this point, and so we need to be careful about
      // repeating side effects if those side effects are expressed *in the
      // value*. A case where that can happen is GC data (each struct.new
      // creates a new, unique struct, even if the data is equal), and so
      // PrecomputingExpressionRunner has special logic to make sure that
      // reference identity is preserved properly.
      //
      // (Other side effects are fine; if an expression does a call and we
      // somehow know the entire expression precomputes to a 42, then we can
      // propagate that 42 along to the users, regardless of whatever the call
      // did globally.)
      auto values = precomputeValue(
        Properties::getFallthrough(set->value, getPassOptions(), *getModule()));

      // We precomputed the *fallthrough* value (which allows us to look through
      // some things that would otherwise block us). But in some cases, like a
      // ref.cast, the fallthrough value can have an incompatible type for the
      // entire expression, which would be invalid for us to propagate, e.g.:
      //
      //  (ref.cast (ref struct)
      //    (ref.null any)
      //  )
      //
      // In such a case the value cannot actually fall through. Ignore such
      // cases (which other optimizations can handle) by making sure that we
      // only propagate a valid subtype.
      if (values.isConcrete() &&
          Type::isSubType(values.getType(), set->value->type)) {
        setValues[set] = values;
        work.push_back(set);
      }
    };

    // The same, for a get.
    auto checkConstantGet = [&](LocalGet* get) {
      if (getValues.contains(get)) {
        // Already known to be constant.
        return;
      }

      // For this get to have constant value, all sets must agree on a constant.
      Literals values;
      bool first = true;
      for (auto* set : localGraph.getSets(get)) {
        Literals curr;
        if (set == nullptr) {
          if (getFunction()->isVar(get->index)) {
            auto localType = getFunction()->getLocalType(get->index);
            if (!localType.isDefaultable()) {
              // This is a nondefaultable local that seems to read the default
              // value at the function entry. This is either an internal error
              // or a case of unreachable code; the latter is possible as
              // LocalGraph is not precise in unreachable code. Give up.
              return;
            } else {
              curr = Literal::makeZeros(localType);
            }
          } else {
            // It's a param, so the value is non-constant. Give up.
            return;
          }
        } else {
          // If there is an entry for the set, use that constant. Otherwise, the
          // set is not constant, and we give up.
          auto iter = setValues.find(set);
          if (iter == setValues.end()) {
            return;
          }
          curr = iter->second;
        }

        // We found a concrete value, so there is a chance, if it matches all
        // the rest.
        assert(curr.isConcrete());
        if (first) {
          // This is the first ever value we see. All later ones must match it.
          values = curr;
          first = false;
        } else if (values != curr) {
          // This later value is not the same as before, give up.
          return;
        }
      }

      if (values.isConcrete()) {
        // We found a constant value!
        getValues[get] = values;
        work.push_back(get);
        propagated = true;
      } else {
        // If it is not concrete then, since we early-exited before on any
        // possible problem, there must be no sets for this get, which means it
        // is in unreachable code. In that case, we never switched |first| from
        // true to false.
        assert(first == true);
        // We could optimize using unreachability here, but we leave that for
        // other passes.
      }
    };

    // Check all gets and sets to find which are constant, mark them as such,
    // and add propagation work based on that.
    for (auto& [curr, _] : localGraph.getLocations()) {
      if (auto* set = curr->dynCast<LocalSet>()) {
        checkConstantSet(set);
      } else {
        checkConstantGet(curr->cast<LocalGet>());
      }
    }

    // Propagate constant values while work remains.
    while (!work.empty()) {
      auto* curr = work.back();
      work.pop_back();

      // This get or set is a constant value. Check if the things it influences
      // become constant.
      if (auto* set = curr->dynCast<LocalSet>()) {
        for (auto* get : localGraph.getSetInfluences(set)) {
          checkConstantGet(get);
        }
      } else {
        auto* get = curr->cast<LocalGet>();
        for (auto* set : localGraph.getGetInfluences(get)) {
          checkConstantSet(set);
        }
      }
    }

    return propagated;
  }

  bool canEmitConstantFor(const Literals& values) {
    for (auto& value : values) {
      if (!canEmitConstantFor(value)) {
        return false;
      }
    }
    return true;
  }

  bool canEmitConstantFor(const Literal& value) {
    // A null is fine to emit a constant for - we'll emit a RefNull. Otherwise,
    // see below about references to GC data.
    if (value.isNull()) {
      return true;
    }

    auto type = value.type;
    // A function is fine to emit a constant for - we'll emit a RefFunc, which
    // is compact and immutable, so there can't be a problem.
    if (type.isFunction()) {
      return true;
    }
    // We can emit a StringConst for a string constant if the string is a
    // UTF-16 string.
    if (type.isString()) {
      return isValidUTF16Literal(value);
    }
    // All other reference types cannot be precomputed. Even an immutable GC
    // reference is not currently something this pass can handle, as it will
    // evaluate and reevaluate code multiple times in e.g. propagateLocals, see
    // the comment above.
    if (type.isRef()) {
      return false;
    }

    return true;
  }

  // TODO: move this logic to src/support/string, and refactor to share code
  // with wasm/literal.cpp string printing's conversion from a Literal to a raw
  // string.
  bool isValidUTF16Literal(const Literal& value) {
    bool expectLowSurrogate = false;
    for (auto& v : value.getGCData()->values) {
      auto c = v.getInteger();
      if (c >= 0xDC00 && c <= 0xDFFF) {
        if (expectLowSurrogate) {
          expectLowSurrogate = false;
          continue;
        }
        // We got a low surrogate but weren't expecting one.
        return false;
      }
      if (expectLowSurrogate) {
        // We are expecting a low surrogate but didn't get one.
        return false;
      }
      if (c >= 0xD800 && c <= 0xDBFF) {
        expectLowSurrogate = true;
      }
    }
    return !expectLowSurrogate;
  }

  // Helpers for partial precomputing.

  // Given a stack of expressions and the index of an expression in it, find
  // the pointer to that expression in the parent. This gives us a pointer that
  // allows us to replace the expression.
  Expression** getChildPointerInImmediateParent(const ExpressionStack& stack,
                                                Index index,
                                                Function* func) {
    if (index == 0) {
      // There is nothing above this expression, so the pointer referring to it
      // is the function's body.
      return &func->body;
    }

    auto* child = stack[index];
    auto childIterator = ChildIterator(stack[index - 1]);
    for (auto** currChild : childIterator.children) {
      if (*currChild == child) {
        return currChild;
      }
    }

    WASM_UNREACHABLE("child not found in parent");
  }
};

Pass* createPrecomputePass() { return new Precompute(false); }

Pass* createPrecomputePropagatePass() { return new Precompute(true); }

} // namespace wasm
