//===- PathProfiling.cpp - Inserts counters for path profiling ------------===//
//
//                      The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass instruments functions for Ball-Larus path profiling.  Ball-Larus
// profiling converts the CFG into a DAG by replacing backedges with edges
// from entry to the start block and from the end block to exit.  The paths
// along the new DAG are enumrated, i.e. each path is given a path number.
// Edges are instrumented to increment the path number register, such that the
// path number register will equal the path number of the path taken at the
// exit.
//
// This file defines classes for building a CFG for use with different stages
// in the Ball-Larus path profiling instrumentation [Ball96].  The
// requirements are formatting the llvm CFG into the Ball-Larus DAG, path
// numbering, finding a spanning tree, moving increments from the spanning
// tree to chords.
//
// Terms:
// DAG            - Directed Acyclic Graph.
// Ball-Larus DAG - A CFG with an entry node, an exit node, and backedges
//                  removed in the following manner.  For every backedge
//                  v->w, insert edge ENTRY->w and edge v->EXIT.
// Path Number    - The number corresponding to a specific path through a
//                  Ball-Larus DAG.
// Spanning Tree  - A subgraph, S, is a spanning tree if S covers all
//                  vertices and is a tree.
// Chord          - An edge not in the spanning tree.
//
// [Ball96]
//  T. Ball and J. R. Larus. "Efficient Path Profiling."
//  International Symposium on Microarchitecture, pages 46-57, 1996.
//  http://portal.acm.org/citation.cfm?id=243857
//
// [Ball94]
//  Thomas Ball.  "Efficiently Counting Program Events with Support for
//  On-line queries."
//  ACM Transactions on Programmmg Languages and Systems, Vol 16, No 5,
//  September 1994, Pages 1399-1410.
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "insert-path-profiling"

#include "llvm/DerivedTypes.h"
#include "ProfilingUtils.h"
#include "llvm/Analysis/PathNumbering.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/InstrTypes.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TypeBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Instrumentation.h"
#include <vector>

#define HASH_THRESHHOLD 100000

using namespace llvm;

namespace {
class BLInstrumentationNode;
class BLInstrumentationEdge;
class BLInstrumentationDag;

// ---------------------------------------------------------------------------
// BLInstrumentationNode extends BallLarusNode with member used by the
// instrumentation algortihms.
// ---------------------------------------------------------------------------
class BLInstrumentationNode : public BallLarusNode {
public:
  // Creates a new BLInstrumentationNode from a BasicBlock.
  BLInstrumentationNode(BasicBlock* BB);

  // Get/sets the Value corresponding to the pathNumber register,
  // constant or phinode.  Used by the instrumentation code to remember
  // path number Values.
  Value* getStartingPathNumber();
  void setStartingPathNumber(Value* pathNumber);

  Value* getEndingPathNumber();
  void setEndingPathNumber(Value* pathNumber);

  // Get/set the PHINode Instruction for this node.
  PHINode* getPathPHI();
  void setPathPHI(PHINode* pathPHI);

private:

  Value* _startingPathNumber; // The Value for the current pathNumber.
  Value* _endingPathNumber; // The Value for the current pathNumber.
  PHINode* _pathPHI; // The PHINode for current pathNumber.
};

// --------------------------------------------------------------------------
// BLInstrumentationEdge extends BallLarusEdge with data about the
// instrumentation that will end up on each edge.
// --------------------------------------------------------------------------
class BLInstrumentationEdge : public BallLarusEdge {
public:
  BLInstrumentationEdge(BLInstrumentationNode* source,
                        BLInstrumentationNode* target);

  // Sets the target node of this edge.  Required to split edges.
  void setTarget(BallLarusNode* node);

  // Get/set whether edge is in the spanning tree.
  bool isInSpanningTree() const;
  void setIsInSpanningTree(bool isInSpanningTree);

  // Get/ set whether this edge will be instrumented with a path number
  // initialization.
  bool isInitialization() const;
  void setIsInitialization(bool isInitialization);

  // Get/set whether this edge will be instrumented with a path counter
  // increment.  Notice this is incrementing the path counter
  // corresponding to the path number register.  The path number
  // increment is determined by getIncrement().
  bool isCounterIncrement() const;
  void setIsCounterIncrement(bool isCounterIncrement);

  // Get/set the path number increment that this edge will be instrumented
  // with.  This is distinct from the path counter increment and the
  // weight.  The counter increment counts the number of executions of
  // some path, whereas the path number keeps track of which path number
  // the program is on.
  long getIncrement() const;
  void setIncrement(long increment);

  // Get/set whether the edge has been instrumented.
  bool hasInstrumentation();
  void setHasInstrumentation(bool hasInstrumentation);

  // Returns the successor number of this edge in the source.
  unsigned getSuccessorNumber();

private:
  // The increment that the code will be instrumented with.
  long long _increment;

  // Whether this edge is in the spanning tree.
  bool _isInSpanningTree;

  // Whether this edge is an initialiation of the path number.
  bool _isInitialization;

  // Whether this edge is a path counter increment.
  bool _isCounterIncrement;

  // Whether this edge has been instrumented.
  bool _hasInstrumentation;
};

// ---------------------------------------------------------------------------
// BLInstrumentationDag extends BallLarusDag with algorithms that
// determine where instrumentation should be placed.
// ---------------------------------------------------------------------------
class BLInstrumentationDag : public BallLarusDag {
public:
  BLInstrumentationDag(Function &F);

  // Returns the Exit->Root edge. This edge is required for creating
  // directed cycles in the algorithm for moving instrumentation off of
  // the spanning tree
  BallLarusEdge* getExitRootEdge();

  // Returns an array of phony edges which mark those nodes
  // with function calls
  BLEdgeVector getCallPhonyEdges();

  // Gets/sets the path counter array
  GlobalVariable* getCounterArray();
  void setCounterArray(GlobalVariable* c);

  // Calculates the increments for the chords, thereby removing
  // instrumentation from the spanning tree edges. Implementation is based
  // on the algorithm in Figure 4 of [Ball94]
  void calculateChordIncrements();

  // Updates the state when an edge has been split
  void splitUpdate(BLInstrumentationEdge* formerEdge, BasicBlock* newBlock);

  // Calculates a spanning tree of the DAG ignoring cycles.  Whichever
  // edges are in the spanning tree will not be instrumented, but this
  // implementation does not try to minimize the instrumentation overhead
  // by trying to find hot edges.
  void calculateSpanningTree();

  // Pushes initialization further down in order to group the first
  // increment and initialization.
  void pushInitialization();

