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

//
// Use mathematical constraint solving to optimize. For example:
//
//  if (x == 10) {
//    assert(x != 0); // redundant and can be removed.
//  }
//
// For loops, we must avoid the following problem:
//
//  x = 0
//  do {
//    print(x >= 0 & x < 100)
//    x++
//  } while (x < 100)
//
// Say that we flow information around precisely. Then initially x is 0 at the
// top of the loop, and x++ turns it into 1. 1 < 100 so we return to the top of
// the loop, and now x can be 0 or 1. We will then interpret this loop for 100
// iterations at compile time, going from [0] to [0, 1] to [0, 2] and so forth,
// which is obviously not a good idea.
//
// Instead, we do something similar to "widening" in abstract interpretation
// (which at a loop header, where a merge occurs, widens the range of values
// based on the bounds check that it sees elsewhere). We do something even
// simpler here, which can be accomplished in an eager way as follows:
//
//   * x++ turns x from 0 to 1 in the example above, in the first iteration of
//     the loop.
//   * When we then see x == 1 that branches with x < 100, we turn that into
//     x >= 1 && x < 100. This is "imprecise", because perhaps the local will
//     not actually get incremented all the way to 100, but it is an upper
//     bound that ends up getting us to the result we want in common loop
//     shapes. (And it is safe to do because we allow more values for x, meaning
//     we can prove fewer things, so we won't prove anything false.)
//   * After doing that, we return to the top of the loop, where now we can see
//     x >= 0 && x < 100. After running that through the loop a second time, no
//     more happen: we successfully "jumped ahead" to the end state of the
//     loop variable.
//
// Doing this eagerly when we see a branch, rather than identifying specific
// loop headers and analyzing their bounds more precisely, is good enough for
// us: the only imprecision we add is "x == C, branch with x < D  =>  x >= C &&
// x < D". While imprecise, if we see "x == C, branch with x < D", then this is
// a situation inside a loop: if it were not, then x would get constant-
// propagatated to the branch anyhow by other passes. And, if this is in a loop,
// then this widening is exactly what we want. This eager approach avoids us
// needing to analyze loops shapes specifically and/or to consider branch
// conditions "from afar" (seeing a branch on "x < D", but *not* applying it
// eagerly, and instead using it later at the loop header or in some whole-
// function analysis).
//

#include <algorithm>

#include "cfg/cfg-traversal.h"
#include "cfg/rpo.h"
#include "ir/constraint.h"
#include "ir/drop.h"
#include "ir/eh-utils.h"
#include "ir/literal-utils.h"
#include "ir/local-graph.h"
#include "ir/properties.h"
#include "ir/utils.h"
#include "pass.h"
#include "support/unique_deferring_queue.h"
#include "support/utilities.h"
#include "wasm-builder.h"
#include "wasm.h"

#define CONSTRAINT_DEBUG 0

#ifndef CONSTRAINT_DEBUG
#define CONSTRAINT_DEBUG 0
#endif

namespace wasm {

using namespace wasm::constraint;

namespace {

// Information in a basic block.
struct Info {
  // For RPOQueue
  bool inQueue;
  Index index;

  // All relevant operations: local gets and sets and uses of them.
  std::vector<Expression**> actions;

  // The branching instruction at the end of the block (or nullptr if there is
  // something like a return or an unreachable, which are terminators that don't
  // interest us in this pass - we just look at ifs and brs).
  Expression* brancher = nullptr;

  // For each local index, we track the constraints we know about it. We only do
  // so at the start of each block, which is enough for the analysis below.
  BasicBlockConstraintMap startConstraints;

