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

//
// Removes duplicate functions. That can happen due to C++ templates,
// and also due to types being different at the source level, but
// identical when finally lowered into concrete wasm code.
//

#include "ir/function-utils.h"
#include "ir/hashed.h"
#include "ir/module-utils.h"
#include "ir/utils.h"
#include "opt-utils.h"
#include "pass.h"
#include "wasm.h"

namespace wasm {

struct DuplicateFunctionElimination : public Pass {
  // FIXME Merge DWARF info
  bool invalidatesDWARF() override { return true; }

  void run(PassRunner* runner, Module* module) override {
    // Multiple iterations may be necessary: A and B may be identical only after
    // we see the functions C1 and C2 that they call are in fact identical.
    // Rarely, such "chains" can be very long, so we limit how many we do.
    auto& options = runner->options;
    Index limit;
    if (options.optimizeLevel >= 3 || options.shrinkLevel >= 1) {
      limit = module->functions.size(); // no limit
    } else if (options.optimizeLevel >= 2) {
      // 10 passes usually does most of the work, as this is typically
      // logarithmic
      limit = 10;
    } else {
      limit = 1;
    }
    while (limit > 0) {
      limit--;
      // Hash all the functions
      auto hashes = FunctionHasher::createMap(module);
      FunctionHasher(&hashes).run(runner, module);
      // Find hash-equal groups
      std::map<uint32_t, std::vector<Function*>> hashGroups;
      ModuleUtils::iterDefinedFunctions(*module, [&](Function* func) {
        hashGroups[hashes[func]].push_back(func);
      });
      // Find actually equal functions and prepare to replace them
      std::map<Name, Name> replacements;
      std::set<Name> duplicates;
      for (auto& [_, group] : hashGroups) {
        Index size = group.size();
        if (size == 1) {
          continue;
        }
        // The groups should be fairly small, and even if a group is large we
        // should have almost all of them identical, so we should not hit actual
        // O(N^2) here unless the hash is quite poor.
        for (Index i = 0; i < size - 1; i++) {
          auto* first = group[i];
          if (duplicates.count(first->name)) {
            continue;
          }
          for (Index j = i + 1; j < size; j++) {
            auto* second = group[j];
            if (duplicates.count(second->name)) {
              continue;
            }
            if (FunctionUtils::equal(first, second)) {
              // great, we can replace the second with the first!
              replacements[second->name] = first->name;
              duplicates.insert(second->name);
            }
          }
        }
      }
      // perform replacements
      if (replacements.size() > 0) {
        // remove the duplicates
        module->removeFunctions(
          [&](Function* func) { return duplicates.count(func->name) > 0; });
        OptUtils::replaceFunctions(runner, *module, replacements);
      } else {
        break;
      }
    }
  }
};

Pass* createDuplicateFunctionEliminationPass() {
  return new DuplicateFunctionElimination();
}

} // namespace wasm