  // Pushes the path counter increments up in order to group the last path
  // number increment.
  void pushCounters();

  // Removes phony edges from the successor list of the source, and the
  // predecessor list of the target.
  void unlinkPhony();

  // Generate dot graph for the function
  void generateDotGraph();

protected:
  // BLInstrumentationDag creates BLInstrumentationNode objects in this
  // method overriding the creation of BallLarusNode objects.
  //
  // Allows subclasses to determine which type of Node is created.
  // Override this method to produce subclasses of BallLarusNode if
  // necessary.
  virtual BallLarusNode* createNode(BasicBlock* BB);

  // BLInstrumentationDag create BLInstrumentationEdges.
  //
  // Allows subclasses to determine which type of Edge is created.
  // Override this method to produce subclasses of BallLarusEdge if
  // necessary.  Parameters source and target will have been created by
  // createNode and can be cast to the subclass of BallLarusNode*
  // returned by createNode.
  virtual BallLarusEdge* createEdge(
    BallLarusNode* source, BallLarusNode* target, unsigned edgeNumber);

private:
  BLEdgeVector _treeEdges; // All edges in the spanning tree.
  BLEdgeVector _chordEdges; // All edges not in the spanning tree.
  GlobalVariable* _counterArray; // Array to store path counters

  // Removes the edge from the appropriate predecessor and successor lists.
  void unlinkEdge(BallLarusEdge* edge);

  // Makes an edge part of the spanning tree.
  void makeEdgeSpanning(BLInstrumentationEdge* edge);

  // Pushes initialization and calls itself recursively.
  void pushInitializationFromEdge(BLInstrumentationEdge* edge);

  // Pushes path counter increments up recursively.
  void pushCountersFromEdge(BLInstrumentationEdge* edge);

  // Depth first algorithm for determining the chord increments.f
  void calculateChordIncrementsDfs(
    long weight, BallLarusNode* v, BallLarusEdge* e);

  // Determines the relative direction of two edges.
  int calculateChordIncrementsDir(BallLarusEdge* e, BallLarusEdge* f);
};

// ---------------------------------------------------------------------------
// PathProfiler is a module pass which instruments path profiling instructions
// ---------------------------------------------------------------------------
class PathProfiler : public ModulePass {
private:
  // Current context for multi threading support.
  LLVMContext* Context;

  // Which function are we currently instrumenting
  unsigned currentFunctionNumber;

  // The function prototype in the profiling runtime for incrementing a
  // single path counter in a hash table.
  Constant* llvmIncrementHashFunction;
  Constant* llvmDecrementHashFunction;

  // Instruments each function with path profiling.  'main' is instrumented
  // with code to save the profile to disk.
  bool runOnModule(Module &M);

  // Analyzes the function for Ball-Larus path profiling, and inserts code.
  void runOnFunction(std::vector<Constant*> &ftInit, Function &F, Module &M);

  // Creates an increment constant representing incr.
  ConstantInt* createIncrementConstant(long incr, int bitsize);

  // Creates an increment constant representing the value in
  // edge->getIncrement().
  ConstantInt* createIncrementConstant(BLInstrumentationEdge* edge);

  // Finds the insertion point after pathNumber in block.  PathNumber may
  // be NULL.
  BasicBlock::iterator getInsertionPoint(
    BasicBlock* block, Value* pathNumber);

  // Inserts source's pathNumber Value* into target.  Target may or may not
  // have multiple predecessors, and may or may not have its phiNode
  // initalized.
  void pushValueIntoNode(
    BLInstrumentationNode* source, BLInstrumentationNode* target);

  // Inserts source's pathNumber Value* into the appropriate slot of
  // target's phiNode.
  void pushValueIntoPHI(
    BLInstrumentationNode* target, BLInstrumentationNode* source);

  // The Value* in node, oldVal,  is updated with a Value* correspodning to
  // oldVal + addition.
  void insertNumberIncrement(BLInstrumentationNode* node, Value* addition,
                             bool atBeginning);

  // Creates a counter increment in the given node.  The Value* in node is
  // taken as the index into a hash table.
  void insertCounterIncrement(
    Value* incValue,
    BasicBlock::iterator insertPoint,
    BLInstrumentationDag* dag,
    bool increment = true);

  // A PHINode is created in the node, and its values initialized to -1U.
  void preparePHI(BLInstrumentationNode* node);

  // Inserts instrumentation for the given edge
  //
  // Pre: The edge's source node has pathNumber set if edge is non zero
  // path number increment.
  //
  // Post: Edge's target node has a pathNumber set to the path number Value
  // corresponding to the value of the path register after edge's
  // execution.
  void insertInstrumentationStartingAt(
    BLInstrumentationEdge* edge,
    BLInstrumentationDag* dag);

  // If this edge is a critical edge, then inserts a node at this edge.
  // This edge becomes the first edge, and a new BallLarusEdge is created.
  bool splitCritical(BLInstrumentationEdge* edge, BLInstrumentationDag* dag);

  // Inserts instrumentation according to the marked edges in dag.  Phony
  // edges must be unlinked from the DAG, but accessible from the
  // backedges.  Dag must have initializations, path number increments, and
  // counter increments present.
  //
  // Counter storage is created here.
  void insertInstrumentation( BLInstrumentationDag& dag, Module &M);

public:
  static char ID; // Pass identification, replacement for typeid
  PathProfiler() : ModulePass(ID) {
    initializePathProfilerPass(*PassRegistry::getPassRegistry());
  }

  virtual const char *getPassName() const {
    return "Path Profiler";
  }
};
} // end anonymous namespace

// Should we print the dot-graphs
static cl::opt<bool> DotPathDag("path-profile-pathdag", cl::Hidden,
        cl::desc("Output the path profiling DAG for each function."));

// Register the path profiler as a pass
char PathProfiler::ID = 0;
INITIALIZE_PASS(PathProfiler, "insert-path-profiling",
                "Insert instrumentation for Ball-Larus path profiling",
                false, false)

ModulePass *llvm::createPathProfilerPass() { return new PathProfiler(); }

namespace llvm {
  class PathProfilingFunctionTable {};

  // Type for global array storing references to hashes or arrays
  template<bool xcompile> class TypeBuilder<PathProfilingFunctionTable,
                                            xcompile> {
  public:
    static StructType *get(LLVMContext& C) {
      return( StructType::get(
                TypeBuilder<types::i<32>, xcompile>::get(C), // type
                TypeBuilder<types::i<32>, xcompile>::get(C), // array size
                TypeBuilder<types::i<8>*, xcompile>::get(C), // array/hash ptr
                NULL));
    }
  };