  void dump(Function* func) {
    std::cout << "Info{" << actions.size();
    if (brancher) {
      std::cout << ", " << *brancher;
    }
    std::cout << ", " << startConstraints << "}\n";
  }
};

struct ConstraintAnalysis
  : public WalkerPass<
      CFGWalker<ConstraintAnalysis, Visitor<ConstraintAnalysis>, Info>> {
  bool isFunctionParallel() override { return true; }

  // Locals are not modified here.
  bool requiresNonNullableLocalFixups() override { return false; }

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

  using Super = WalkerPass<
    CFGWalker<ConstraintAnalysis, Visitor<ConstraintAnalysis>, Info>>;

  // Branches outside of the function can be ignored, as we only look at local
  // state in the function.
  bool ignoreBranchesOutsideOfFunc = true;

  // A relevant local is one that we care about optimizing.
  std::vector<bool> relevantLocals;

  bool fastMath;

  bool isRelevantType(Type type) {
    if (type == Type::v128) {
      // TODO optimize SIMD where it makes sense, but for now we don't want to
      // do things like propagate v128 constants, which are large.
      return false;
    }

    // Floating-point math does not follow the basic rules of logic (for
    // example, NaN < NaN and NaN >= NaN are both false, despite the law of the
    // excluded middle). Constraints follow the rules of logic, so we cannot
    // operate on floats unless we have fast-math enabled (which assures us we
    // can ignore NaNs).
    // TODO: when values are constant and non-NaN, we could optimize even
    //       without fast-math
    return !type.isFloat() || fastMath;
  }

  void doWalkFunction(Function* func) {
    fastMath = getPassOptions().fastMath;

    // Mark the relevant locals.
    relevantLocals.assign(func->getNumLocals(), false);
    for (Index i = 0; i < func->getNumLocals(); ++i) {
      relevantLocals[i] = isRelevantType(func->getLocalType(i));
    }

    Super::doWalkFunction(func);
  }

  // Store the actions we care about.
  void addAction() {
    if (currBasicBlock) {
      auto* currp = getCurrentPointer();
      currBasicBlock->contents.actions.push_back(currp);
    }
  }

  void visitLocalGet(LocalGet* curr) {
    if (isRelevantType(curr->type)) {
      addAction();
    }
  }

  void visitLocalSet(LocalSet* curr) {
    if (isRelevantType(getFunction()->getLocalType(curr->index))) {
      addAction();
    }
  }

  void visitUnary(Unary* curr) { addAction(); }
  void visitBinary(Binary* curr) { addAction(); }
  void visitRefEq(RefEq* curr) { addAction(); }
  void visitRefIsNull(RefIsNull* curr) { addAction(); }

  static void doStartIfTrue(ConstraintAnalysis* self, Expression** currp) {
    // We are right after the condition, so we are in the block before the If's
    // branching. Mark the If as the brancher (unless in unreachable code).
    if (self->currBasicBlock) {
      self->currBasicBlock->contents.brancher = *currp;
    }
    Super::doStartIfTrue(self, currp);
  }

  static void doEndBranch(ConstraintAnalysis* self, Expression** currp) {
    if (self->currBasicBlock) {
      self->currBasicBlock->contents.brancher = *currp;
    }
    Super::doEndBranch(self, currp);
  }

  void visitFunction(Function* curr) {
    if (!entry) {
      // Body is unreachable, no entry block.
      return;
    }

    flow();
    optimize();
  }

  // Flow infos around until we have inferred all we can about the constraints
  // in each location.
  void flow() {
#if CONSTRAINT_DEBUG
    dumpCFG("flow");
#endif

    // Start from the entry as the only reachable block. That block has incoming
    // values - defaults - for each var.
    entry->contents.startConstraints.setReachable();
    auto& entryConstraints = entry->contents.startConstraints;
    auto* func = getFunction();
    for (Index i = func->getVarIndexBase(); i < func->getNumLocals(); i++) {
      if (!relevantLocals[i]) {
        // No point to apply a constraint to an irrelevant local.
        continue;
      }
      auto type = func->getLocalType(i);
      // TODO: support tuples
      if (type.size() == 1 && LiteralUtils::canMakeZero(type)) {
        // We have a default value, so we can prove something.
        auto value = Literal::makeZero(type);
        entryConstraints.set(i, Constraint{Abstract::Eq, {value}});
      }
      // Note that we need no special handling for non-nullable locals. They
      // cannot be used before being set, so it doesn't matter what we have in
      // the map for them. We leave them as proving nothing (as if they were
      // parameters in effect) as that is more efficient in the way the
      // information is encoded (see constraint.h).
    }

    // Starting from the entry, keep going while we find something new.
    RPOQueue<ConstraintAnalysis> work(*this);
    work.push(entry);

    while (!work.empty()) {
      auto* block = work.pop();

      // Start at the top of the block, then go through, applying things.
      BasicBlockConstraintMap constraints = block->contents.startConstraints;

#if CONSTRAINT_DEBUG
      std::cout << block << " start constraints: " << constraints << '\n';
#endif

      for (auto** currp : block->contents.actions) {
        if (constraints.unreachable) {
          break;
        }
        applyToConstraints(*currp, constraints);
      }

      if (constraints.unreachable) {
        // Nothing to send.
        continue;
      }

#if CONSTRAINT_DEBUG
      std::cout << block << " end   constraints: " << constraints << '\n';
#endif

      // We now know the values at the end of the block. Flow it onward, and
      // where it causes changes, queue more work.
      for (auto* out : block->out) {
        auto& outStartConstraints = out->contents.startConstraints;

        // Find the constraints sent to this specific successor, if there is a
        // branch, and use them.
        if (auto branch = getBranchConstraints(block, out);
            filterRelevant(branch), !branch.empty()) {
          auto sentConstraints = constraints;
          applyBranchConstraints(branch, sentConstraints);
#if CONSTRAINT_DEBUG
          std::cout << block << " sending branch to " << out
                    << " with sent constraints: " << sentConstraints << '\n';
#endif
          // If anything changed at the start of the target block, flow onwards.
          if (outStartConstraints.approximateOr(sentConstraints)) {
#if CONSTRAINT_DEBUG
            std::cout << "out's start after  " << outStartConstraints << '\n';
            std::cout << block << " branch-modified " << out
                      << " to start with: " << outStartConstraints << '\n';
#endif
            work.push(out);
          }
        } else {
          // There are no specific branch constraints, so send the unmodified
          // |constraints|, avoiding a copy.
          if (outStartConstraints.approximateOr(constraints)) {
#if CONSTRAINT_DEBUG
            std::cout << block << " modified " << out
                      << " to start with: " << outStartConstraints << '\n';
#endif
            work.push(out);
          }
        }
      }
    }
  }

  // If we change types, we must refinalize.
  bool refinalize = false;

  // After inferring all we can, apply it to optimize the code.
  void optimize() {

    // If we find local.gets that we can optimize, we queue those changes here.
    // This order is useful for the following reason:
    //
    //   (i32.eqz
    //     (local.get $x)
    //   )
    //
    // If we can infer that x is 42, and we do that first, then we end up with
    // eqz of 42. That is something Precompute can handle, but not us - this
    // pass only looks at constraints on locals. We do not lose any optimization
    // power by leaving this to Precompute, but it is less efficient and may
    // require more cycles; it is also less convenient for testing, as we must
    // avoid inferrable local.gets in order to fully test constraint
    // optimization.
    //
    // Instead, we queue local.get changes to happen later, after the eqz in the
    // example above. That is, the eqz gets a chance to get optimized, and if it
    // does, the queued local.get change ends up unnoticable (it changes a thing
    // not in the IR; a slight waste of work, but less wasteful than waiting for
    // Precompute).
    //
    // This queue of changes contains tuples of currp (the pointer to the
    // local.get) and the value to replace it with.
    std::vector<std::pair<Expression**, Expression*>> getOptimizations;

    for (auto& block : basicBlocks) {
      // Follow the general shape of flow(): we need to see what the state is
      // at each intermediate point inside the block. (Flowing between blocks is
      // of course not needed at this stage.)
      auto& constraints = block->contents.startConstraints;
      for (auto** currp : block->contents.actions) {
#if CONSTRAINT_DEBUG
        std::cout << block << " trying to optimize " << **currp << '\n';
#endif
        if (!constraints.unreachable) {
          applyToConstraints(*currp, constraints);
          if (auto* rep = optimizeLocalGet(currp, constraints)) {
            getOptimizations.emplace_back(currp, rep);
          } else {
            optimizeConstraint(currp, constraints);
          }
        } else {
          // This is unreachable code: just mark it so.
          *currp = getDroppedChildrenAndAppend(
            *currp,
            *getModule(),
            getPassOptions(),
            Builder(*getModule()).makeUnreachable());
          refinalize = true;
        }
      }
    }

    // Apply local.get optimizations after all that.
    for (auto& [currp, rep] : getOptimizations) {
      *currp = rep;
    }

    if (refinalize) {
      ReFinalize().walkFunctionInModule(getFunction(), getModule());
      EHUtils::handleBlockNestedPops(getFunction(), *getModule());
    }
  }

  // Given an expression and the constraints on it, see if it is a local.get
  // that we can optimize, and return the value to optimize to, if so.
  Expression* optimizeLocalGet(Expression** currp,
                               const BasicBlockConstraintMap& constraints) {
    // A bare local.get can be optimized, if we know that local is a constant.
    if (auto* get = (*currp)->dynCast<LocalGet>()) {
      if (auto lit = constraints.get(get->index).getLiteral()) {
        // Among references, only propagate nulls. Other things, like strings,
        // may increase size, so we leave them for passes like Precompute and
        // GUFA.
        if (lit->type.isRef() && !lit->isNull()) {
          return nullptr;
        }

        Builder builder(*getModule());
        auto* rep = builder.makeConstantExpression(*lit);

        // See if the type changes.
        auto oldType = get->type;
        if (!Type::isSubType(rep->type, oldType)) {
          // The value we know must exist here is impossible, which means it was
          // cast in a way that traps at runtime. This code is unreachable.
          rep = builder.makeUnreachable();
          refinalize = true;
        } else if (rep->type != oldType) {
          // We are refining.
          refinalize = true;
        }

        return rep;
      }
    }

    return nullptr;
  }

  // Given an expression and the constraints on it, parse it into a constraint
  // if we can, and optimize it.
  void optimizeConstraint(Expression** currp,
                          const BasicBlockConstraintMap& constraints) {
    auto* curr = *currp;

    // Note that we don't need to try to parse a series of constraints with
    // ParsedAndedConstraints: if there is a tree of ANDed things, we will
    // simply optimize it as we walk it, each time handling one.
    auto parsed = LocalConstraint::parse(curr);
    if (!parsed) {
      return;
    }
    if (!relevantLocals[parsed->local]) {
      return;
    }

    auto result = constraints.proves(*parsed);
    if (result == Unknown) {
      // If we parsed something using two locals, like x != y, we can also look
      // for the flipped condition among y's constraints TODO
      return;
    }

    // We know the result!
    auto& wasm = *getModule();
    auto value =
      LiteralUtils::makeFromInt32(result == True ? 1 : 0, curr->type, wasm);
    *currp = getDroppedChildrenAndAppend(
      curr, wasm, getPassOptions(), value, DropMode::IgnoreParentEffects);
  }

  // Given a predecessor and one of its successors, find new constraints that
  // can be added due to the flow to that specific successor.
  ParsedAndedConstraints getBranchConstraints(BasicBlock* pred,
                                              BasicBlock* succ) {
    auto* brancher = pred->contents.brancher;
    if (!brancher) {
      return {};
    }
    // We handle the case of two successors for now. When there are less, other
    // opts can handle things. TODO: Switch is the case of more than 2.
    if (pred->out.size() != 2) {
      return {};
    }

    // CFGWalker builds the IR by putting the physical successor as the first
    // successor (that is, the first is the one we reach without branching).
    // We pass that along to the specific branch type handlers, so they can
    // figure out if we are in the true or false path.
    assert(succ == pred->out[0] || succ == pred->out[1]);
    auto physicalSuccessor = (succ == pred->out[0]);

    if (auto* iff = brancher->dynCast<If>()) {
      return getConstraintsFromIf(iff, physicalSuccessor);
    } else if (auto* br = brancher->dynCast<Break>()) {
      return getConstraintsFromBreak(br, physicalSuccessor);
    } else if (auto* br = brancher->dynCast<BrOn>()) {
      return getConstraintsFromBrOn(br, physicalSuccessor);
    }
    // TODO: Switch
    return {};
  }

  ParsedAndedConstraints getConstraintsFromIf(If* iff, bool physicalSuccessor) {
    auto parsed = ParsedAndedConstraints::parseCondition(iff->condition);
    if (!physicalSuccessor) {
      // We are in the ifFalse, so negate the condition.
      parsed.negate();
    }
    return parsed;
  }

  ParsedAndedConstraints getConstraintsFromBreak(Break* br,
                                                 bool physicalSuccessor) {
    // We get here when there is more than one successor, so there must be a
    // condition.
    assert(br->condition);

    auto parsed = ParsedAndedConstraints::parseCondition(br->condition);
    if (physicalSuccessor) {
      // The branch was not taken, so negate the condition.
      parsed.negate();
    }
    return parsed;
  }

  ParsedAndedConstraints getConstraintsFromBrOn(BrOn* brOn,
                                                bool physicalSuccessor) {
    // The constraint on that local depends on the op.
    // TODO: Handle BrOnCast* etc using subtyping operations.
    if (brOn->op != BrOnNull && brOn->op != BrOnNonNull) {
      return {};
    }

    // parseCondition can parse more things than a local.get, which is all we
    // handle here, but there is no other valid IR that can appear there, so we
    // can reuse it.
    auto parsed = ParsedAndedConstraints::parseCondition(brOn->ref);
    // Negate depending on the op and (similar to Break) the successor.
    if ((brOn->op == BrOnNull) ^ physicalSuccessor) {
      parsed.negate();
    }
    return parsed;
  }

  // When applying constraints for a binary operation like x = y + 1, we may
  // end up with lots of nonlinear work, in a loop: x may go from 0 to 1, then
  // branch back to the top and merge, making it in the range [0, 1], then get
  // incremented and loop again, leading to [0, 2] and so forth, only stopping
  // when it reaches the loop bound, which may be very high. We don't want to
  // spend significant time on such constant operations, as other passes will
  // propagate them anyhow, so we stop before applying such x = y + 1
  // operations a ridiculous number of times, by widening to a worst case.
  static const Index MaxBinaryActions = 20;

  // How many times we processed each Binary action.
  std::unordered_map<Binary*, Index> binaryActionCounts;

  // Given an expression, apply it to the constraints. For example, a local.set
  // sets the value for that local.
  void applyToConstraints(Expression* curr,
                          BasicBlockConstraintMap& constraints) {
    if (auto* set = curr->dynCast<LocalSet>()) {
      if (!relevantLocals[set->index]) {
        // No point to apply a constraint to an irrelevant local.
        return;
      }

      // Look at the fallthrough. It is valid to do so, because our constraints
      // only track two things, constants and locals. For a constant, it does
      // not change while falling through. For a local, the only way for the
      // local to change while falling through is to go through a tee of that
      // local - but that would keep the same value there anyhow. That is:
      //
      //  (local.set $other
      //    (block
      //      ..
      //      (local.tee $source
      //        (block
      //          ..
      //          (local.get $source)
      //        )
      //      )
      //    )
      //  )
      //
      // The fallthrough here is the local.get of $source. We can set $other to
      // the value in $source, because while $source did have a write while
      // falling through, it did not alter the value, and there is no
      // opportunity to write any other value while falling through. (And, any
      // local.tee appearing here would have been reached earlier in the
      // traversal, and handled.)
      auto* value = set->value;
      while (1) {
        if (value->is<LocalSet>()) {
          // We stop at the first tee: we don't need to look any further, and
          // will just apply that local's values to ourselves, saving repeated
          // work.
          break;
        }
        auto* next = Properties::getImmediateFallthrough(
          value, getPassOptions(), *getModule());
        if (value == next) {
          break;
        } else {
          value = next;
        }
      }

      // Now that we know the value, check binary action counting limits (see
      // above).
      if (auto* binary = value->dynCast<Binary>()) {
        // The code below will stop calculating this binary once we pass
        // MaxBinaryActions operations on it. That is enough to prevent
        // unbounded work on this binary, however, we may end up reaching this
        // basic block an even larger number of times for other reasons, i.e.,
        // just because of a very complex CFG. That should be very rare, but can
        // happen. In debug builds we check we do not exceed a very high limit
        // there, intending to throw an assert rather than just hang in the case
        // of a bug (as assert is easier to diagnose, even if it happens after a
        // long delay).
        auto& count = binaryActionCounts[binary];
#ifndef NDEBUG
        static const Index MaxBasicBlockActions = 1024 * 1024;
        assert(count < MaxBasicBlockActions);
#endif
        count++;
        if (count >= MaxBinaryActions) {
          constraints.setProvesNothing(set->index);
          return;
        }
      }

      constraints.set(set->index, value);
    }
  }

  // Filters out constraints on irrelevant locals.
  void filterRelevant(ParsedAndedConstraints& parsed) {
    parsed.erase(std::remove_if(parsed.begin(),
                                parsed.end(),
                                [&](const LocalConstraint& pair) {
                                  return !relevantLocals[pair.local];
                                }),
                 parsed.end());
  }

  // Apply branch constraints to the current set of constraints.
  void applyBranchConstraints(const ParsedAndedConstraints& branch,
                              BasicBlockConstraintMap& constraints) {
    for (auto& pair : branch) {
      // Extend the range of values in the "jump ahead" manner described in the
      // top-level comment.
      if (!applyBranchRangeExtensionToConstraints(pair, constraints)) {
        // Otherwise, apply the constraint normally.
        constraints.approximateAnd(pair.local, pair.constraint);
      }

      if (constraints.unreachable) {
        return;
      }
    }
  }

  bool
  applyBranchRangeExtensionToConstraints(const LocalConstraint& branch,
                                         BasicBlockConstraintMap& constraints) {
    using namespace Abstract;

    // "Jump ahead" and extend ranges. If the branch is x < M, and we were
    // x == N, then extend to x >= N && x < M (see top-level comment). Note that
    // we don't need to worry about a contradiction here: this code is only
    // reached if x == N && x < M. If it is reached, that is not a
    // contradiction, and extending x == N to x >= N is also not.
    auto M = branch.constraint.term;

    // We only handle the case of N being a constant, for two reasons:
    //
    //  * As mentioned above, if a constant reaches a conditional branch, then
    //    other passes would have propagated it into the branch check itself,
    //    if that were possible. The only case where it isn't possible is when
    //    it is a loop variable (so it looks like a constant at first, but gets
    //    written another value by the branch back to the loop top). By only
    //    handling constants here, we only extend ranges for loop variables (and
    //    extending ranges can have downsides, so it is good we do it in a
    //    targeted way).
    //  * The case of a constant for the initial value N is exactly what we want
    //    to optimize here: most typical loop patterns iterate from 0 or 1 or
    //    such.
    //
    // So things work out perfectly here: constants are safe to optimize (no
    // risk of extension causing  downsides) and are exactly what we want to
    // optimize.
    //
    // (Note that there is no limitation on *M*, the upper bound of the loop: we
    // can iterate up to a constant or to a local. I.e. loops from 0 to 100 and
    // 5 to x work, but not loops from x to 100 or x to y.)
    auto N = constraints.get(branch.local).getLiteral();
    if (!N) {
      return false;
    }

    // We can handle both x < M as the branch, as described above, or
    // x <= M (if N <= M).
    if (branch.constraint.op == Abstract::LtS ||
        branch.constraint.op == Abstract::LeS) {
      constraints.set(branch.local, branch.constraint);
      if (!constraints.unreachable) {
        constraints.approximateAnd(branch.local, {GeS, {*N}});
      }
      return true;
    }
    if (branch.constraint.op == Abstract::LtU ||
        branch.constraint.op == Abstract::LeU) {
      constraints.set(branch.local, branch.constraint);
      if (!constraints.unreachable) {
        constraints.approximateAnd(branch.local, {GeU, {*N}});
      }
      return true;
    }

    return false;
  }
};

} // anonymous namespace

Pass* createConstraintAnalysisPass() { return new ConstraintAnalysis(); }

} // namespace wasm
