• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //===- ProfileVerifierPass.cpp - LLVM Pass to estimate profile info -------===//
2  //
3  //                     The LLVM Compiler Infrastructure
4  //
5  // This file is distributed under the University of Illinois Open Source
6  // License. See LICENSE.TXT for details.
7  //
8  //===----------------------------------------------------------------------===//
9  //
10  // This file implements a pass that checks profiling information for
11  // plausibility.
12  //
13  //===----------------------------------------------------------------------===//
14  #define DEBUG_TYPE "profile-verifier"
15  #include "llvm/Analysis/Passes.h"
16  #include "llvm/Analysis/ProfileInfo.h"
17  #include "llvm/IR/Instructions.h"
18  #include "llvm/IR/Module.h"
19  #include "llvm/Pass.h"
20  #include "llvm/Support/CFG.h"
21  #include "llvm/Support/CallSite.h"
22  #include "llvm/Support/CommandLine.h"
23  #include "llvm/Support/Debug.h"
24  #include "llvm/Support/Format.h"
25  #include "llvm/Support/InstIterator.h"
26  #include "llvm/Support/raw_ostream.h"
27  #include <set>
28  using namespace llvm;
29  
30  static cl::opt<bool,false>
31  ProfileVerifierDisableAssertions("profile-verifier-noassert",
32       cl::desc("Disable assertions"));
33  
34  namespace {
35    template<class FType, class BType>
36    class ProfileVerifierPassT : public FunctionPass {
37  
38      struct DetailedBlockInfo {
39        const BType *BB;
40        double      BBWeight;
41        double      inWeight;
42        int         inCount;
43        double      outWeight;
44        int         outCount;
45      };
46  
47      ProfileInfoT<FType, BType> *PI;
48      std::set<const BType*> BBisVisited;
49      std::set<const FType*>   FisVisited;
50      bool DisableAssertions;
51  
52      // When debugging is enabled, the verifier prints a whole slew of debug
53      // information, otherwise its just the assert. These are all the helper
54      // functions.
55      bool PrintedDebugTree;
56      std::set<const BType*> BBisPrinted;
57      void debugEntry(DetailedBlockInfo*);
58      void printDebugInfo(const BType *BB);
59  
60    public:
61      static char ID; // Class identification, replacement for typeinfo
62  
ProfileVerifierPassT()63      explicit ProfileVerifierPassT () : FunctionPass(ID) {
64        initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry());
65        DisableAssertions = ProfileVerifierDisableAssertions;
66      }
ProfileVerifierPassT(bool da)67      explicit ProfileVerifierPassT (bool da) : FunctionPass(ID),
68                                                DisableAssertions(da) {
69        initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry());
70      }
71  
getAnalysisUsage(AnalysisUsage & AU) const72      void getAnalysisUsage(AnalysisUsage &AU) const {
73        AU.setPreservesAll();
74        AU.addRequired<ProfileInfoT<FType, BType> >();
75      }
76  
getPassName() const77      const char *getPassName() const {
78        return "Profiling information verifier";
79      }
80  
81      /// run - Verify the profile information.
82      bool runOnFunction(FType &F);
83      void recurseBasicBlock(const BType*);
84  
85      bool   exitReachable(const FType*);
86      double ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge);
87      void   CheckValue(bool, const char*, DetailedBlockInfo*);
88    };
89  
90    typedef ProfileVerifierPassT<Function, BasicBlock> ProfileVerifierPass;
91  
92    template<class FType, class BType>
printDebugInfo(const BType * BB)93    void ProfileVerifierPassT<FType, BType>::printDebugInfo(const BType *BB) {
94  
95      if (BBisPrinted.find(BB) != BBisPrinted.end()) return;
96  
97      double BBWeight = PI->getExecutionCount(BB);
98      if (BBWeight == ProfileInfoT<FType, BType>::MissingValue) { BBWeight = 0; }
99      double inWeight = 0;
100      int inCount = 0;
101      std::set<const BType*> ProcessedPreds;
102      for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
103           bbi != bbe; ++bbi ) {
104        if (ProcessedPreds.insert(*bbi).second) {
105          typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(*bbi,BB);
106          double EdgeWeight = PI->getEdgeWeight(E);
107          if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
108          dbgs() << "calculated in-edge " << E << ": "
109                 << format("%20.20g",EdgeWeight) << "\n";
110          inWeight += EdgeWeight;
111          inCount++;
112        }
113      }
114      double outWeight = 0;
115      int outCount = 0;
116      std::set<const BType*> ProcessedSuccs;
117      for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
118            bbi != bbe; ++bbi ) {
119        if (ProcessedSuccs.insert(*bbi).second) {
120          typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(BB,*bbi);
121          double EdgeWeight = PI->getEdgeWeight(E);
122          if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
123          dbgs() << "calculated out-edge " << E << ": "
124                 << format("%20.20g",EdgeWeight) << "\n";
125          outWeight += EdgeWeight;
126          outCount++;
127        }
128      }
129      dbgs() << "Block " << BB->getName()                   << " in "
130             << BB->getParent()->getName()                  << ":"
131             << "BBWeight="  << format("%20.20g",BBWeight)  << ","
132             << "inWeight="  << format("%20.20g",inWeight)  << ","
133             << "inCount="   << inCount                     << ","
134             << "outWeight=" << format("%20.20g",outWeight) << ","
135             << "outCount"   << outCount                    << "\n";
136  
137      // mark as visited and recurse into subnodes
138      BBisPrinted.insert(BB);
139      for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
140            bbi != bbe; ++bbi ) {
141        printDebugInfo(*bbi);
142      }
143    }
144  
145    template<class FType, class BType>
debugEntry(DetailedBlockInfo * DI)146    void ProfileVerifierPassT<FType, BType>::debugEntry (DetailedBlockInfo *DI) {
147      dbgs() << "TROUBLE: Block " << DI->BB->getName()          << " in "
148             << DI->BB->getParent()->getName()                  << ":"
149             << "BBWeight="  << format("%20.20g",DI->BBWeight)  << ","
150             << "inWeight="  << format("%20.20g",DI->inWeight)  << ","
151             << "inCount="   << DI->inCount                     << ","
152             << "outWeight=" << format("%20.20g",DI->outWeight) << ","
153             << "outCount="  << DI->outCount                    << "\n";
154      if (!PrintedDebugTree) {
155        PrintedDebugTree = true;
156        printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
157      }
158    }
159  
160    // This compares A and B for equality.
Equals(double A,double B)161    static bool Equals(double A, double B) {
162      return A == B;
163    }
164  
165    // This checks if the function "exit" is reachable from an given function
166    // via calls, this is necessary to check if a profile is valid despite the
167    // counts not fitting exactly.
168    template<class FType, class BType>
exitReachable(const FType * F)169    bool ProfileVerifierPassT<FType, BType>::exitReachable(const FType *F) {
170      if (!F) return false;
171  
172      if (FisVisited.count(F)) return false;
173  
174      FType *Exit = F->getParent()->getFunction("exit");
175      if (Exit == F) {
176        return true;
177      }
178  
179      FisVisited.insert(F);
180      bool exits = false;
181      for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
182        if (const CallInst *CI = dyn_cast<CallInst>(&*I)) {
183          FType *F = CI->getCalledFunction();
184          if (F) {
185            exits |= exitReachable(F);
186          } else {
187            // This is a call to a pointer, all bets are off...
188            exits = true;
189          }
190          if (exits) break;
191        }
192      }
193      return exits;
194    }
195  
196    #define ASSERTMESSAGE(M) \
197      { dbgs() << "ASSERT:" << (M) << "\n"; \
198        if (!DisableAssertions) assert(0 && (M)); }
199  
200    template<class FType, class BType>
ReadOrAssert(typename ProfileInfoT<FType,BType>::Edge E)201    double ProfileVerifierPassT<FType, BType>::ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge E) {
202      double EdgeWeight = PI->getEdgeWeight(E);
203      if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) {
204        dbgs() << "Edge " << E << " in Function "
205               << ProfileInfoT<FType, BType>::getFunction(E)->getName() << ": ";
206        ASSERTMESSAGE("Edge has missing value");
207        return 0;
208      } else {
209        if (EdgeWeight < 0) {
210          dbgs() << "Edge " << E << " in Function "
211                 << ProfileInfoT<FType, BType>::getFunction(E)->getName() << ": ";
212          ASSERTMESSAGE("Edge has negative value");
213        }
214        return EdgeWeight;
215      }
216    }
217  
218    template<class FType, class BType>
CheckValue(bool Error,const char * Message,DetailedBlockInfo * DI)219    void ProfileVerifierPassT<FType, BType>::CheckValue(bool Error,
220                                                        const char *Message,
221                                                        DetailedBlockInfo *DI) {
222      if (Error) {
223        DEBUG(debugEntry(DI));
224        dbgs() << "Block " << DI->BB->getName() << " in Function "
225               << DI->BB->getParent()->getName() << ": ";
226        ASSERTMESSAGE(Message);
227      }
228      return;
229    }
230  
231    // This calculates the Information for a block and then recurses into the
232    // successors.
233    template<class FType, class BType>
recurseBasicBlock(const BType * BB)234    void ProfileVerifierPassT<FType, BType>::recurseBasicBlock(const BType *BB) {
235  
236      // Break the recursion by remembering all visited blocks.
237      if (BBisVisited.find(BB) != BBisVisited.end()) return;
238  
239      // Use a data structure to store all the information, this can then be handed
240      // to debug printers.
241      DetailedBlockInfo DI;
242      DI.BB = BB;
243      DI.outCount = DI.inCount = 0;
244      DI.inWeight = DI.outWeight = 0;
245  
246      // Read predecessors.
247      std::set<const BType*> ProcessedPreds;
248      const_pred_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
249      // If there are none, check for (0,BB) edge.
250      if (bpi == bpe) {
251        DI.inWeight += ReadOrAssert(PI->getEdge(0,BB));
252        DI.inCount++;
253      }
254      for (;bpi != bpe; ++bpi) {
255        if (ProcessedPreds.insert(*bpi).second) {
256          DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB));
257          DI.inCount++;
258        }
259      }
260  
261      // Read successors.
262      std::set<const BType*> ProcessedSuccs;
263      succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
264      // If there is an (0,BB) edge, consider it too. (This is done not only when
265      // there are no successors, but every time; not every function contains
266      // return blocks with no successors (think loop latch as return block)).
267      double w = PI->getEdgeWeight(PI->getEdge(BB,0));
268      if (w != ProfileInfoT<FType, BType>::MissingValue) {
269        DI.outWeight += w;
270        DI.outCount++;
271      }
272      for (;bbi != bbe; ++bbi) {
273        if (ProcessedSuccs.insert(*bbi).second) {
274          DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
275          DI.outCount++;
276        }
277      }
278  
279      // Read block weight.
280      DI.BBWeight = PI->getExecutionCount(BB);
281      CheckValue(DI.BBWeight == ProfileInfoT<FType, BType>::MissingValue,
282                 "BasicBlock has missing value", &DI);
283      CheckValue(DI.BBWeight < 0,
284                 "BasicBlock has negative value", &DI);
285  
286      // Check if this block is a setjmp target.
287      bool isSetJmpTarget = false;
288      if (DI.outWeight > DI.inWeight) {
289        for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
290             i != ie; ++i) {
291          if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
292            FType *F = CI->getCalledFunction();
293            if (F && (F->getName() == "_setjmp")) {
294              isSetJmpTarget = true; break;
295            }
296          }
297        }
298      }
299      // Check if this block is eventually reaching exit.
300      bool isExitReachable = false;
301      if (DI.inWeight > DI.outWeight) {
302        for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
303             i != ie; ++i) {
304          if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
305            FType *F = CI->getCalledFunction();
306            if (F) {
307              FisVisited.clear();
308              isExitReachable |= exitReachable(F);
309            } else {
310              // This is a call to a pointer, all bets are off...
311              isExitReachable = true;
312            }
313            if (isExitReachable) break;
314          }
315        }
316      }
317  
318      if (DI.inCount > 0 && DI.outCount == 0) {
319         // If this is a block with no successors.
320        if (!isSetJmpTarget) {
321          CheckValue(!Equals(DI.inWeight,DI.BBWeight),
322                     "inWeight and BBWeight do not match", &DI);
323        }
324      } else if (DI.inCount == 0 && DI.outCount > 0) {
325        // If this is a block with no predecessors.
326        if (!isExitReachable)
327          CheckValue(!Equals(DI.BBWeight,DI.outWeight),
328                     "BBWeight and outWeight do not match", &DI);
329      } else {
330        // If this block has successors and predecessors.
331        if (DI.inWeight > DI.outWeight && !isExitReachable)
332          CheckValue(!Equals(DI.inWeight,DI.outWeight),
333                     "inWeight and outWeight do not match", &DI);
334        if (DI.inWeight < DI.outWeight && !isSetJmpTarget)
335          CheckValue(!Equals(DI.inWeight,DI.outWeight),
336                     "inWeight and outWeight do not match", &DI);
337      }
338  
339  
340      // Mark this block as visited, rescurse into successors.
341      BBisVisited.insert(BB);
342      for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
343            bbi != bbe; ++bbi ) {
344        recurseBasicBlock(*bbi);
345      }
346    }
347  
348    template<class FType, class BType>
runOnFunction(FType & F)349    bool ProfileVerifierPassT<FType, BType>::runOnFunction(FType &F) {
350      PI = getAnalysisIfAvailable<ProfileInfoT<FType, BType> >();
351      if (!PI)
352        ASSERTMESSAGE("No ProfileInfo available");
353  
354      // Prepare global variables.
355      PrintedDebugTree = false;
356      BBisVisited.clear();
357  
358      // Fetch entry block and recurse into it.
359      const BType *entry = &F.getEntryBlock();
360      recurseBasicBlock(entry);
361  
362      if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry))
363        ASSERTMESSAGE("Function count and entry block count do not match");
364  
365      return false;
366    }
367  
368    template<class FType, class BType>
369    char ProfileVerifierPassT<FType, BType>::ID = 0;
370  }
371  
372  INITIALIZE_PASS_BEGIN(ProfileVerifierPass, "profile-verifier",
373                  "Verify profiling information", false, true)
374  INITIALIZE_AG_DEPENDENCY(ProfileInfo)
375  INITIALIZE_PASS_END(ProfileVerifierPass, "profile-verifier",
376                  "Verify profiling information", false, true)
377  
378  namespace llvm {
createProfileVerifierPass()379    FunctionPass *createProfileVerifierPass() {
380      return new ProfileVerifierPass(ProfileVerifierDisableAssertions);
381    }
382  }
383  
384