[polly] r211769 - Support the new DiagnosticRemarks

Andreas Simbuerger simbuerg at fim.uni-passau.de
Thu Jun 26 03:06:41 PDT 2014


Author: simbuerg
Date: Thu Jun 26 05:06:40 2014
New Revision: 211769

URL: http://llvm.org/viewvc/llvm-project?rev=211769&view=rev
Log:
Support the new DiagnosticRemarks

Add support for generating optimization remarks after completing the
detection of Scops.
The goal is to provide end-users with useful hints about opportunities that
help to increase the size of the detected Scops in their code.

By default the remark is unspecified and the debug location is empty. Future
patches have to expand on the messages generated.

This patch brings a simple test case for ReportFuncCall to demonstrate the
feature.

Reports all missed opportunities to increase the size/number of valid
Scops:
 clang <...> -Rpass-missed="polly-detect" <...>
 opt <...> -pass-remarks-missed="polly-detect" <...>

Reports beginning and end of all valid Scops:
 clang <...> -Rpass="polly-detect" <...>
 opt <...> -pass-remarks="polly-detect" <...>

Differential Revision: http://reviews.llvm.org/D4171

Added:
    polly/trunk/test/ScopDetectionDiagnostics/
    polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll
Modified:
    polly/trunk/include/polly/ScopDetection.h
    polly/trunk/include/polly/ScopDetectionDiagnostic.h
    polly/trunk/lib/Analysis/ScopDetection.cpp
    polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp

Modified: polly/trunk/include/polly/ScopDetection.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopDetection.h?rev=211769&r1=211768&r2=211769&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetection.h (original)
+++ polly/trunk/include/polly/ScopDetection.h Thu Jun 26 05:06:40 2014
@@ -326,6 +326,23 @@ public:
   const_reject_iterator reject_end() const { return RejectLogs.end(); }
   //@}
 
+  /// @brief Emit rejection remarks for all smallest invalid regions.
+  ///
+  /// @param F The function to emit remarks for.
+  /// @param R The region to start the region tree traversal for.
+  void emitMissedRemarksForLeaves(const Function &F, const Region *R);
+
+  /// @brief Emit rejection remarks for the parent regions of all valid regions.
+  ///
+  /// Emitting rejection remarks for the parent regions of all valid regions
+  /// may give the end-user clues about how to increase the size of the
+  /// detected Scops.
+  ///
+  /// @param F The function to emit remarks for.
+  /// @param ValidRegions The set of valid regions to emit remarks for.
+  void emitMissedRemarksForValidRegions(const Function &F,
+                                        const RegionSet &ValidRegions);
+
   /// @brief Mark the function as invalid so we will not extract any scop from
   ///        the function.
   ///

Modified: polly/trunk/include/polly/ScopDetectionDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopDetectionDiagnostic.h?rev=211769&r1=211768&r2=211769&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetectionDiagnostic.h (original)
+++ polly/trunk/include/polly/ScopDetectionDiagnostic.h Thu Jun 26 05:06:40 2014
@@ -52,6 +52,20 @@ namespace polly {
 void getDebugLocation(const Region *R, unsigned &LineBegin, unsigned &LineEnd,
                       std::string &FileName);
 
+class RejectLog;
+/// @brief Emit optimization remarks about the rejected regions to the user.
+///
+/// This emits the content of the reject log as optimization remarks.
+/// Remember to at least track failures (-polly-detect-track-failures).
+/// @param F The function we emit remarks for.
+/// @param Log The error log containing all messages being emitted as remark.
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log);
+
+/// @brief Emit diagnostic remarks for a valid Scop
+///
+/// @param F The function we emit remarks for
+/// @param R The region that marks a valid Scop
+void emitValidRemarks(const llvm::Function &F, const Region *R);
 //===----------------------------------------------------------------------===//
 /// @brief Base class of all reject reasons found during Scop detection.
 ///
@@ -67,6 +81,23 @@ public:
   ///
   /// @return A debug message representing this error.
   virtual std::string getMessage() const = 0;
+
+  /// @brief Generate a message for the end-user describing this error.
+  ///
+  /// The message provided has to be suitable for the end-user. So it should
+  /// not reference any LLVM internal data structures or terminology.
+  /// Ideally, the message helps the end-user to increase the size of the
+  /// regions amenable to Polly.
+  ///
+  /// @return A short message representing this error.
+  virtual std::string getEndUserMessage() const {
+    return "Unspecified error.";
+  };
+
+  /// @brief Get the source location of this error.
+  ///
+  /// @return The debug location for this error.
+  virtual const llvm::DebugLoc &getDebugLoc() const;
 };
 
 typedef std::shared_ptr<RejectReason> RejectReasonPtr;