  typedef TypeBuilder<PathProfilingFunctionTable, true>
  ftEntryTypeBuilder;

  // BallLarusEdge << operator overloading
  raw_ostream& operator<<(raw_ostream& os,
                          const BLInstrumentationEdge& edge)
      LLVM_ATTRIBUTE_USED;
  raw_ostream& operator<<(raw_ostream& os,
                          const BLInstrumentationEdge& edge) {
    os << "[" << edge.getSource()->getName() << " -> "
       << edge.getTarget()->getName() << "] init: "
       << (edge.isInitialization() ? "yes" : "no")
       << " incr:" << edge.getIncrement() << " cinc: "
       << (edge.isCounterIncrement() ? "yes" : "no");
    return(os);
  }
}

// Creates a new BLInstrumentationNode from a BasicBlock.
BLInstrumentationNode::BLInstrumentationNode(BasicBlock* BB) :
  BallLarusNode(BB),
  _startingPathNumber(NULL), _endingPathNumber(NULL), _pathPHI(NULL) {}

// Constructor for BLInstrumentationEdge.
BLInstrumentationEdge::BLInstrumentationEdge(BLInstrumentationNode* source,
                                             BLInstrumentationNode* target)
  : BallLarusEdge(source, target, 0),
    _increment(0), _isInSpanningTree(false), _isInitialization(false),
    _isCounterIncrement(false), _hasInstrumentation(false) {}

// Sets the target node of this edge.  Required to split edges.
void BLInstrumentationEdge::setTarget(BallLarusNode* node) {
  _target = node;
}

// Returns whether this edge is in the spanning tree.
bool BLInstrumentationEdge::isInSpanningTree() const {
  return(_isInSpanningTree);
}

// Sets whether this edge is in the spanning tree.
void BLInstrumentationEdge::setIsInSpanningTree(bool isInSpanningTree) {
  _isInSpanningTree = isInSpanningTree;
}

// Returns whether this edge will be instrumented with a path number
// initialization.
bool BLInstrumentationEdge::isInitialization() const {
  return(_isInitialization);
}

// Sets whether this edge will be instrumented with a path number
// initialization.
void BLInstrumentationEdge::setIsInitialization(bool isInitialization) {
  _isInitialization = isInitialization;
}

// Returns whether this edge will be instrumented with a path counter
// increment.  Notice this is incrementing the path counter
// corresponding to the path number register.  The path number
// increment is determined by getIncrement().
bool BLInstrumentationEdge::isCounterIncrement() const {
  return(_isCounterIncrement);
}

// Sets whether this edge will be instrumented with a path counter
// increment.
void BLInstrumentationEdge::setIsCounterIncrement(bool isCounterIncrement) {
  _isCounterIncrement = isCounterIncrement;
}

// Gets the path number increment that this edge will be instrumented
// with.  This is distinct from the path counter increment and the
// weight.  The counter increment is counts the number of executions of
// some path, whereas the path number keeps track of which path number
// the program is on.
long BLInstrumentationEdge::getIncrement() const {
  return(_increment);
}

// Set whether this edge will be instrumented with a path number
// increment.
void BLInstrumentationEdge::setIncrement(long increment) {
  _increment = increment;
}

// True iff the edge has already been instrumented.
bool BLInstrumentationEdge::hasInstrumentation() {
  return(_hasInstrumentation);
}

// Set whether this edge has been instrumented.
void BLInstrumentationEdge::setHasInstrumentation(bool hasInstrumentation) {
  _hasInstrumentation = hasInstrumentation;
}

// Returns the successor number of this edge in the source.
unsigned BLInstrumentationEdge::getSuccessorNumber() {
  BallLarusNode* sourceNode = getSource();
  BallLarusNode* targetNode = getTarget();
  BasicBlock* source = sourceNode->getBlock();
  BasicBlock* target = targetNode->getBlock();

  if(source == NULL || target == NULL)
    return(0);

  TerminatorInst* terminator = source->getTerminator();

        unsigned i;
  for(i=0; i < terminator->getNumSuccessors(); i++) {
    if(terminator->getSuccessor(i) == target)
      break;
  }

  return(i);
}

// BLInstrumentationDag constructor initializes a DAG for the given Function.
BLInstrumentationDag::BLInstrumentationDag(Function &F) : BallLarusDag(F),
                                                          _counterArray(0) {
}

// Returns the Exit->Root edge. This edge is required for creating
// directed cycles in the algorithm for moving instrumentation off of
// the spanning tree
BallLarusEdge* BLInstrumentationDag::getExitRootEdge() {
  BLEdgeIterator erEdge = getExit()->succBegin();
  return(*erEdge);
}

BLEdgeVector BLInstrumentationDag::getCallPhonyEdges () {
  BLEdgeVector callEdges;

  for( BLEdgeIterator edge = _edges.begin(), end = _edges.end();
       edge != end; edge++ ) {
    if( (*edge)->getType() == BallLarusEdge::CALLEDGE_PHONY )
      callEdges.push_back(*edge);
  }

  return callEdges;
}

// Gets the path counter array
GlobalVariable* BLInstrumentationDag::getCounterArray() {
  return _counterArray;
}

void BLInstrumentationDag::setCounterArray(GlobalVariable* c) {
  _counterArray = c;
}

// Calculates the increment for the chords, thereby removing
// instrumentation from the spanning tree edges. Implementation is based on
// the algorithm in Figure 4 of [Ball94]
void BLInstrumentationDag::calculateChordIncrements() {
  calculateChordIncrementsDfs(0, getRoot(), NULL);

  BLInstrumentationEdge* chord;
  for(BLEdgeIterator chordEdge = _chordEdges.begin(),
      end = _chordEdges.end(); chordEdge != end; chordEdge++) {
    chord = (BLInstrumentationEdge*) *chordEdge;
    chord->setIncrement(chord->getIncrement() + chord->getWeight());
  }
}

