| //===- 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/Transforms/Instrumentation.h" |
| #include "ProfilingUtils.h" |
| #include "llvm/Analysis/PathNumbering.h" |
| #include "llvm/IR/Constants.h" |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/IR/InstrTypes.h" |
| #include "llvm/IR/Instructions.h" |
| #include "llvm/IR/LLVMContext.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/IR/TypeBuilder.h" |
| #include "llvm/Pass.h" |
| #include "llvm/Support/CFG.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "llvm/Transforms/Utils/BasicBlockUtils.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); |
| } |