@@ -79,10 +110,10 @@ class RejectLog {
 public:
   explicit RejectLog(Region *R) : R(R) {}
 
-  typedef llvm::SmallVector<RejectReasonPtr, 1>::iterator iterator;
+  typedef llvm::SmallVector<RejectReasonPtr, 1>::const_iterator iterator;
 
-  iterator begin() { return ErrorReports.begin(); }
-  iterator end() { return ErrorReports.end(); }
+  iterator begin() const { return ErrorReports.begin(); }
+  iterator end() const { return ErrorReports.end(); }
   size_t size() { return ErrorReports.size(); }
 
   const Region *region() const { return R; }
@@ -104,11 +135,12 @@ class ReportNonBranchTerminator : public
   BasicBlock *BB;
 
 public:
-  ReportNonBranchTerminator(BasicBlock *BB) : BB(BB) {}
+  ReportNonBranchTerminator(BasicBlock *BB) : ReportCFG(), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -121,11 +153,12 @@ class ReportCondition : public ReportCFG
   BasicBlock *BB;
 
 public:
-  ReportCondition(BasicBlock *BB) : BB(BB) {}
+  ReportCondition(BasicBlock *BB) : ReportCFG(), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -136,8 +169,16 @@ public:
 /// this class.
 class ReportAffFunc : public RejectReason {
   //===--------------------------------------------------------------------===//
+
+  // The instruction that caused non-affinity to occur.
+  const Instruction *Inst;
+
 public:
-  ReportAffFunc();
+  ReportAffFunc(const Instruction *Inst);
+
+  virtual const DebugLoc &getDebugLoc() const override {
+    return Inst->getDebugLoc();
+  }
 };
 
 //===----------------------------------------------------------------------===//
@@ -149,11 +190,12 @@ class ReportUndefCond : public ReportAff
   BasicBlock *BB;
 
 public:
-  ReportUndefCond(BasicBlock *BB) : BB(BB) {}
+  ReportUndefCond(const Instruction *Inst, BasicBlock *BB)
+      : ReportAffFunc(Inst), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -168,11 +210,12 @@ class ReportInvalidCond : public ReportA
   BasicBlock *BB;
 
 public:
-  ReportInvalidCond(BasicBlock *BB) : BB(BB) {}
+  ReportInvalidCond(const Instruction *Inst, BasicBlock *BB)
+      : ReportAffFunc(Inst), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -185,11 +228,12 @@ class ReportUndefOperand : public Report
   BasicBlock *BB;
 
 public:
-  ReportUndefOperand(BasicBlock *BB) : BB(BB) {}
+  ReportUndefOperand(BasicBlock *BB, const Instruction *Inst)
+      : ReportAffFunc(Inst), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -208,15 +252,16 @@ class ReportNonAffBranch : public Report
   //@}
 
 public:
-  ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS)
-      : BB(BB), LHS(LHS), RHS(RHS) {}
+  ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS,
+                     const Instruction *Inst)
+      : ReportAffFunc(Inst), BB(BB), LHS(LHS), RHS(RHS) {}
 
   const SCEV *lhs() { return LHS; }
   const SCEV *rhs() { return RHS; }
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -225,9 +270,11 @@ public:
 class ReportNoBasePtr : public ReportAffFunc {
   //===--------------------------------------------------------------------===//
 public:
+  ReportNoBasePtr(const Instruction *Inst) : ReportAffFunc(Inst) {}
+
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -236,9 +283,11 @@ public:
 class ReportUndefBasePtr : public ReportAffFunc {
   //===--------------------------------------------------------------------===//
 public:
+  ReportUndefBasePtr(const Instruction *Inst) : ReportAffFunc(Inst) {}
+
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -251,11 +300,12 @@ class ReportVariantBasePtr : public Repo
   Value *BaseValue;
 
 public:
-  ReportVariantBasePtr(Value *BaseValue) : BaseValue(BaseValue) {}
+  ReportVariantBasePtr(Value *BaseValue, const Instruction *Inst)
+      : ReportAffFunc(Inst), BaseValue(BaseValue) {}
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -268,14 +318,14 @@ class ReportNonAffineAccess : public Rep
   const SCEV *AccessFunction;
 
 public:
-  ReportNonAffineAccess(const SCEV *AccessFunction)
-      : AccessFunction(AccessFunction) {}
+  ReportNonAffineAccess(const SCEV *AccessFunction, const Instruction *Inst)
+      : ReportAffFunc(Inst), AccessFunction(AccessFunction) {}
 
   const SCEV *get() { return AccessFunction; }
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -299,11 +349,12 @@ class ReportPhiNodeRefInRegion : public
   Instruction *Inst;
 
 public:
-  ReportPhiNodeRefInRegion(Instruction *Inst) : Inst(Inst) {}
+  ReportPhiNodeRefInRegion(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -316,11 +367,12 @@ class ReportNonCanonicalPhiNode : public
   Instruction *Inst;
 
 public:
-  ReportNonCanonicalPhiNode(Instruction *Inst) : Inst(Inst) {}
+  ReportNonCanonicalPhiNode(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -333,11 +385,12 @@ class ReportLoopHeader : public ReportIn
   Loop *L;
 
 public:
-  ReportLoopHeader(Loop *L) : L(L) {}
+  ReportLoopHeader(Loop *L);
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -345,12 +398,16 @@ public:
 /// @brief Captures a region with invalid entering edges.
 class ReportIndEdge : public RejectReason {
   //===--------------------------------------------------------------------===//
+
+  BasicBlock *BB;
+
 public:
-  ReportIndEdge();
+  ReportIndEdge(BasicBlock *BB);
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -372,7 +429,8 @@ public:
 
   /// @name RejectReason interface
   //@{
-  virtual std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -389,7 +447,9 @@ public:
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
+  virtual std::string getEndUserMessage() const override;
   //@}
 };
 
@@ -398,20 +458,21 @@ public:
 class ReportAlias : public RejectReason {
   //===--------------------------------------------------------------------===//
 
-  // The offending alias set.
-  AliasSet *AS;
-
   /// @brief Format an invalid alias set.
   ///
   /// @param AS The invalid alias set to format.
   std::string formatInvalidAlias(AliasSet &AS) const;
 
+  AliasSet *AS;
+  Instruction *Inst;
+
 public:
-  ReportAlias(AliasSet *AS);
+  ReportAlias(Instruction *Inst, AliasSet *AS);
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -424,7 +485,7 @@ public:
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -437,7 +498,7 @@ public:
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const { return "Unknown reject reason"; }
+  virtual std::string getMessage() const override;
   //@}
 };
 
@@ -447,14 +508,15 @@ class ReportIntToPtr : public ReportOthe
   //===--------------------------------------------------------------------===//
 
   // The offending base value.
-  Value *BaseValue;
+  Instruction *BaseValue;
 
 public:
-  ReportIntToPtr(Value *BaseValue) : BaseValue(BaseValue) {}
+  ReportIntToPtr(Instruction *BaseValue);
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -465,11 +527,12 @@ class ReportAlloca : public ReportOther
   Instruction *Inst;
 
 public:
-  ReportAlloca(Instruction *Inst) : Inst(Inst) {}
+  ReportAlloca(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -480,11 +543,12 @@ class ReportUnknownInst : public ReportO
   Instruction *Inst;
 
 public:
-  ReportUnknownInst(Instruction *Inst) : Inst(Inst) {}
+  ReportUnknownInst(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -492,10 +556,15 @@ public:
 /// @brief Captures errors with phi nodes in exit BBs.
 class ReportPHIinExit : public ReportOther {
   //===--------------------------------------------------------------------===//
+  Instruction *Inst;
+
 public:
+  ReportPHIinExit(Instruction *Inst);
+
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 
@@ -503,10 +572,15 @@ public:
 /// @brief Captures errors with regions containing the function entry block.
 class ReportEntry : public ReportOther {
   //===--------------------------------------------------------------------===//
+  BasicBlock *BB;
+
 public:
+  ReportEntry(BasicBlock *BB);
+
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getMessage() const override;
+  virtual const DebugLoc &getDebugLoc() const override;
   //@}
 };
 

Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=211769&r1=211768&r2=211769&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Thu Jun 26 05:06:40 2014
@@ -250,11 +250,11 @@ bool ScopDetection::isValidCFG(BasicBloc
 
   // UndefValue is not allowed as condition.
   if (isa<UndefValue>(Condition))
-    return invalid<ReportUndefCond>(Context, /*Assert=*/true, &BB);
+    return invalid<ReportUndefCond>(Context, /*Assert=*/true, Br, &BB);
 
   // Only Constant and ICmpInst are allowed as condition.
   if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition)))
-    return invalid<ReportInvalidCond>(Context, /*Assert=*/true, &BB);
+    return invalid<ReportInvalidCond>(Context, /*Assert=*/true, Br, &BB);
 
   // Allow perfectly nested conditions.
   assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors");
@@ -271,7 +271,7 @@ bool ScopDetection::isValidCFG(BasicBloc
     // Are both operands of the ICmp affine?
     if (isa<UndefValue>(ICmp->getOperand(0)) ||
         isa<UndefValue>(ICmp->getOperand(1)))
-      return invalid<ReportUndefOperand>(Context, /*Assert=*/true, &BB);
+      return invalid<ReportUndefOperand>(Context, /*Assert=*/true, &BB, ICmp);
 
     Loop *L = LI->getLoopFor(ICmp->getParent());
     const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
@@ -280,7 +280,7 @@ bool ScopDetection::isValidCFG(BasicBloc
     if (!isAffineExpr(&Context.CurRegion, LHS, *SE) ||
         !isAffineExpr(&Context.CurRegion, RHS, *SE))
       return invalid<ReportNonAffBranch>(Context, /*Assert=*/true, &BB, LHS,
-                                         RHS);
+                                         RHS, ICmp);
   }
 
   // Allow loop exit conditions.
@@ -380,8 +380,8 @@ bool ScopDetection::hasAffineMemoryAcces
       const SCEVAddRecExpr *AF = PIAF.second;
       const Instruction *Insn = PIAF.first;
       if (Shape->DelinearizedSizes.empty())
-        return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
-                                              PIAF.second);
+        return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF,
+                                              Insn);
 
       MemAcc *Acc = new MemAcc(Insn, Shape);
       InsnToMemAcc.insert({Insn, Acc});
@@ -389,12 +389,14 @@ bool ScopDetection::hasAffineMemoryAcces
                                  Shape->DelinearizedSizes);
       if (Shape->DelinearizedSizes.empty() ||
           Acc->DelinearizedSubscripts.empty())
-        return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF);
+        return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF,
+                                              Insn);
 
       // Check that the delinearized subscripts are affine.
       for (const SCEV *S : Acc->DelinearizedSubscripts)
         if (!isAffineExpr(&Context.CurRegion, S, *SE, BaseValue))