// Updates the state when an edge has been split
void BLInstrumentationDag::splitUpdate(BLInstrumentationEdge* formerEdge,
                                       BasicBlock* newBlock) {
  BallLarusNode* oldTarget = formerEdge->getTarget();
  BallLarusNode* newNode = addNode(newBlock);
  formerEdge->setTarget(newNode);
  newNode->addPredEdge(formerEdge);

  DEBUG(dbgs() << "  Edge split: " << *formerEdge << "\n");

  oldTarget->removePredEdge(formerEdge);
  BallLarusEdge* newEdge = addEdge(newNode, oldTarget,0);

  if( formerEdge->getType() == BallLarusEdge::BACKEDGE ||
                        formerEdge->getType() == BallLarusEdge::SPLITEDGE) {
                newEdge->setType(formerEdge->getType());
    newEdge->setPhonyRoot(formerEdge->getPhonyRoot());
    newEdge->setPhonyExit(formerEdge->getPhonyExit());
    formerEdge->setType(BallLarusEdge::NORMAL);
                formerEdge->setPhonyRoot(NULL);
    formerEdge->setPhonyExit(NULL);
  }
}

// Calculates a spanning tree of the DAG ignoring cycles.  Whichever
// edges are in the spanning tree will not be instrumented, but this
// implementation does not try to minimize the instrumentation overhead
// by trying to find hot edges.
void BLInstrumentationDag::calculateSpanningTree() {
  std::stack<BallLarusNode*> dfsStack;

  for(BLNodeIterator nodeIt = _nodes.begin(), end = _nodes.end();
      nodeIt != end; nodeIt++) {
    (*nodeIt)->setColor(BallLarusNode::WHITE);
  }

  dfsStack.push(getRoot());
  while(dfsStack.size() > 0) {
    BallLarusNode* node = dfsStack.top();
    dfsStack.pop();

    if(node->getColor() == BallLarusNode::WHITE)
      continue;

    BallLarusNode* nextNode;
    bool forward = true;
    BLEdgeIterator succEnd = node->succEnd();

    node->setColor(BallLarusNode::WHITE);
    // first iterate over successors then predecessors
    for(BLEdgeIterator edge = node->succBegin(), predEnd = node->predEnd();
        edge != predEnd; edge++) {
      if(edge == succEnd) {
        edge = node->predBegin();
        forward = false;
      }

      // Ignore split edges
      if ((*edge)->getType() == BallLarusEdge::SPLITEDGE)
        continue;

      nextNode = forward? (*edge)->getTarget(): (*edge)->getSource();
      if(nextNode->getColor() != BallLarusNode::WHITE) {
        nextNode->setColor(BallLarusNode::WHITE);
        makeEdgeSpanning((BLInstrumentationEdge*)(*edge));
      }
    }
  }

  for(BLEdgeIterator edge = _edges.begin(), end = _edges.end();
      edge != end; edge++) {
    BLInstrumentationEdge* instEdge = (BLInstrumentationEdge*) (*edge);
      // safe since createEdge is overriden
    if(!instEdge->isInSpanningTree() && (*edge)->getType()
        != BallLarusEdge::SPLITEDGE)
      _chordEdges.push_back(instEdge);
  }
}

// Pushes initialization further down in order to group the first
// increment and initialization.
void BLInstrumentationDag::pushInitialization() {
  BLInstrumentationEdge* exitRootEdge =
                (BLInstrumentationEdge*) getExitRootEdge();
  exitRootEdge->setIsInitialization(true);
  pushInitializationFromEdge(exitRootEdge);
}

// Pushes the path counter increments up in order to group the last path
// number increment.
void BLInstrumentationDag::pushCounters() {
  BLInstrumentationEdge* exitRootEdge =
    (BLInstrumentationEdge*) getExitRootEdge();
  exitRootEdge->setIsCounterIncrement(true);
  pushCountersFromEdge(exitRootEdge);
}

// Removes phony edges from the successor list of the source, and the
// predecessor list of the target.
void BLInstrumentationDag::unlinkPhony() {
  BallLarusEdge* edge;

  for(BLEdgeIterator next = _edges.begin(),
      end = _edges.end(); next != end; next++) {
    edge = (*next);

    if( edge->getType() == BallLarusEdge::BACKEDGE_PHONY ||
        edge->getType() == BallLarusEdge::SPLITEDGE_PHONY ||
        edge->getType() == BallLarusEdge::CALLEDGE_PHONY ) {
      unlinkEdge(edge);
    }
  }
}

// Generate a .dot graph to represent the DAG and pathNumbers
void BLInstrumentationDag::generateDotGraph() {
  std::string errorInfo;
  std::string functionName = getFunction().getName().str();
  std::string filename = "pathdag." + functionName + ".dot";

  DEBUG (dbgs() << "Writing '" << filename << "'...\n");
  raw_fd_ostream dotFile(filename.c_str(), errorInfo);

  if (!errorInfo.empty()) {
    errs() << "Error opening '" << filename.c_str() <<"' for writing!";
    errs() << "\n";
    return;
  }

  dotFile << "digraph " << functionName << " {\n";

  for( BLEdgeIterator edge = _edges.begin(), end = _edges.end();
       edge != end; edge++) {
    std::string sourceName = (*edge)->getSource()->getName();
    std::string targetName = (*edge)->getTarget()->getName();

    dotFile << "\t\"" << sourceName.c_str() << "\" -> \""
            << targetName.c_str() << "\" ";

    long inc = ((BLInstrumentationEdge*)(*edge))->getIncrement();

    switch( (*edge)->getType() ) {
    case BallLarusEdge::NORMAL:
      dotFile << "[label=" << inc << "] [color=black];\n";
      break;

    case BallLarusEdge::BACKEDGE:
      dotFile << "[color=cyan];\n";
      break;

    case BallLarusEdge::BACKEDGE_PHONY:
      dotFile << "[label=" << inc
              << "] [color=blue];\n";
      break;

    case BallLarusEdge::SPLITEDGE:
      dotFile << "[color=violet];\n";
      break;

    case BallLarusEdge::SPLITEDGE_PHONY:
      dotFile << "[label=" << inc << "] [color=red];\n";
      break;

    case BallLarusEdge::CALLEDGE_PHONY:
      dotFile << "[label=" << inc     << "] [color=green];\n";
      break;
    }
  }

  dotFile << "}\n";
}

// Allows subclasses to determine which type of Node is created.
// Override this method to produce subclasses of BallLarusNode if
// necessary. The destructor of BallLarusDag will call free on each pointer
// created.
BallLarusNode* BLInstrumentationDag::createNode(BasicBlock* BB) {
  return( new BLInstrumentationNode(BB) );
}

// Allows subclasses to determine which type of Edge is created.
// Override this method to produce subclasses of BallLarusEdge if
// necessary. The destructor of BallLarusDag will call free on each pointer
// created.
BallLarusEdge* BLInstrumentationDag::createEdge(BallLarusNode* source,
                                                BallLarusNode* target, unsigned edgeNumber) {
  // One can cast from BallLarusNode to BLInstrumentationNode since createNode
  // is overriden to produce BLInstrumentationNode.
  return( new BLInstrumentationEdge((BLInstrumentationNode*)source,
                                    (BLInstrumentationNode*)target) );
}

