[polly] r330466 - Allow arbitrary function calls for debugging purposes.

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 20 11:55:44 PDT 2018


Author: meinersbur
Date: Fri Apr 20 11:55:44 2018
New Revision: 330466

URL: http://llvm.org/viewvc/llvm-project?rev=330466&view=rev
Log:
Allow arbitrary function calls for debugging purposes.

Add the switch -polly-debug-func to define the name of a debug
function. This function is ignored for any validity check.

Its purpose is to allow to observe a value after transformation by a
SCoP, and to follow which statements are executed in which order. For
instance, consider the following code:

    static void dbg_printf(int sum, int i) {
      fprintf(stderr, "The value of sum is %d, i=%d\n", sum, i);
      fflush(stderr);
    }

    void func(int n) {
      int sum = 0;
      for (int i = 0; i < 16; i+=1) {
        sum += i;
        dbg_printf(sum, i);
      }
    }

Executing this after Polly's codegen with -polly-debug-func=dbg_printf
reveals the new execution order and the assumed values at that point of
execution.

Differential Revision: https://reviews.llvm.org/D45728

Added:
    polly/trunk/test/ScopInfo/debug_call.ll
Modified:
    polly/trunk/include/polly/Support/ScopHelper.h
    polly/trunk/lib/Analysis/ScopBuilder.cpp
    polly/trunk/lib/Analysis/ScopDetection.cpp
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/Support/ScopHelper.cpp