-          return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF);
+          return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF,
+                                                Insn);
     }
   }
   return true;
@@ -411,12 +413,12 @@ bool ScopDetection::isValidMemoryAccess(
   BasePointer = dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
 
   if (!BasePointer)
-    return invalid<ReportNoBasePtr>(Context, /*Assert=*/true);
+    return invalid<ReportNoBasePtr>(Context, /*Assert=*/true, &Inst);
 
   BaseValue = BasePointer->getValue();
 
   if (isa<UndefValue>(BaseValue))
-    return invalid<ReportUndefBasePtr>(Context, /*Assert=*/true);
+    return invalid<ReportUndefBasePtr>(Context, /*Assert=*/true, &Inst);
 
   // Check that the base address of the access is invariant in the current
   // region.
@@ -424,7 +426,8 @@ bool ScopDetection::isValidMemoryAccess(
     // Verification of this property is difficult as the independent blocks
     // pass may introduce aliasing that we did not have when running the
     // scop detection.
-    return invalid<ReportVariantBasePtr>(Context, /*Assert=*/false, BaseValue);
+    return invalid<ReportVariantBasePtr>(Context, /*Assert=*/false, BaseValue,
+                                         &Inst);
 
   AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
 
@@ -436,7 +439,7 @@ bool ScopDetection::isValidMemoryAccess(
 
     if (!PollyDelinearize || !AF)
       return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
-                                            AccessFunction);
+                                            AccessFunction, &Inst);
 
     const SCEV *ElementSize = SE->getElementSize(&Inst);
     Context.ElementSize[BasePointer] = ElementSize;
@@ -456,8 +459,8 @@ bool ScopDetection::isValidMemoryAccess(
 
   // FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions
   // created by IndependentBlocks Pass.
-  if (isa<IntToPtrInst>(BaseValue))
-    return invalid<ReportIntToPtr>(Context, /*Assert=*/true, BaseValue);
+  if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BaseValue))
+    return invalid<ReportIntToPtr>(Context, /*Assert=*/true, Inst);
 
   if (IgnoreAliasing)
     return true;
