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

//
// Hoists repeated constants to a local. A local.get takes 2 bytes
// in most cases, and if a const is larger than that, it may be
// better to store it to a local, then get it from that local.
//
// WARNING: this often shrinks code size, but can *increase* gzip
//          size. apparently having the constants in their proper
//          places lets them be compressed better, across
//          functions, etc. TODO investigate
// TODO: hoisting a zero does not even require an initial set!
// TODO: hoisting a float or double zero is especially beneficial as there
//       is no LEB compression for them, and no need for the set, so
//       each f32.const is 5 bytes and f64.const is 9 bytes, while it is
//       <= 1 byte to declare the local and 2-3 to use it!
//

#include "pass.h"
#include "support/insert_ordered.h"
#include "wasm-binary.h"
#include "wasm-builder.h"
#include "wasm.h"

namespace wasm {

// with fewer uses than this, it is never beneficial to hoist
static const Index MIN_USES = 2;

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

  Pass* create() override { return new ConstHoisting; }

  InsertOrderedMap<Literal, std::vector<Expression**>> uses;

  void visitConst(Const* curr) {
    uses[curr->value].push_back(getCurrentPointer());
  }

  void visitFunction(Function* curr) {
    std::vector<Expression*> prelude;
    for (auto& [value, vec] : uses) {
      auto num = vec.size();
      if (worthHoisting(value, num)) {
        prelude.push_back(hoist(vec));
      }
    }
    if (!prelude.empty()) {
      Builder builder(*getModule());
      // merge-blocks can optimize this into a single block later in most cases
      curr->body = builder.makeSequence(builder.makeBlock(prelude), curr->body);
    }
  }

private:
  bool worthHoisting(Literal value, Index num) {
    if (num < MIN_USES) {
      return false;
    }
    // measure the size of the constant
    Index size = 0;
    TODO_SINGLE_COMPOUND(value.type);
    switch (value.type.getBasic()) {
      case Type::i32: {
        size = getWrittenSize(S32LEB(value.geti32()));
        break;
      }
      case Type::i64: {
        size = getWrittenSize(S64LEB(value.geti64()));
        break;
      }
      case Type::f32:
      case Type::f64: {
        size = value.type.getByteSize();
        break;
      }
      // not implemented yet
      case Type::v128:
        return false;
      case Type::none:
      case Type::unreachable:
        WASM_UNREACHABLE("unexpected type");
    }
    // compute the benefit, of replacing the uses with
    // one use + a set and then a get for each use
    // doing the algebra, the criterion here is when
    //   size > 2(1+num)/(num-1)
    // or
    //   num > (size+2)/(size-2)
    auto before = num * size;
    auto after = size + 2 /* local.set */ + (2 /* local.get */ * num);
    return after < before;
  }

  template<typename T> Index getWrittenSize(const T& thing) {
    BufferWithRandomAccess buffer;
    buffer << thing;
    return buffer.size();
  }

  // replace all the uses with gets, for a local set at the top. returns
  // the set.
  Expression* hoist(std::vector<Expression**>& vec) {
    auto type = (*(vec[0]))->type;
    Builder builder(*getModule());
    auto temp = builder.addVar(getFunction(), type);
    auto* ret = builder.makeLocalSet(temp, *(vec[0]));
    for (auto item : vec) {
      *item = builder.makeLocalGet(temp, type);
    }
    return ret;
  }
};

Pass* createConstHoistingPass() { return new ConstHoisting(); }

} // namespace wasm
