[llvm-commits] [llvm] r80666 - in /llvm/trunk: include/llvm/Analysis/Passes.h include/llvm/LinkAllPasses.h lib/Analysis/ProfileVerifierPass.cpp

Andreas Neustifter astifter at gmx.at
Tue Sep 1 01:48:44 PDT 2009


Author: astifter
Date: Tue Sep  1 03:48:42 2009
New Revision: 80666

URL: http://llvm.org/viewvc/llvm-project?rev=80666&view=rev
Log:
Preparation for Optimal Edge Profiling:
This adds a pass to verify the current profile against the flow conditions.
This is very helpful when later on trying to perserve the profiling information
during all passes.

Added:
    llvm/trunk/lib/Analysis/ProfileVerifierPass.cpp
Modified:
    llvm/trunk/include/llvm/Analysis/Passes.h
    llvm/trunk/include/llvm/LinkAllPasses.h

Modified: llvm/trunk/include/llvm/Analysis/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=80666&r1=80665&r2=80666&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/Passes.h (original)
+++ llvm/trunk/include/llvm/Analysis/Passes.h Tue Sep  1 03:48:42 2009
@@ -109,6 +109,12 @@
 
   //===--------------------------------------------------------------------===//
   //
+  // createProfileVerifierPass - This pass verifies profiling information.
+  //
+  FunctionPass *createProfileVerifierPass();
+
+  //===--------------------------------------------------------------------===//
+  //
   // createDSAAPass - This pass implements simple context sensitive alias
   // analysis.
   //

Modified: llvm/trunk/include/llvm/LinkAllPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=80666&r1=80665&r2=80666&view=diff

==============================================================================
--- llvm/trunk/include/llvm/LinkAllPasses.h (original)
+++ llvm/trunk/include/llvm/LinkAllPasses.h Tue Sep  1 03:48:42 2009
@@ -94,6 +94,7 @@
       (void) llvm::createNoAAPass();
       (void) llvm::createNoProfileInfoPass();
       (void) llvm::createProfileEstimatorPass();
+      (void) llvm::createProfileVerifierPass();
       (void) llvm::createProfileLoaderPass();
       (void) llvm::createPromoteMemoryToRegisterPass();
       (void) llvm::createDemoteRegisterToMemoryPass();

Added: llvm/trunk/lib/Analysis/ProfileVerifierPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ProfileVerifierPass.cpp?rev=80666&view=auto