@@ -476,7 +479,7 @@ bool ScopDetection::isValidMemoryAccess(
   // not proof this without -basicaa we would fail. We disable this check to
   // not cause irrelevant verification failures.
   if (!AS.isMustAlias())
-    return invalid<ReportAlias>(Context, /*Assert=*/true, &AS);
+    return invalid<ReportAlias>(Context, /*Assert=*/true, &Inst, &AS);
 
   return true;
 }
@@ -692,7 +695,7 @@ bool ScopDetection::isValidExit(Detectio
   if (BasicBlock *Exit = R.getExit()) {
     BasicBlock::iterator I = Exit->begin();
     if (I != Exit->end() && isa<PHINode>(*I))
-      return invalid<ReportPHIinExit>(Context, /*Assert=*/true);
+      return invalid<ReportPHIinExit>(Context, /*Assert=*/true, I);
   }
 
   return true;
@@ -745,7 +748,7 @@ bool ScopDetection::isValidRegion(Detect
         // Region entering edges come from the same loop but outside the region
         // are not allowed.
         if (L->contains(*PI) && !R.contains(*PI))
-          return invalid<ReportIndEdge>(Context, /*Assert=*/true);
+          return invalid<ReportIndEdge>(Context, /*Assert=*/true, *PI);
       }
     }
   }