Modified: polly/trunk/include/polly/Support/ScopHelper.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/ScopHelper.h?rev=330466&r1=330465&r2=330466&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/ScopHelper.h (original)
+++ polly/trunk/include/polly/Support/ScopHelper.h Fri Apr 20 11:55:44 2018
@@ -36,6 +36,7 @@ class GetElementPtrInst;
 
 namespace polly {
 class Scop;
+class ScopStmt;
 
 /// Type to remap values.
 using ValueMapT = llvm::DenseMap<llvm::AssertingVH<llvm::Value>,
@@ -458,5 +459,24 @@ llvm::Loop *getFirstNonBoxedLoopFor(llvm
 // @param BoxedLoops    Set of Boxed Loops we get from the SCoP.
 llvm::Loop *getFirstNonBoxedLoopFor(llvm::BasicBlock *BB, llvm::LoopInfo &LI,
                                     const BoxedLoopsSetTy &BoxedLoops);
+
+/// Is the given instruction a call to a debug function?
+///
+/// A debug function can be used to insert output in Polly-optimized code which
+/// normally does not allow function calls with side-effects. For instance, a
+/// printf can be inserted to check whether a value still has the expected value
+/// after Polly generated code:
+///
+///     int sum = 0;
+///     for (int i = 0; i < 16; i+=1) {
+///       sum += i;
+///       printf("The value of sum at i=%d is %d\n", sum, i);
+///     }
+bool isDebugCall(llvm::Instruction *Inst);
+
+/// Does the statement contain a call to a debug function?
+///
+/// Such a statement must not be removed, even if has no side-effects.
+bool hasDebugCall(ScopStmt *Stmt);
 } // namespace polly
 #endif

Modified: polly/trunk/lib/Analysis/ScopBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopBuilder.cpp?rev=330466&r1=330465&r2=330466&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopBuilder.cpp (original)
+++ polly/trunk/lib/Analysis/ScopBuilder.cpp Fri Apr 20 11:55:44 2018
@@ -559,7 +559,7 @@ bool ScopBuilder::buildAccessCallInst(Me
   if (CI == nullptr)
     return false;
 
-  if (CI->doesNotAccessMemory() || isIgnoredIntrinsic(CI))
+  if (CI->doesNotAccessMemory() || isIgnoredIntrinsic(CI) || isDebugCall(CI))
     return true;
 
   bool ReadOnly = false;

Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=330466&r1=330465&r2=330466&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Fri Apr 20 11:55:44 2018
@@ -703,6 +703,12 @@ bool ScopDetection::isValidCallInst(Call
   if (CalledFunction == nullptr)
     return false;
 
+  if (isDebugCall(&CI)) {
+    DEBUG(dbgs() << "Allow call to debug function: "
+                 << CalledFunction->getName() << '\n');
+    return true;
+  }
+
   if (AllowModrefCall) {
     switch (AA.getModRefBehavior(CalledFunction)) {
     case FMRB_UnknownModRefBehavior:

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=330466&r1=330465&r2=330466&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Fri Apr 20 11:55:44 2018
@@ -3585,6 +3585,10 @@ void Scop::removeStmtNotInDomainMap() {
 
 void Scop::simplifySCoP(bool AfterHoisting) {
   auto ShouldDelete = [AfterHoisting](ScopStmt &Stmt) -> bool {
+    // Never delete statements that contain calls to debug functions.
+    if (hasDebugCall(&Stmt))
+      return false;
+
     bool RemoveStmt = Stmt.isEmpty();
 
     // Remove read only statements only after invariant load hoisting.

Modified: polly/trunk/lib/Support/ScopHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/ScopHelper.cpp?rev=330466&r1=330465&r2=330466&view=diff
==============================================================================
--- polly/trunk/lib/Support/ScopHelper.cpp (original)
+++ polly/trunk/lib/Support/ScopHelper.cpp Fri Apr 20 11:55:44 2018
@@ -35,6 +35,13 @@ static cl::opt<bool> PollyAllowErrorBloc
     cl::desc("Allow to speculate on the execution of 'error blocks'."),
     cl::Hidden, cl::init(true), cl::ZeroOrMore, cl::cat(PollyCategory));
 
+static cl::list<std::string> DebugFunctions(
+    "polly-debug-func",
+    cl::desc("Allow calls to the specified functions in SCoPs even if their "
+             "side-effects are unknown. This can be used to do debug output in "
+             "Polly-transformed code."),
+    cl::Hidden, cl::ZeroOrMore, cl::CommaSeparated, cl::cat(PollyCategory));
+
 // Ensures that there is just one predecessor to the entry node from outside the
 // region.
 // The identity of the region entry node is preserved.
@@ -401,6 +408,9 @@ bool polly::isErrorBlock(BasicBlock &BB,
 
   for (Instruction &Inst : BB)
     if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
+      if (isDebugCall(CI))
+        continue;
+
       if (isIgnoredIntrinsic(CI))
         continue;
 
@@ -586,3 +596,45 @@ llvm::Loop *polly::getFirstNonBoxedLoopF
   Loop *L = LI.getLoopFor(BB);
   return getFirstNonBoxedLoopFor(L, LI, BoxedLoops);
 }
+
+bool polly::isDebugCall(Instruction *Inst) {
+  auto *CI = dyn_cast<CallInst>(Inst);
+  if (!CI)
+    return false;
+
+  Function *CF = CI->getCalledFunction();
+  if (!CF)
+    return false;
+
+  return std::find(DebugFunctions.begin(), DebugFunctions.end(),
+                   CF->getName()) != DebugFunctions.end();
+}
+
+static bool hasDebugCall(BasicBlock *BB) {
+  for (Instruction &Inst : *BB) {
+    if (isDebugCall(&Inst))
+      return true;
+  }
+  return false;
+}
+
+bool polly::hasDebugCall(ScopStmt *Stmt) {
+  // Quick skip if no debug functions have been defined.
+  if (DebugFunctions.empty())
+    return false;
+
+  if (!Stmt)
+    return false;
+
+  for (Instruction *Inst : Stmt->getInstructions())
+    if (isDebugCall(Inst))
+      return true;
+
+  if (Stmt->isRegionStmt()) {
+    for (BasicBlock *RBB : Stmt->getRegion()->blocks())
+      if (RBB != Stmt->getEntryBlock() && ::hasDebugCall(RBB))
+        return true;
+  }
+
+  return false;
+}

Added: polly/trunk/test/ScopInfo/debug_call.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/debug_call.ll?rev=330466&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/debug_call.ll (added)
+++ polly/trunk/test/ScopInfo/debug_call.ll Fri Apr 20 11:55:44 2018
@@ -0,0 +1,37 @@
+; RUN: opt %loadPolly -polly-debug-func=dbg_printf -polly-scops -analyze < %s | FileCheck %s -match-full-lines
+;
+; Check that the call to dbg_printf is accepted as a debug-function.
+;
+declare void @dbg_printf(i8*, ...)
+
+define void @func(i32 %n) {
+entry:
+  br label %for
+
+for:
+  %j = phi i32 [0, %entry], [%j.inc, %inc]
+  %j.cmp = icmp slt i32 %j, %n
+  br i1 %j.cmp, label %body, label %exit
+
+    body:
+      call void (i8*, ...) @dbg_printf(i8* null, i32 %j)
+      br label %inc
+
+inc:
+  %j.inc = add nuw nsw i32 %j, 1
+  br label %for
+
+exit:
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK:      Statements {
+; CHECK-NEXT:     Stmt_body
+; CHECK-NEXT:         Domain :=
+; CHECK-NEXT:             [n] -> { Stmt_body[i0] : 0 <= i0 < n };
+; CHECK-NEXT:         Schedule :=
+; CHECK-NEXT:             [n] -> { Stmt_body[i0] -> [i0] };
+; CHECK-NEXT: }




More information about the llvm-commits mailing list