// Sets the Value corresponding to the pathNumber register, constant,
// or phinode.  Used by the instrumentation code to remember path
// number Values.
Value* BLInstrumentationNode::getStartingPathNumber(){
  return(_startingPathNumber);
}

// Sets the Value of the pathNumber.  Used by the instrumentation code.
void BLInstrumentationNode::setStartingPathNumber(Value* pathNumber) {
  DEBUG(dbgs() << "  SPN-" << getName() << " <-- " << (pathNumber ?
                                                       pathNumber->getName() :
                                                       "unused") << "\n");
  _startingPathNumber = pathNumber;
}

Value* BLInstrumentationNode::getEndingPathNumber(){
  return(_endingPathNumber);
}

void BLInstrumentationNode::setEndingPathNumber(Value* pathNumber) {
  DEBUG(dbgs() << "  EPN-" << getName() << " <-- "
               << (pathNumber ? pathNumber->getName() : "unused") << "\n");
  _endingPathNumber = pathNumber;
}

// Get the PHINode Instruction for this node.  Used by instrumentation
// code.
PHINode* BLInstrumentationNode::getPathPHI() {
  return(_pathPHI);
}

// Set the PHINode Instruction for this node.  Used by instrumentation
// code.
void BLInstrumentationNode::setPathPHI(PHINode* pathPHI) {
  _pathPHI = pathPHI;
}

// Removes the edge from the appropriate predecessor and successor
// lists.
void BLInstrumentationDag::unlinkEdge(BallLarusEdge* edge) {
  if(edge == getExitRootEdge())
    DEBUG(dbgs() << " Removing exit->root edge\n");

  edge->getSource()->removeSuccEdge(edge);
  edge->getTarget()->removePredEdge(edge);
}

// Makes an edge part of the spanning tree.
void BLInstrumentationDag::makeEdgeSpanning(BLInstrumentationEdge* edge) {
  edge->setIsInSpanningTree(true);
  _treeEdges.push_back(edge);
}

// Pushes initialization and calls itself recursively.
void BLInstrumentationDag::pushInitializationFromEdge(
  BLInstrumentationEdge* edge) {
  BallLarusNode* target;

  target = edge->getTarget();
  if( target->getNumberPredEdges() > 1 || target == getExit() ) {
    return;
  } else {
    for(BLEdgeIterator next = target->succBegin(),
          end = target->succEnd(); next != end; next++) {
      BLInstrumentationEdge* intoEdge = (BLInstrumentationEdge*) *next;

      // Skip split edges
      if (intoEdge->getType() == BallLarusEdge::SPLITEDGE)
        continue;

      intoEdge->setIncrement(intoEdge->getIncrement() +
                             edge->getIncrement());
      intoEdge->setIsInitialization(true);
      pushInitializationFromEdge(intoEdge);
    }

    edge->setIncrement(0);
    edge->setIsInitialization(false);
  }
}

// Pushes path counter increments up recursively.
void BLInstrumentationDag::pushCountersFromEdge(BLInstrumentationEdge* edge) {
  BallLarusNode* source;

  source = edge->getSource();
  if(source->getNumberSuccEdges() > 1 || source == getRoot()
     || edge->isInitialization()) {
    return;
  } else {
    for(BLEdgeIterator previous = source->predBegin(),
          end = source->predEnd(); previous != end; previous++) {
      BLInstrumentationEdge* fromEdge = (BLInstrumentationEdge*) *previous;

      // Skip split edges
      if (fromEdge->getType() == BallLarusEdge::SPLITEDGE)
        continue;

      fromEdge->setIncrement(fromEdge->getIncrement() +
                             edge->getIncrement());
      fromEdge->setIsCounterIncrement(true);
      pushCountersFromEdge(fromEdge);
    }

    edge->setIncrement(0);
    edge->setIsCounterIncrement(false);
  }
}

// Depth first algorithm for determining the chord increments.
void BLInstrumentationDag::calculateChordIncrementsDfs(long weight,
                                                       BallLarusNode* v, BallLarusEdge* e) {
  BLInstrumentationEdge* f;

  for(BLEdgeIterator treeEdge = _treeEdges.begin(),
        end = _treeEdges.end(); treeEdge != end; treeEdge++) {
    f = (BLInstrumentationEdge*) *treeEdge;
    if(e != f && v == f->getTarget()) {
      calculateChordIncrementsDfs(
        calculateChordIncrementsDir(e,f)*(weight) +
        f->getWeight(), f->getSource(), f);
    }
    if(e != f && v == f->getSource()) {
      calculateChordIncrementsDfs(
        calculateChordIncrementsDir(e,f)*(weight) +
        f->getWeight(), f->getTarget(), f);
    }
  }

  for(BLEdgeIterator chordEdge = _chordEdges.begin(),
        end = _chordEdges.end(); chordEdge != end; chordEdge++) {
    f = (BLInstrumentationEdge*) *chordEdge;
    if(v == f->getSource() || v == f->getTarget()) {
      f->setIncrement(f->getIncrement() +
                      calculateChordIncrementsDir(e,f)*weight);
    }
  }
}

// Determines the relative direction of two edges.
int BLInstrumentationDag::calculateChordIncrementsDir(BallLarusEdge* e,
                                                      BallLarusEdge* f) {
  if( e == NULL)
    return(1);
  else if(e->getSource() == f->getTarget()
          || e->getTarget() == f->getSource())
    return(1);

  return(-1);
}

// Creates an increment constant representing incr.
ConstantInt* PathProfiler::createIncrementConstant(long incr,
                                                   int bitsize) {
  return(ConstantInt::get(IntegerType::get(*Context, 32), incr));
}

// Creates an increment constant representing the value in
// edge->getIncrement().
ConstantInt* PathProfiler::createIncrementConstant(
  BLInstrumentationEdge* edge) {
  return(createIncrementConstant(edge->getIncrement(), 32));
}