@@ -753,7 +756,7 @@ bool ScopDetection::isValidRegion(Detect
   // SCoP cannot contain the entry block of the function, because we need
   // to insert alloca instruction there when translate scalar to array.
   if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock()))
-    return invalid<ReportEntry>(Context, /*Assert=*/true);
+    return invalid<ReportEntry>(Context, /*Assert=*/true, R.getEntry());
 
   if (!isValidExit(Context))
     return false;
@@ -780,6 +783,34 @@ void ScopDetection::printLocations(llvm:
   }
 }
 
+void
+ScopDetection::emitMissedRemarksForValidRegions(const Function &F,
+                                                const RegionSet &ValidRegions) {
+  for (const Region *R : ValidRegions) {
+    const Region *Parent = R->getParent();
+    if (Parent && !Parent->isTopLevelRegion() && RejectLogs.count(Parent))
+      emitRejectionRemarks(F, RejectLogs.at(Parent));
+  }
+}
+
+void ScopDetection::emitMissedRemarksForLeaves(const Function &F,
+                                               const Region *R) {
+  for (const std::unique_ptr<Region> &Child : *R) {
+    bool IsValid = ValidRegions.count(Child.get());
+    if (IsValid)
+      continue;
+
+    bool IsLeaf = Child->begin() == Child->end();
+    if (!IsLeaf)
+      emitMissedRemarksForLeaves(F, Child.get());
+    else {
+      if (RejectLogs.count(Child.get())) {
+        emitRejectionRemarks(F, RejectLogs.at(Child.get()));
+      }
+    }
+  }
+}
+
 bool ScopDetection::runOnFunction(llvm::Function &F) {
   LI = &getAnalysis<LoopInfo>();
   RI = &getAnalysis<RegionInfo>();
@@ -800,6 +831,15 @@ bool ScopDetection::runOnFunction(llvm::
 
   findScops(*TopRegion);
 
+  // Only makes sense when we tracked errors.
+  if (PollyTrackFailures) {
+    emitMissedRemarksForValidRegions(F, ValidRegions);
+    emitMissedRemarksForLeaves(F, TopRegion);
+  }
+
+  for (const Region *R : ValidRegions)
+    emitValidRemarks(F, R);
+
   if (ReportLevel >= 1)
     printLocations(F);
 

Modified: polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp?rev=211769&r1=211768&r2=211769&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp Thu Jun 26 05:06:40 2014
@@ -22,12 +22,15 @@
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/AliasSetTracker.h"
 #include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Value.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
 
 #include "llvm/Analysis/RegionInfo.h"
-#include "llvm/IR/DebugInfo.h"
 
 #define DEBUG_TYPE "polly-detect"
 #include "llvm/Support/Debug.h"
@@ -81,75 +84,204 @@ void getDebugLocation(const Region *R, u
     }
 }
 
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log) {
+  LLVMContext &Ctx = F.getContext();
+
+  const Region *R = Log.region();
+  const BasicBlock *Entry = R->getEntry();
+  DebugLoc DL = Entry->getTerminator()->getDebugLoc();
+
+  emitOptimizationRemarkMissed(
+      Ctx, DEBUG_TYPE, F, DL,
+      "The following errors keep this region from being a Scop.");
+  for (RejectReasonPtr RR : Log) {
+    const DebugLoc &Loc = RR->getDebugLoc();
+    if (!Loc.isUnknown())
+      emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc,
+                                   RR->getEndUserMessage());
+  }
+}
+
+void emitValidRemarks(const llvm::Function &F, const Region *R) {
+  LLVMContext &Ctx = F.getContext();
+
+  const BasicBlock *Entry = R->getEntry();
+  const BasicBlock *Exit = R->getExit();
+
+  const DebugLoc &Begin = Entry->getFirstNonPHIOrDbg()->getDebugLoc();
+  const DebugLoc &End = Exit->getFirstNonPHIOrDbg()->getDebugLoc();
+
+  emitOptimizationRemark(Ctx, DEBUG_TYPE, F, Begin,
+                         "A valid Scop begins here.");
+  emitOptimizationRemark(Ctx, DEBUG_TYPE, F, End, "A valid Scop ends here.");
+}
+
+//===----------------------------------------------------------------------===//
+// RejectReason.
+
+const llvm::DebugLoc &RejectReason::getDebugLoc() const {
+  // Allocate an empty DebugLoc and return it a reference to it.
+  return *(std::make_shared<DebugLoc>().get());
+}
+
 //===----------------------------------------------------------------------===//
 // ReportCFG.
 
 ReportCFG::ReportCFG() { ++BadCFGForScop; }
 