==============================================================================
--- llvm/trunk/lib/Analysis/ProfileVerifierPass.cpp (added)
+++ llvm/trunk/lib/Analysis/ProfileVerifierPass.cpp Tue Sep  1 03:48:42 2009
@@ -0,0 +1,228 @@
+//===- ProfileVerifierPass.cpp - LLVM Pass to estimate profile info -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a pass that checks profiling information for 
+// plausibility.
+//
+//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "profile-verifier"
+#include "llvm/Pass.h"
+#include "llvm/Analysis/ProfileInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
+#include <set>
+using namespace llvm;
+
+static bool DisableAssertions = false;
+static cl::opt<bool,true>
+ProfileVerifierDisableAssertions("profile-verifier-noassert",
+    cl::location(DisableAssertions), cl::desc("Disable assertions"));
+bool PrintedDebugTree = false;
+
+namespace {
+  class VISIBILITY_HIDDEN ProfileVerifierPass : public FunctionPass {
+    ProfileInfo *PI;
+    std::set<const BasicBlock*> BBisVisited;
+#ifndef NDEBUG
+    std::set<const BasicBlock*> BBisPrinted;
+    void debugEntry(const BasicBlock* BB, double w, double inw, int inc,
+                    double outw, int outc, double d);
+    void printDebugInfo(const BasicBlock *BB);
+#endif
+  public:
+    static char ID; // Class identification, replacement for typeinfo
+
+    explicit ProfileVerifierPass () : FunctionPass(&ID) {
+      DisableAssertions = ProfileVerifierDisableAssertions;
+    }
+
+    void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.setPreservesAll();
+      AU.addRequired<ProfileInfo>();
+    }
+
+    const char *getPassName() const {
+      return "Profiling information verifier";
+    }
+
+    /// run - Verify the profile information.
+    bool runOnFunction(Function &F);
+    void recurseBasicBlock(const BasicBlock *BB);
+  };
+}  // End of anonymous namespace
+
+char ProfileVerifierPass::ID = 0;
+static RegisterPass<ProfileVerifierPass>
+X("profile-verifier", "Verify profiling information", false, true);
+
+namespace llvm {
+  FunctionPass *createProfileVerifierPass() {
+    return new ProfileVerifierPass(); 
+  }
+}
+
+#ifndef NDEBUG
+void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
+
+  if (BBisPrinted.find(BB) != BBisPrinted.end()) return;
+
+  double BBWeight = PI->getExecutionCount(BB);
+  if (BBWeight == ProfileInfo::MissingValue) { BBWeight = 0; }
+  double inWeight = 0;
+  int inCount = 0;
+  std::set<const BasicBlock*> ProcessedPreds;
+  for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
+        bbi != bbe; ++bbi ) {
+    if (ProcessedPreds.insert(*bbi).second) {
+      double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB));
+      if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
+      DEBUG(errs()<<"calculated in-edge ("<<(*bbi)->getNameStr()<<","<<BB->getNameStr()
+          <<"): "<<EdgeWeight<<"\n");
+      inWeight += EdgeWeight;
+      inCount++;
+    }
+  }
+  double outWeight = 0;
+  int outCount = 0;
+  std::set<const BasicBlock*> ProcessedSuccs;
+  for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
+        bbi != bbe; ++bbi ) {
+    if (ProcessedSuccs.insert(*bbi).second) {
+      double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi));
+      if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
+      DEBUG(errs()<<"calculated out-edge ("<<BB->getNameStr()<<","<<(*bbi)->getNameStr()
+          <<"): "<<EdgeWeight<<"\n");
+      outWeight += EdgeWeight;
+      outCount++;
+    }
+  }
+  DEBUG(errs()<<"Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr()
+      <<",BBWeight="<<BBWeight<<",inWeight="<<inWeight<<",inCount="<<inCount
+      <<",outWeight="<<outWeight<<",outCount"<<outCount<<"\n");
+
+  // mark as visited and recurse into subnodes
+  BBisPrinted.insert(BB);
+  for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); 
+        bbi != bbe; ++bbi ) {
+    printDebugInfo(*bbi);
+  }
+}
+
+void ProfileVerifierPass::debugEntry (const BasicBlock* BB, double w, 
+                                      double inw,  int inc, double outw, int
+                                      outc, double d) {
+  DEBUG(errs()<<"TROUBLE: Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr()
+      <<",BBWeight="<<w<<",inWeight="<<inw<<",inCount="<<inc<<",outWeight="
+      <<outw<<",outCount"<<outc<<"\n");
+  DEBUG(errs()<<"DELTA:"<<d<<"\n");
+  if (!PrintedDebugTree) {
+    PrintedDebugTree = true;
+    printDebugInfo(&(BB->getParent()->getEntryBlock()));
+  }
+}
+#endif
+
+// compare with relative error
+static bool dcmp(double A, double B) { 
+  double maxRelativeError = 0.0000001;
+  if (A == B)
+    return true;
+  double relativeError;
+  if (fabs(B) > fabs(A)) 
+    relativeError = fabs((A - B) / B);
+  else 
+    relativeError = fabs((A - B) / A);
+  if (relativeError <= maxRelativeError) return true; 
+  return false; 
+}
+
+#define CHECK(C,M) \
+if (C) { \
+  if (DisableAssertions) { errs()<<(M)<<"\n"; } else { assert((!(C)) && (M)); } \
+}
+
+#define CHECKDEBUG(C,M,D) \
+if (C) { \
+  DEBUG(debugEntry(BB, BBWeight, inWeight,  inCount, \
+                                 outWeight, outCount, (D))); \
+  if (DisableAssertions) { errs()<<(M)<<"\n"; } else { assert((!(C)) && (M)); } \
+}
+
+void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
+
+  if (BBisVisited.find(BB) != BBisVisited.end()) return;
+
+  double inWeight = 0;
+  int inCount = 0;
+  std::set<const BasicBlock*> ProcessedPreds;
+  for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
+        bbi != bbe; ++bbi ) {
+    if (ProcessedPreds.insert(*bbi).second) {
+      double EdgeWeight = PI->getEdgeWeight(PI->getEdge(*bbi,BB));
+      CHECK(EdgeWeight == ProfileInfo::MissingValue,
+            "ASSERT:Edge has missing value");
+      inWeight += EdgeWeight; inCount++;
+    }
+  }
+
+  double outWeight = 0;
+  int outCount = 0;
+  std::set<const BasicBlock*> ProcessedSuccs;
+  for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
+        bbi != bbe; ++bbi ) {
+    if (ProcessedSuccs.insert(*bbi).second) {
+      double EdgeWeight = PI->getEdgeWeight(PI->getEdge(BB,*bbi));
+      CHECK(EdgeWeight == ProfileInfo::MissingValue,
+            "ASSERT:Edge has missing value");
+      outWeight += EdgeWeight; outCount++;
+    }
+  }
+
+  double BBWeight = PI->getExecutionCount(BB);
+  CHECKDEBUG(BBWeight == ProfileInfo::MissingValue,
+             "ASSERT:BasicBlock has missing value",-1);
+
+  if (inCount > 0) {
+    CHECKDEBUG(!dcmp(inWeight,BBWeight),
+        "ASSERT:inWeight and BBWeight do not match",inWeight-BBWeight);
+  }
+  if (outCount > 0) {
+    CHECKDEBUG(!dcmp(outWeight,BBWeight),
+        "ASSERT:outWeight and BBWeight do not match",outWeight-BBWeight);
+  }
+
+  // mark as visited and recurse into subnodes
+  BBisVisited.insert(BB);
+  for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); 
+        bbi != bbe; ++bbi ) {
+    recurseBasicBlock(*bbi);
+  }
+}
+
+bool ProfileVerifierPass::runOnFunction(Function &F) {
+  PI = &getAnalysis<ProfileInfo>();
+
+  if (PI->getExecutionCount(&F) == ProfileInfo::MissingValue) {
+    DEBUG(errs()<<"Function "<<F.getNameStr()<<" has no profile\n");
+    return false;
+  }
+
+  PrintedDebugTree = false;
+  BBisVisited.clear();
+
+  const BasicBlock *entry = &F.getEntryBlock();
+  recurseBasicBlock(entry);
+
+  if (!DisableAssertions)
+    assert((PI->getExecutionCount(&F)==PI->getExecutionCount(entry)) &&
+           "Function count and entry block count do not match");
+  return false;
+}





More information about the llvm-commits mailing list