// Finds the insertion point after pathNumber in block.  PathNumber may
// be NULL.
BasicBlock::iterator PathProfiler::getInsertionPoint(BasicBlock* block, Value*
                                                     pathNumber) {
  if(pathNumber == NULL || isa<ConstantInt>(pathNumber)
     || (((Instruction*)(pathNumber))->getParent()) != block) {
    return(block->getFirstInsertionPt());
  } else {
    Instruction* pathNumberInst = (Instruction*) (pathNumber);
    BasicBlock::iterator insertPoint;
    BasicBlock::iterator end = block->end();

    for(insertPoint = block->begin();
        insertPoint != end; insertPoint++) {
      Instruction* insertInst = &(*insertPoint);

      if(insertInst == pathNumberInst)
        return(++insertPoint);
    }

    return(insertPoint);
  }
}

// A PHINode is created in the node, and its values initialized to -1U.
void PathProfiler::preparePHI(BLInstrumentationNode* node) {
  BasicBlock* block = node->getBlock();
  BasicBlock::iterator insertPoint = block->getFirstInsertionPt();
  pred_iterator PB = pred_begin(node->getBlock()),
          PE = pred_end(node->getBlock());
  PHINode* phi = PHINode::Create(Type::getInt32Ty(*Context),
                                 std::distance(PB, PE), "pathNumber",
                                 insertPoint );
  node->setPathPHI(phi);
  node->setStartingPathNumber(phi);
  node->setEndingPathNumber(phi);

  for(pred_iterator predIt = PB; predIt != PE; predIt++) {
    BasicBlock* pred = (*predIt);

    if(pred != NULL)
      phi->addIncoming(createIncrementConstant((long)-1, 32), pred);
  }
}

// Inserts source's pathNumber Value* into target.  Target may or may not
// have multiple predecessors, and may or may not have its phiNode
// initalized.
void PathProfiler::pushValueIntoNode(BLInstrumentationNode* source,
                                     BLInstrumentationNode* target) {
  if(target->getBlock() == NULL)
    return;


  if(target->getNumberPredEdges() <= 1) {
    assert(target->getStartingPathNumber() == NULL &&
           "Target already has path number");
    target->setStartingPathNumber(source->getEndingPathNumber());
    target->setEndingPathNumber(source->getEndingPathNumber());
    DEBUG(dbgs() << "  Passing path number"
          << (source->getEndingPathNumber() ? "" : " (null)")
          << " value through.\n");
  } else {
    if(target->getPathPHI() == NULL) {
      DEBUG(dbgs() << "  Initializing PHI node for block '"
            << target->getName() << "'\n");
      preparePHI(target);
    }
    pushValueIntoPHI(target, source);
    DEBUG(dbgs() << "  Passing number value into PHI for block '"
          << target->getName() << "'\n");
  }
}

// Inserts source's pathNumber Value* into the appropriate slot of
// target's phiNode.
void PathProfiler::pushValueIntoPHI(BLInstrumentationNode* target,
                                    BLInstrumentationNode* source) {
  PHINode* phi = target->getPathPHI();
  assert(phi != NULL && "  Tried to push value into node with PHI, but node"
         " actually had no PHI.");
  phi->removeIncomingValue(source->getBlock(), false);
  phi->addIncoming(source->getEndingPathNumber(), source->getBlock());
}

// The Value* in node, oldVal,  is updated with a Value* correspodning to
// oldVal + addition.
void PathProfiler::insertNumberIncrement(BLInstrumentationNode* node,
                                         Value* addition, bool atBeginning) {
  BasicBlock* block = node->getBlock();
  assert(node->getStartingPathNumber() != NULL);
  assert(node->getEndingPathNumber() != NULL);

  BasicBlock::iterator insertPoint;

  if( atBeginning )
    insertPoint = block->getFirstInsertionPt();
  else
    insertPoint = block->getTerminator();

  DEBUG(errs() << "  Creating addition instruction.\n");
  Value* newpn = BinaryOperator::Create(Instruction::Add,
                                        node->getStartingPathNumber(),
                                        addition, "pathNumber", insertPoint);

  node->setEndingPathNumber(newpn);

  if( atBeginning )
    node->setStartingPathNumber(newpn);
}

// Creates a counter increment in the given node.  The Value* in node is
// taken as the index into an array or hash table.  The hash table access
// is a call to the runtime.
void PathProfiler::insertCounterIncrement(Value* incValue,
                                          BasicBlock::iterator insertPoint,
                                          BLInstrumentationDag* dag,
                                          bool increment) {
  // Counter increment for array
  if( dag->getNumberOfPaths() <= HASH_THRESHHOLD ) {
    // Get pointer to the array location
    std::vector<Value*> gepIndices(2);
    gepIndices[0] = Constant::getNullValue(Type::getInt32Ty(*Context));
    gepIndices[1] = incValue;

    GetElementPtrInst* pcPointer =
      GetElementPtrInst::Create(dag->getCounterArray(), gepIndices,
                                "counterInc", insertPoint);

    // Load from the array - call it oldPC
    LoadInst* oldPc = new LoadInst(pcPointer, "oldPC", insertPoint);

    // Test to see whether adding 1 will overflow the counter
    ICmpInst* isMax = new ICmpInst(insertPoint, CmpInst::ICMP_ULT, oldPc,
                                   createIncrementConstant(0xffffffff, 32),
                                   "isMax");

    // Select increment for the path counter based on overflow
    SelectInst* inc =
      SelectInst::Create( isMax, createIncrementConstant(increment?1:-1,32),
                          createIncrementConstant(0,32),
                          "pathInc", insertPoint);

    // newPc = oldPc + inc
    BinaryOperator* newPc = BinaryOperator::Create(Instruction::Add,
                                                   oldPc, inc, "newPC",
                                                   insertPoint);

    // Store back in to the array
    new StoreInst(newPc, pcPointer, insertPoint);
  } else { // Counter increment for hash
    std::vector<Value*> args(2);
    args[0] = ConstantInt::get(Type::getInt32Ty(*Context),
                               currentFunctionNumber);
    args[1] = incValue;

    CallInst::Create(
      increment ? llvmIncrementHashFunction : llvmDecrementHashFunction,
      args, "", insertPoint);
  }
}

