#include "Utility.hpp"
#include "ValueCounter.hpp"

#include <llvm/Module.h>
#include <llvm/Support/InstIterator.h>

#include <set>

using namespace llvm;

bool ValueCounter::runOnModule(llvm::Module & M)
{
  for(Module::iterator F = M.begin(), F_E = M.end(); F != F_E; ++F)
  {
    countFunction(*F);
  }

  return false;
}

void ValueCounter::countFunction(const llvm::Function & F)
{
  value_set ssavalues;
  for(const_inst_iterator it = inst_begin(F), ed = inst_end(F);
      it != ed; ++it)
  {
    if(const User * u = dyn_cast<const User>(&*it))
    {
      insertUser(ssavalues, u);
    }
    else
    {
      value_set pvals = flattenPhiNode(&*it);
      ssavalues.insert(pvals.begin(), pvals.end());
    }
  }

  for(Function::const_arg_iterator it = F.arg_begin(), ed = F.arg_end();
      it != ed; ++it)
  {
    ssavalues.insert(&*it);
  }

  _values[&F] = ssavalues.size();
}

void ValueCounter::getAnalysisUsage(llvm::AnalysisUsage &AU) const
{
  AU.setPreservesAll();
}

void ValueCounter::insertUser(value_set & vs, const llvm::User * u)
{
  for(User::const_op_iterator it = u->op_begin(), ed = u->op_end();
      it != ed; ++it)
  {
    value_set pvals = flattenPhiNode(it->get());
    vs.insert(pvals.begin(), pvals.end());
  }
}

size_t ValueCounter::getValueCount(const Function &F) const
{
  assert(_values.find(&F) != _values.end());
  return _values.find(&F)->second;
}

char ValueCounter::ID = 0;
static RegisterPass<ValueCounter> VC("valueCounter", "Counts the number of unique values in a function");

