ScopDetect: Only track detection failures if actually needed.
authorTobias Grosser <tobias@grosser.es>
Thu, 25 Jul 2013 03:02:29 +0000 (03:02 +0000)
committerTobias Grosser <tobias@grosser.es>
Thu, 25 Jul 2013 03:02:29 +0000 (03:02 +0000)
String operations resulted by raw_string_ostream in the INVALID macro can lead
to significant compile-time overhead when compiling large size source code.
This is because raw_string_ostream relies on TypeFinder class, whose
compile-time cost increases as the size of the module increases. This patch
targets to ensure that it only track detection failures if actually needed.
In this way, we can avoid expensive string operations in normal execution.

With this patch file, the relative compile-time cost of Polly-detect pass does
not increase even when compiling very large size source code.

Contributed-by: Star Tan <tanmx_star@yeah.net>
llvm-svn: 187102

polly/include/polly/ScopDetection.h
polly/lib/Analysis/ScopDetection.cpp
polly/lib/RegisterPasses.cpp

index 6ee48ee..dd5b630 100755 (executable)
@@ -72,6 +72,8 @@ class Value;
 namespace polly {
 typedef std::set<const SCEV *> ParamSetType;
 
+extern bool PollyTrackFailures;
+
 //===----------------------------------------------------------------------===//
 /// @brief Pass to detect the maximal static control parts (Scops) of a
 /// function.
@@ -145,6 +147,13 @@ class ScopDetection : public FunctionPass {
   /// @return True if the call instruction is valid, false otherwise.
   static bool isValidCallInst(CallInst &CI);
 
+  /// @brief Format the invalid alias message.
+  ///
+  /// @param AS The alias set.
+  ///
+  /// @return The failure message why the alias is invalid.
+  std::string formatInvalidAlias(AliasSet &AS) const;
+
   /// @brief Check if a memory access can be part of a Scop.
   ///
   /// @param Inst The instruction accessing the memory.
index 9b2a9a8..d06b5fc 100644 (file)
@@ -98,6 +98,14 @@ AllowNonAffine("polly-allow-nonaffine",
                cl::desc("Allow non affine access functions in arrays"),
                cl::Hidden, cl::init(false), cl::cat(PollyCategory));
 
+static cl::opt<bool, true>
+TrackFailures("polly-detect-track-failures",
+              cl::desc("Track failure strings in detecting scop regions"),
+              cl::location(PollyTrackFailures), cl::Hidden, cl::init(false),
+              cl::cat(PollyCategory));
+
+bool polly::PollyTrackFailures = false;
+
 //===----------------------------------------------------------------------===//
 // Statistics.
 
@@ -108,11 +116,13 @@ STATISTIC(ValidRegion, "Number of regions that a valid part of Scop");
 
 #define INVALID(NAME, MESSAGE)                                                 \
   do {                                                                         \
-    std::string Buf;                                                           \
-    raw_string_ostream fmt(Buf);                                               \
-    fmt << MESSAGE;                                                            \
-    fmt.flush();                                                               \
-    LastFailure = Buf;                                                         \
+    if (PollyTrackFailures) {                                                  \
+      std::string Buf;                                                         \
+      raw_string_ostream fmt(Buf);                                             \
+      fmt << MESSAGE;                                                          \
+      fmt.flush();                                                             \
+      LastFailure = Buf;                                                       \
+    }                                                                          \
     DEBUG(dbgs() << MESSAGE);                                                  \
     DEBUG(dbgs() << "\n");                                                     \
     assert(!Context.Verifying &&#NAME);                                        \
@@ -122,11 +132,13 @@ STATISTIC(ValidRegion, "Number of regions that a valid part of Scop");
 
 #define INVALID_NOVERIFY(NAME, MESSAGE)                                        \
   do {                                                                         \
-    std::string Buf;                                                           \
-    raw_string_ostream fmt(Buf);                                               \
-    fmt << MESSAGE;                                                            \
-    fmt.flush();                                                               \
-    LastFailure = Buf;                                                         \
+    if (PollyTrackFailures) {                                                  \
+      std::string Buf;                                                         \
+      raw_string_ostream fmt(Buf);                                             \
+      fmt << MESSAGE;                                                          \
+      fmt.flush();                                                             \
+      LastFailure = Buf;                                                       \
+    }                                                                          \
     DEBUG(dbgs() << MESSAGE);                                                  \
     DEBUG(dbgs() << "\n");                                                     \
     /* DISABLED: assert(!Context.Verifying && #NAME); */                       \
@@ -256,6 +268,40 @@ bool ScopDetection::isValidCallInst(CallInst &CI) {
   return false;
 }
 
+std::string ScopDetection::formatInvalidAlias(AliasSet &AS) const {
+  std::string Message;
+  raw_string_ostream OS(Message);
+
+  OS << "Possible aliasing: ";
+
+  std::vector<Value *> Pointers;
+
+  for (AliasSet::iterator AI = AS.begin(), AE = AS.end(); AI != AE; ++AI)
+    Pointers.push_back(AI.getPointer());
+
+  std::sort(Pointers.begin(), Pointers.end());
+
+  for (std::vector<Value *>::iterator PI = Pointers.begin(),
+                                      PE = Pointers.end();
+       ;) {
+    Value *V = *PI;
+
+    if (V->getName().size() == 0)
+      OS << "\"" << *V << "\"";
+    else
+      OS << "\"" << V->getName() << "\"";
+
+    ++PI;
+
+    if (PI != PE)
+      OS << ", ";
+    else
+      break;
+  }
+
+  return OS.str();
+}
+
 bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
                                         DetectionContext &Context) const {
   Value *Ptr = getPointerOperand(Inst);
@@ -310,37 +356,7 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
   // not proof this without -basicaa we would fail. We disable this check to
   // not cause irrelevant verification failures.
   if (!AS.isMustAlias()) {
-    std::string Message;
-    raw_string_ostream OS(Message);
-
-    OS << "Possible aliasing: ";
-
-    std::vector<Value *> Pointers;
-
-    for (AliasSet::iterator AI = AS.begin(), AE = AS.end(); AI != AE; ++AI)
-      Pointers.push_back(AI.getPointer());
-
-    std::sort(Pointers.begin(), Pointers.end());
-
-    for (std::vector<Value *>::iterator PI = Pointers.begin(),
-                                        PE = Pointers.end();
-         ;) {
-      Value *V = *PI;
-
-      if (V->getName().size() == 0)
-        OS << "\"" << *V << "\"";
-      else
-        OS << "\"" << V->getName() << "\"";
-
-      ++PI;
-
-      if (PI != PE)
-        OS << ", ";
-      else
-        break;
-    }
-
-    INVALID_NOVERIFY(Alias, OS.str());
+    INVALID_NOVERIFY(Alias, formatInvalidAlias(AS));
     return false;
   }
 
index 7fc0960..26a138e 100644 (file)
@@ -317,6 +317,9 @@ registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
   if (Builder.OptLevel == 0)
     return;
 
+  if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)
+    PollyTrackFailures = true;
+
   if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||
       ExportJScop || ImportJScop)
     PollyEnabled = true;