// Inserts instrumentation for the given edge
//
// Pre: The edge's source node has pathNumber set if edge is non zero
// path number increment.
//
// Post: Edge's target node has a pathNumber set to the path number Value
// corresponding to the value of the path register after edge's
// execution.
//
// FIXME: This should be reworked so it's not recursive.
void PathProfiler::insertInstrumentationStartingAt(BLInstrumentationEdge* edge,
                                                   BLInstrumentationDag* dag) {
  // Mark the edge as instrumented
  edge->setHasInstrumentation(true);
  DEBUG(dbgs() << "\nInstrumenting edge: " << (*edge) << "\n");

  // create a new node for this edge's instrumentation
  splitCritical(edge, dag);

  BLInstrumentationNode* sourceNode = (BLInstrumentationNode*)edge->getSource();
  BLInstrumentationNode* targetNode = (BLInstrumentationNode*)edge->getTarget();
  BLInstrumentationNode* instrumentNode;
  BLInstrumentationNode* nextSourceNode;

  bool atBeginning = false;

  // Source node has only 1 successor so any information can be simply
  // inserted in to it without splitting
  if( sourceNode->getBlock() && sourceNode->getNumberSuccEdges() <= 1) {
    DEBUG(dbgs() << "  Potential instructions to be placed in: "
          << sourceNode->getName() << " (at end)\n");
    instrumentNode = sourceNode;
    nextSourceNode = targetNode; // ... since we never made any new nodes
  }

  // The target node only has one predecessor, so we can safely insert edge
  // instrumentation into it. If there was splitting, it must have been
  // successful.
  else if( targetNode->getNumberPredEdges() == 1 ) {
    DEBUG(dbgs() << "  Potential instructions to be placed in: "
          << targetNode->getName() << " (at beginning)\n");
    pushValueIntoNode(sourceNode, targetNode);
    instrumentNode = targetNode;
    nextSourceNode = NULL; // ... otherwise we'll just keep splitting
    atBeginning = true;
  }

  // Somehow, splitting must have failed.
  else {
    errs() << "Instrumenting could not split a critical edge.\n";
    DEBUG(dbgs() << "  Couldn't split edge " << (*edge) << ".\n");
    return;
  }

  // Insert instrumentation if this is a back or split edge
  if( edge->getType() == BallLarusEdge::BACKEDGE ||
      edge->getType() == BallLarusEdge::SPLITEDGE ) {
    BLInstrumentationEdge* top =
      (BLInstrumentationEdge*) edge->getPhonyRoot();
    BLInstrumentationEdge* bottom =
      (BLInstrumentationEdge*) edge->getPhonyExit();

    assert( top->isInitialization() && " Top phony edge did not"
            " contain a path number initialization.");
    assert( bottom->isCounterIncrement() && " Bottom phony edge"
            " did not contain a path counter increment.");

    // split edge has yet to be initialized
    if( !instrumentNode->getEndingPathNumber() ) {
      instrumentNode->setStartingPathNumber(createIncrementConstant(0,32));
      instrumentNode->setEndingPathNumber(createIncrementConstant(0,32));
    }

    BasicBlock::iterator insertPoint = atBeginning ?
      instrumentNode->getBlock()->getFirstInsertionPt() :
      instrumentNode->getBlock()->getTerminator();

    // add information from the bottom edge, if it exists
    if( bottom->getIncrement() ) {
      Value* newpn =
        BinaryOperator::Create(Instruction::Add,
                               instrumentNode->getStartingPathNumber(),
                               createIncrementConstant(bottom),
                               "pathNumber", insertPoint);
      instrumentNode->setEndingPathNumber(newpn);
    }

    insertCounterIncrement(instrumentNode->getEndingPathNumber(),
                           insertPoint, dag);

    if( atBeginning )
      instrumentNode->setStartingPathNumber(createIncrementConstant(top));

    instrumentNode->setEndingPathNumber(createIncrementConstant(top));

    // Check for path counter increments
    if( top->isCounterIncrement() ) {
      insertCounterIncrement(instrumentNode->getEndingPathNumber(),
                             instrumentNode->getBlock()->getTerminator(),dag);
      instrumentNode->setEndingPathNumber(0);
    }
  }

  // Insert instrumentation if this is a normal edge
  else {
    BasicBlock::iterator insertPoint = atBeginning ?
      instrumentNode->getBlock()->getFirstInsertionPt() :
      instrumentNode->getBlock()->getTerminator();

    if( edge->isInitialization() ) { // initialize path number
      instrumentNode->setEndingPathNumber(createIncrementConstant(edge));
    } else if( edge->getIncrement() )       {// increment path number
      Value* newpn =
        BinaryOperator::Create(Instruction::Add,
                               instrumentNode->getStartingPathNumber(),
                               createIncrementConstant(edge),
                               "pathNumber", insertPoint);
      instrumentNode->setEndingPathNumber(newpn);

      if( atBeginning )
        instrumentNode->setStartingPathNumber(newpn);
    }

    // Check for path counter increments
    if( edge->isCounterIncrement() ) {
      insertCounterIncrement(instrumentNode->getEndingPathNumber(),
                             insertPoint, dag);
      instrumentNode->setEndingPathNumber(0);
    }
  }

  // Push it along
  if (nextSourceNode && instrumentNode->getEndingPathNumber())
    pushValueIntoNode(instrumentNode, nextSourceNode);

  // Add all the successors
  for( BLEdgeIterator next = targetNode->succBegin(),
         end = targetNode->succEnd(); next != end; next++ ) {
    // So long as it is un-instrumented, add it to the list
    if( !((BLInstrumentationEdge*)(*next))->hasInstrumentation() )
      insertInstrumentationStartingAt((BLInstrumentationEdge*)*next,dag);
    else
      DEBUG(dbgs() << "  Edge " << *(BLInstrumentationEdge*)(*next)
            << " already instrumented.\n");
  }
}

// Inserts instrumentation according to the marked edges in dag.  Phony edges
// must be unlinked from the DAG, but accessible from the backedges.  Dag
// must have initializations, path number increments, and counter increments
// present.
//
// Counter storage is created here.
void PathProfiler::insertInstrumentation(
  BLInstrumentationDag& dag, Module &M) {

  BLInstrumentationEdge* exitRootEdge =
    (BLInstrumentationEdge*) dag.getExitRootEdge();
  insertInstrumentationStartingAt(exitRootEdge, &dag);

  // Iterate through each call edge and apply the appropriate hash increment
  // and decrement functions
  BLEdgeVector callEdges = dag.getCallPhonyEdges();
  for( BLEdgeIterator edge = callEdges.begin(),
         end = callEdges.end(); edge != end; edge++ ) {
    BLInstrumentationNode* node =
      (BLInstrumentationNode*)(*edge)->getSource();
    BasicBlock::iterator insertPoint = node->getBlock()->getFirstInsertionPt();

    // Find the first function call
    while( ((Instruction&)(*insertPoint)).getOpcode() != Instruction::Call )
      insertPoint++;

    DEBUG(dbgs() << "\nInstrumenting method call block '"
                 << node->getBlock()->getName() << "'\n");
    DEBUG(dbgs() << "   Path number initialized: "
                 << ((node->getStartingPathNumber()) ? "yes" : "no") << "\n");

    Value* newpn;
    if( node->getStartingPathNumber() ) {
      long inc = ((BLInstrumentationEdge*)(*edge))->getIncrement();
      if ( inc )
        newpn = BinaryOperator::Create(Instruction::Add,
                                       node->getStartingPathNumber(),
                                       createIncrementConstant(inc,32),
                                       "pathNumber", insertPoint);
      else
        newpn = node->getStartingPathNumber();
    } else {
      newpn = (Value*)createIncrementConstant(
        ((BLInstrumentationEdge*)(*edge))->getIncrement(), 32);
    }

    insertCounterIncrement(newpn, insertPoint, &dag);
    insertCounterIncrement(newpn, node->getBlock()->getTerminator(),
                           &dag, false);
  }
}