+//===----------------------------------------------------------------------===//
+// ReportNonBranchTerminator.
+
 std::string ReportNonBranchTerminator::getMessage() const {
   return ("Non branch instruction terminates BB: " + BB->getName()).str();
 }
 
+const DebugLoc &ReportNonBranchTerminator::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportCondition.
+
 std::string ReportCondition::getMessage() const {
   return ("Not well structured condition at BB: " + BB->getName()).str();
 }
 
-ReportAffFunc::ReportAffFunc() { ++BadAffFuncForScop; }
+const DebugLoc &ReportCondition::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAffFunc.
+
+ReportAffFunc::ReportAffFunc(const Instruction *Inst)
+    : RejectReason(), Inst(Inst) {
+  ++BadAffFuncForScop;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUndefCond.
 
 std::string ReportUndefCond::getMessage() const {
   return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
 }
 
+//===----------------------------------------------------------------------===//
+// ReportInvalidCond.
+
 std::string ReportInvalidCond::getMessage() const {
   return ("Condition in BB '" + BB->getName()).str() +
          "' neither constant nor an icmp instruction";
 }
 
+//===----------------------------------------------------------------------===//
+// ReportUndefOperand.
+
 std::string ReportUndefOperand::getMessage() const {
   return ("undef operand in branch at BB: " + BB->getName()).str();
 }
 
+//===----------------------------------------------------------------------===//
+// ReportNonAffBranch.
+
 std::string ReportNonAffBranch::getMessage() const {
   return ("Non affine branch in BB '" + BB->getName()).str() + "' with LHS: " +
          *LHS + " and RHS: " + *RHS;
 }
 
+//===----------------------------------------------------------------------===//
+// ReportNoBasePtr.
+
 std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
 
+//===----------------------------------------------------------------------===//
+// ReportUndefBasePtr.
+
 std::string ReportUndefBasePtr::getMessage() const {
   return "Undefined base pointer";
 }
 
+//===----------------------------------------------------------------------===//
+// ReportVariantBasePtr.
+
 std::string ReportVariantBasePtr::getMessage() const {
   return "Base address not invariant in current region:" + *BaseValue;
 }
 
+//===----------------------------------------------------------------------===//
+// ReportNonAffineAccess.
+
 std::string ReportNonAffineAccess::getMessage() const {
   return "Non affine access function: " + *AccessFunction;
 }
 
-ReportIndVar::ReportIndVar() { ++BadIndVarForScop; }
+//===----------------------------------------------------------------------===//
+// ReportIndVar.
+
+ReportIndVar::ReportIndVar() : RejectReason() { ++BadIndVarForScop; }
+
+//===----------------------------------------------------------------------===//
+// ReportPhiNodeRefInRegion.
+
+ReportPhiNodeRefInRegion::ReportPhiNodeRefInRegion(Instruction *Inst)
+    : ReportIndVar(), Inst(Inst) {}
 
 std::string ReportPhiNodeRefInRegion::getMessage() const {
   return "SCEV of PHI node refers to SSA names in region: " + *Inst;
 }
 
+const DebugLoc &ReportPhiNodeRefInRegion::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportNonCanonicalPhiNode.
+
+ReportNonCanonicalPhiNode::ReportNonCanonicalPhiNode(Instruction *Inst)
+    : ReportIndVar(), Inst(Inst) {}
+
 std::string ReportNonCanonicalPhiNode::getMessage() const {
   return "Non canonical PHI node: " + *Inst;
 }
 
+const DebugLoc &ReportNonCanonicalPhiNode::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportLoopHeader.
+
+ReportLoopHeader::ReportLoopHeader(Loop *L) : ReportIndVar(), L(L) {}
+
 std::string ReportLoopHeader::getMessage() const {
   return ("No canonical IV at loop header: " + L->getHeader()->getName()).str();
 }
 
-ReportIndEdge::ReportIndEdge() { ++BadIndEdgeForScop; }
+const DebugLoc &ReportLoopHeader::getDebugLoc() const {
+  BasicBlock *BB = L->getHeader();
+  return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportIndEdge.
+
+ReportIndEdge::ReportIndEdge(BasicBlock *BB) : RejectReason(), BB(BB) {
+  ++BadIndEdgeForScop;
+}
 
 std::string ReportIndEdge::getMessage() const {
   return "Region has invalid entering edges!";
 }
 
+const DebugLoc &ReportIndEdge::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportLoopBound.
+
 ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
-    : L(L), LoopCount(LoopCount) {
+    : RejectReason(), L(L), LoopCount(LoopCount) {
   ++BadLoopBoundForScop;
 }
 
@@ -158,7 +290,15 @@ std::string ReportLoopBound::getMessage(
          L->getHeader()->getName();
 }
 
-ReportFuncCall::ReportFuncCall(Instruction *Inst) : Inst(Inst) {
+const DebugLoc &ReportLoopBound::getDebugLoc() const {
+  const BasicBlock *BB = L->getHeader();
+  return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportFuncCall.
+
+ReportFuncCall::ReportFuncCall(Instruction *Inst) : RejectReason(), Inst(Inst) {
   ++BadFuncCallForScop;
 }
 
@@ -166,7 +306,22 @@ std::string ReportFuncCall::getMessage()
   return "Call instruction: " + *Inst;
 }
 
-ReportAlias::ReportAlias(AliasSet *AS) : AS(AS) { ++BadAliasForScop; }
+const DebugLoc &ReportFuncCall::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+std::string ReportFuncCall::getEndUserMessage() const {
+  return "This function call cannot be handeled. "
+         "Try to inline it.";
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlias.
+
+ReportAlias::ReportAlias(Instruction *Inst, AliasSet *AS)
+    : RejectReason(), AS(AS), Inst(Inst) {
+  ++BadAliasForScop;
+}
 
 std::string ReportAlias::formatInvalidAlias(AliasSet &AS) const {
   std::string Message;
@@ -204,31 +359,89 @@ std::string ReportAlias::formatInvalidAl
 
 std::string ReportAlias::getMessage() const { return formatInvalidAlias(*AS); }
 
-ReportSimpleLoop::ReportSimpleLoop() { ++BadSimpleLoopForScop; }
+const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
+
+//===----------------------------------------------------------------------===//
+// ReportSimpleLoop.
+
+ReportSimpleLoop::ReportSimpleLoop() : RejectReason() {
+  ++BadSimpleLoopForScop;
+}
 
 std::string ReportSimpleLoop::getMessage() const {
   return "Loop not in simplify form is invalid!";
 }
 
-ReportOther::ReportOther() { ++BadOtherForScop; }
+//===----------------------------------------------------------------------===//
+// ReportOther.
+
+std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
+
+ReportOther::ReportOther() : RejectReason() { ++BadOtherForScop; }
+
+//===----------------------------------------------------------------------===//
+// ReportIntToPtr.
+ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
+    : ReportOther(), BaseValue(BaseValue) {}
 
 std::string ReportIntToPtr::getMessage() const {
   return "Find bad intToptr prt: " + *BaseValue;
 }
 
+const DebugLoc &ReportIntToPtr::getDebugLoc() const {
+  return BaseValue->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlloca.
+
+ReportAlloca::ReportAlloca(Instruction *Inst) : ReportOther(), Inst(Inst) {}
+
 std::string ReportAlloca::getMessage() const {
   return "Alloca instruction: " + *Inst;
 }
 
+const DebugLoc &ReportAlloca::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUnknownInst.
+
+ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
+    : ReportOther(), Inst(Inst) {}
+
 std::string ReportUnknownInst::getMessage() const {
   return "Unknown instruction: " + *Inst;
 }
 
+const DebugLoc &ReportUnknownInst::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportPHIinExit.
+
+ReportPHIinExit::ReportPHIinExit(Instruction *Inst)
+    : ReportOther(), Inst(Inst) {}
+
 std::string ReportPHIinExit::getMessage() const {
   return "PHI node in exit BB";
 }
 
+const DebugLoc &ReportPHIinExit::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportEntry.
+ReportEntry::ReportEntry(BasicBlock *BB) : ReportOther(), BB(BB) {}
+
 std::string ReportEntry::getMessage() const {
   return "Region containing entry block of function is invalid!";
 }
+
+const DebugLoc &ReportEntry::getDebugLoc() const {
+  return BB->getTerminator()->getDebugLoc();
+}
 } // namespace polly

Added: polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll?rev=211769&view=auto
==============================================================================
--- polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll (added)
+++ polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll Thu Jun 26 05:06:40 2014
@@ -0,0 +1,67 @@
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1 | FileCheck %s
+
+; #define N 1024
+; double invalidCall(double A[N]);
+;
+; void a(double A[N], int n) {
+;   for (int i=0; i<n; ++i) {
+;     A[i] = invalidCall(A);
+;   }
+; }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @a(double* %A, i32 %n) #0 {
+entry:
+  %cmp1 = icmp sgt i32 %n, 0, !dbg !10
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end, !dbg !10
+
+for.body.lr.ph:                                   ; preds = %entry
+  %0 = zext i32 %n to i64
+  br label %for.body, !dbg !10
+
+for.body:                                         ; preds = %for.body, %for.body.lr.ph
+  %indvar = phi i64 [ 0, %for.body.lr.ph ], [ %indvar.next, %for.body ]
+  %arrayidx = getelementptr double* %A, i64 %indvar, !dbg !12
+  %call = tail call double @invalidCall(double* %A) #2, !dbg !12
+  store double %call, double* %arrayidx, align 8, !dbg !12, !tbaa !14
+  %indvar.next = add i64 %indvar, 1, !dbg !10
+  %exitcond = icmp eq i64 %indvar.next, %0, !dbg !10
+  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !10
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void, !dbg !18
+}
+
+declare double @invalidCall(double*) #1
+
+; CHECK: remark: ReportFuncCall.c:4:8: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportFuncCall.c:5:12: This function call cannot be handeled. Try to inline it.
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+!llvm.ident = !{!9}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 ", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c] [DW_LANG_C99]
+!1 = metadata !{metadata !"ReportFuncCall.c", metadata !"/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics"}
+!2 = metadata !{}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"a", metadata !"a", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (double*, i32)* @a, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [a]
+!5 = metadata !{i32 786473, metadata !1}          ; [ DW_TAG_file_type ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!8 = metadata !{i32 2, metadata !"Debug Info Version", i32 1}
+!9 = metadata !{metadata !"clang version 3.5.0 "}
+!10 = metadata !{i32 4, i32 8, metadata !11, null}
+!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!12 = metadata !{i32 5, i32 12, metadata !13, null}
+!13 = metadata !{i32 786443, metadata !1, metadata !11, i32 4, i32 27, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!14 = metadata !{metadata !15, metadata !15, i64 0}
+!15 = metadata !{metadata !"double", metadata !16, i64 0}
+!16 = metadata !{metadata !"omnipotent char", metadata !17, i64 0}
+!17 = metadata !{metadata !"Simple C/C++ TBAA"}
+!18 = metadata !{i32 7, i32 1, metadata !4, null}





More information about the llvm-commits mailing list