// Entry point of the module
void PathProfiler::runOnFunction(std::vector<Constant*> &ftInit,
                                 Function &F, Module &M) {
  // Build DAG from CFG
  BLInstrumentationDag dag = BLInstrumentationDag(F);
  dag.init();

  // give each path a unique integer value
  dag.calculatePathNumbers();

  // modify path increments to increase the efficiency
  // of instrumentation
  dag.calculateSpanningTree();
  dag.calculateChordIncrements();
  dag.pushInitialization();
  dag.pushCounters();
  dag.unlinkPhony();

  // potentially generate .dot graph for the dag
  if (DotPathDag)
    dag.generateDotGraph ();

  // Should we store the information in an array or hash
  if( dag.getNumberOfPaths() <= HASH_THRESHHOLD ) {
    Type* t = ArrayType::get(Type::getInt32Ty(*Context),
                                   dag.getNumberOfPaths());

    dag.setCounterArray(new GlobalVariable(M, t, false,
                                           GlobalValue::InternalLinkage,
                                           Constant::getNullValue(t), ""));
  }

  insertInstrumentation(dag, M);

  // Add to global function reference table
  unsigned type;
  Type* voidPtr = TypeBuilder<types::i<8>*, true>::get(*Context);

  if( dag.getNumberOfPaths() <= HASH_THRESHHOLD )
    type = ProfilingArray;
  else
    type = ProfilingHash;

  std::vector<Constant*> entryArray(3);
  entryArray[0] = createIncrementConstant(type,32);
  entryArray[1] = createIncrementConstant(dag.getNumberOfPaths(),32);
  entryArray[2] = dag.getCounterArray() ?
    ConstantExpr::getBitCast(dag.getCounterArray(), voidPtr) :
    Constant::getNullValue(voidPtr);

  StructType* at = ftEntryTypeBuilder::get(*Context);
  ConstantStruct* functionEntry =
    (ConstantStruct*)ConstantStruct::get(at, entryArray);
  ftInit.push_back(functionEntry);
}

// Output the bitcode if we want to observe instrumentation changess
#define PRINT_MODULE dbgs() <<                               \
  "\n\n============= MODULE BEGIN ===============\n" << M << \
  "\n============== MODULE END ================\n"

bool PathProfiler::runOnModule(Module &M) {
  Context = &M.getContext();

  DEBUG(dbgs()
        << "****************************************\n"
        << "****************************************\n"
        << "**                                    **\n"
        << "**   PATH PROFILING INSTRUMENTATION   **\n"
        << "**                                    **\n"
        << "****************************************\n"
        << "****************************************\n");

  // No main, no instrumentation!
  Function *Main = M.getFunction("main");

  // Using fortran? ... this kind of works
  if (!Main)
    Main = M.getFunction("MAIN__");

  if (!Main) {
    errs() << "WARNING: cannot insert path profiling into a module"
           << " with no main function!\n";
    return false;
  }

  llvmIncrementHashFunction = M.getOrInsertFunction(
    "llvm_increment_path_count",
    Type::getVoidTy(*Context), // return type
    Type::getInt32Ty(*Context), // function number
    Type::getInt32Ty(*Context), // path number
    NULL );

  llvmDecrementHashFunction = M.getOrInsertFunction(
    "llvm_decrement_path_count",
    Type::getVoidTy(*Context), // return type
    Type::getInt32Ty(*Context), // function number
    Type::getInt32Ty(*Context), // path number
    NULL );

  std::vector<Constant*> ftInit;
  unsigned functionNumber = 0;
  for (Module::iterator F = M.begin(), E = M.end(); F != E; F++) {
    if (F->isDeclaration())
      continue;

    DEBUG(dbgs() << "Function: " << F->getName() << "\n");
    functionNumber++;

    // set function number
    currentFunctionNumber = functionNumber;
    runOnFunction(ftInit, *F, M);
  }

  Type *t = ftEntryTypeBuilder::get(*Context);
  ArrayType* ftArrayType = ArrayType::get(t, ftInit.size());
  Constant* ftInitConstant = ConstantArray::get(ftArrayType, ftInit);

  DEBUG(dbgs() << " ftArrayType:" << *ftArrayType << "\n");

  GlobalVariable* functionTable =
    new GlobalVariable(M, ftArrayType, false, GlobalValue::InternalLinkage,
                       ftInitConstant, "functionPathTable");
  Type *eltType = ftArrayType->getTypeAtIndex((unsigned)0);
  InsertProfilingInitCall(Main, "llvm_start_path_profiling", functionTable,
                          PointerType::getUnqual(eltType));

  DEBUG(PRINT_MODULE);

  return true;
}

// If this edge is a critical edge, then inserts a node at this edge.
// This edge becomes the first edge, and a new BallLarusEdge is created.
// Returns true if the edge was split
bool PathProfiler::splitCritical(BLInstrumentationEdge* edge,
                                 BLInstrumentationDag* dag) {
  unsigned succNum = edge->getSuccessorNumber();
  BallLarusNode* sourceNode = edge->getSource();
  BallLarusNode* targetNode = edge->getTarget();
  BasicBlock* sourceBlock = sourceNode->getBlock();
  BasicBlock* targetBlock = targetNode->getBlock();

  if(sourceBlock == NULL || targetBlock == NULL
     || sourceNode->getNumberSuccEdges() <= 1
     || targetNode->getNumberPredEdges() == 1 ) {
    return(false);
  }

  TerminatorInst* terminator = sourceBlock->getTerminator();

  if( SplitCriticalEdge(terminator, succNum, this, false)) {
    BasicBlock* newBlock = terminator->getSuccessor(succNum);
    dag->splitUpdate(edge, newBlock);
    return(true);
  } else
    return(false);
}
