[PATCH 02/11] Support the new DiagnosticRemarks

Andreas Simbuerger simbuerg at googlemail.com
Sun Jun 8 17:42:24 PDT 2014


After the ScopDetection is finished, we provide Diagnostic remarks
for all error entries of each valid Scops parent region.

The goal is to provide developers with useful hints about
opportunities to increase the size of the detected Scops in their
code.

Usage:
 clang <...> -Rpass="polly-detect" <...>
 opt <...> -pass-remarks="polly-detect" <...>
---
 include/polly/ScopDetectionDiagnostic.h  | 160 ++++++++++++----
 lib/Analysis/ScopDetection.cpp           |  47 +++--
 lib/Analysis/ScopDetectionDiagnostic.cpp | 309 ++++++++++++++++++++++++++++++-
 3 files changed, 454 insertions(+), 62 deletions(-)

diff --git a/include/polly/ScopDetectionDiagnostic.h b/include/polly/ScopDetectionDiagnostic.h
index 1006770..a08bc1a 100644
--- a/include/polly/ScopDetectionDiagnostic.h
+++ b/include/polly/ScopDetectionDiagnostic.h
@@ -52,6 +52,17 @@ 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.
+/// @param LI LoopInfo to fetch the surrounding loops.
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log,
+                          LoopInfo *LI);
+
 //===----------------------------------------------------------------------===//
 /// @brief Base class of all reject reasons found during Scop detection.
 ///
@@ -67,6 +78,19 @@ public:
   ///
   /// @return A debug message representing this error.
   virtual std::string getMessage() const = 0;
+
+  /// @brief Generate a short diagnostic messagedescribing this error.
+  ///
+  /// The generated message is suitable for providing additional information
+  /// to the end user in the form of optimization remarks.
+  ///
+  /// @return A short message representing this error.
+  virtual std::string getShortMessage() const = 0;
+
+  /// @brief Get the source location of this error.
+  ///
+  /// @return The debug location for this error.
+  virtual const llvm::DebugLoc &getDebugLoc() const = 0;
 };
 
 typedef std::shared_ptr<RejectReason> RejectReasonPtr;
@@ -79,10 +103,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 +128,13 @@ class ReportNonBranchTerminator : public ReportCFG {
   BasicBlock *BB;
 
 public:
-  ReportNonBranchTerminator(BasicBlock *BB) : BB(BB) {}
+  ReportNonBranchTerminator(BasicBlock *BB) : ReportCFG(), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -121,11 +147,13 @@ class ReportCondition : public ReportCFG {
   BasicBlock *BB;
 
 public:
-  ReportCondition(BasicBlock *BB) : BB(BB) {}
+  ReportCondition(BasicBlock *BB) : ReportCFG(), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -136,8 +164,14 @@ 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 { return Inst->getDebugLoc(); };
 };
 
 //===----------------------------------------------------------------------===//
@@ -149,10 +183,12 @@ class ReportUndefCond : public ReportAffFunc {
   BasicBlock *BB;
 
 public:
-  ReportUndefCond(BasicBlock *BB) : BB(BB) {}
+  ReportUndefCond(const Instruction *Inst, BasicBlock *BB)
+      : ReportAffFunc(Inst), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -168,10 +204,12 @@ class ReportInvalidCond : public ReportAffFunc {
   BasicBlock *BB;
 
 public:
-  ReportInvalidCond(BasicBlock *BB) : BB(BB) {}
+  ReportInvalidCond(const Instruction *Inst, BasicBlock *BB)
+      : ReportAffFunc(Inst), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -185,10 +223,12 @@ class ReportUndefOperand : public ReportAffFunc {
   BasicBlock *BB;
 
 public:
-  ReportUndefOperand(BasicBlock *BB) : BB(BB) {}
+  ReportUndefOperand(BasicBlock *BB, const Instruction *Inst)
+      : ReportAffFunc(Inst), BB(BB) {}
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -208,14 +248,16 @@ class ReportNonAffBranch : public ReportAffFunc {
   //@}
 
 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 getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -225,8 +267,11 @@ public:
 class ReportNoBasePtr : public ReportAffFunc {
   //===--------------------------------------------------------------------===//
 public:
+  ReportNoBasePtr(const Instruction *Inst) : ReportAffFunc(Inst) {}
+
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -236,8 +281,11 @@ public:
 class ReportUndefBasePtr : public ReportAffFunc {
   //===--------------------------------------------------------------------===//
 public:
+  ReportUndefBasePtr(const Instruction *Inst) : ReportAffFunc(Inst) {}
+
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -251,10 +299,12 @@ class ReportVariantBasePtr : public ReportAffFunc {
   Value *BaseValue;
 
 public:
-  ReportVariantBasePtr(Value *BaseValue) : BaseValue(BaseValue) {}
+  ReportVariantBasePtr(Value *BaseValue, const Instruction *Inst)
+      : ReportAffFunc(Inst), BaseValue(BaseValue) {}
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -268,13 +318,14 @@ class ReportNonAffineAccess : public ReportAffFunc {
   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 getShortMessage() const;
   virtual std::string getMessage() const;
   //@}
 };
@@ -299,11 +350,13 @@ class ReportPhiNodeRefInRegion : public ReportIndVar {
   Instruction *Inst;
 
 public:
-  ReportPhiNodeRefInRegion(Instruction *Inst) : Inst(Inst) {}
+  ReportPhiNodeRefInRegion(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -316,11 +369,13 @@ class ReportNonCanonicalPhiNode : public ReportIndVar {
   Instruction *Inst;
 
 public:
-  ReportNonCanonicalPhiNode(Instruction *Inst) : Inst(Inst) {}
+  ReportNonCanonicalPhiNode(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -333,11 +388,13 @@ class ReportLoopHeader : public ReportIndVar {
   Loop *L;
 
 public:
-  ReportLoopHeader(Loop *L) : L(L) {}
+  ReportLoopHeader(Loop *L);
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -345,12 +402,17 @@ 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 getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -372,7 +434,9 @@ public:
 
   /// @name RejectReason interface
   //@{
+  virtual std::string getShortMessage() const;
   virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -389,7 +453,9 @@ public:
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -398,20 +464,22 @@ 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 getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -424,7 +492,9 @@ public:
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -437,7 +507,9 @@ public:
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const { return "Unknown reject reason"; }
+  virtual std::string getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -447,14 +519,16 @@ class ReportIntToPtr : public ReportOther {
   //===--------------------------------------------------------------------===//
 
   // 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 getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -465,11 +539,13 @@ 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 getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -480,11 +556,13 @@ class ReportUnknownInst : public ReportOther {
   Instruction *Inst;
 
 public:
-  ReportUnknownInst(Instruction *Inst) : Inst(Inst) {}
+  ReportUnknownInst(Instruction *Inst);
 
   /// @name RejectReason interface
   //@{
-  std::string getMessage() const;
+  virtual std::string getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -492,10 +570,16 @@ 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 getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
@@ -503,10 +587,16 @@ 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 getShortMessage() const;
+  virtual std::string getMessage() const;
+  virtual const DebugLoc &getDebugLoc() const;
   //@}
 };
 
diff --git a/lib/Analysis/ScopDetection.cpp b/lib/Analysis/ScopDetection.cpp
index 8a9226e..cab7af7 100644
--- a/lib/Analysis/ScopDetection.cpp
+++ b/lib/Analysis/ScopDetection.cpp
@@ -243,11 +243,11 @@ bool ScopDetection::isValidCFG(BasicBlock &BB,
 
   // 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");
@@ -264,7 +264,7 @@ bool ScopDetection::isValidCFG(BasicBlock &BB,
     // 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);
@@ -273,7 +273,7 @@ bool ScopDetection::isValidCFG(BasicBlock &BB,
     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.
@@ -373,8 +373,8 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
       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});
@@ -382,12 +382,14 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
                                  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;
@@ -404,12 +406,12 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
   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.
@@ -417,7 +419,8 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
     // 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);
 
@@ -429,7 +432,7 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
 
     if (!PollyDelinearize || !AF)
       return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
-                                            AccessFunction);
+                                            AccessFunction, &Inst);
 
     const SCEV *ElementSize = SE->getElementSize(&Inst);
     Context.ElementSize[BasePointer] = ElementSize;
@@ -449,8 +452,8 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
 
   // 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;
@@ -469,7 +472,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())
-    return invalid<ReportAlias>(Context, /*Assert=*/true, &AS);
+    return invalid<ReportAlias>(Context, /*Assert=*/true, &Inst, &AS);
 
   return true;
 }
@@ -685,7 +688,7 @@ bool ScopDetection::isValidExit(DetectionContext &Context) const {
   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;
@@ -738,7 +741,7 @@ bool ScopDetection::isValidRegion(DetectionContext &Context) const {
         // 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);
       }
     }
   }
@@ -746,7 +749,7 @@ bool ScopDetection::isValidRegion(DetectionContext &Context) const {
   // 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;
@@ -793,6 +796,14 @@ bool ScopDetection::runOnFunction(llvm::Function &F) {
 
   findScops(*TopRegion);
 
+  // Emit diagnostic remarks for the parents of valid Scops.
+  // This should help users with increasing the size of valid Scops.
+  for (const Region *R : ValidRegions) {
+    const Region *Parent = R->getParent();
+    if ((Parent != TopRegion) && RejectLogs.count(Parent))
+      emitRejectionRemarks(F, RejectLogs.at(Parent), LI);
+  }
+
   if (ReportLevel >= 1)
     printLocations(F);
 
diff --git a/lib/Analysis/ScopDetectionDiagnostic.cpp b/lib/Analysis/ScopDetectionDiagnostic.cpp
index eaed954..67a0a4d 100644
--- a/lib/Analysis/ScopDetectionDiagnostic.cpp
+++ b/lib/Analysis/ScopDetectionDiagnostic.cpp
@@ -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,243 @@ void getDebugLocation(const Region *R, unsigned &LineBegin, unsigned &LineEnd,
     }
 }
 
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log,
+                          LoopInfo *LI) {
+  LLVMContext &Ctx = F.getContext();
+
+  const Region *R = Log.region();
+  Loop *L = LI->getLoopFor(R->getEntry());
+
+  if (L) {
+    DebugLoc DL = L->getStartLoc();
+    Ctx.diagnose(DiagnosticInfoOptimizationRemark(
+        DEBUG_TYPE, F, DL,
+        "The following errors keep this loop from being a Scop."));
+    for (RejectReasonPtr RR : Log) {
+      Ctx.diagnose(DiagnosticInfoOptimizationRemark(
+          DEBUG_TYPE, F, RR->getDebugLoc(), RR->getShortMessage()));
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // ReportCFG.
 
 ReportCFG::ReportCFG() { ++BadCFGForScop; }
 
+//===----------------------------------------------------------------------===//
+// ReportNonBranchTerminator.
+
+std::string ReportNonBranchTerminator::getShortMessage() const {
+  return "(FIXME) Non branch instruction terminates BB";
+}
+
 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::getShortMessage() const {
+  return "(FIXME) The condition is not well structured";
+}
+
 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::getShortMessage() const {
+  return "(FIXME) Condition is based on 'undef' value in BB";
+}
 
 std::string ReportUndefCond::getMessage() const {
   return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
 }
 
+//===----------------------------------------------------------------------===//
+// ReportInvalidCond.
+
+std::string ReportInvalidCond::getShortMessage() const {
+  return "Condition is neither constant nor an integer comparison";
+}
+
 std::string ReportInvalidCond::getMessage() const {
   return ("Condition in BB '" + BB->getName()).str() +
          "' neither constant nor an icmp instruction";
 }
 
+//===----------------------------------------------------------------------===//
+// ReportUndefOperand.
+
+std::string ReportUndefOperand::getShortMessage() const {
+  return "(FIXME) Undefined operand in condition";
+}
+
 std::string ReportUndefOperand::getMessage() const {
   return ("undef operand in branch at BB: " + BB->getName()).str();
 }
 
+//===----------------------------------------------------------------------===//
+// ReportNonAffBranch.
+
+std::string ReportNonAffBranch::getShortMessage() const {
+  return "The condition has non-affine operands";
+}
+
 std::string ReportNonAffBranch::getMessage() const {
   return ("Non affine branch in BB '" + BB->getName()).str() + "' with LHS: " +
          *LHS + " and RHS: " + *RHS;
 }
 
+//===----------------------------------------------------------------------===//
+// ReportNoBasePtr.
+
+std::string ReportNoBasePtr::getShortMessage() const {
+  return "I don't have a base pointer for this array";
+}
+
 std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
 
+//===----------------------------------------------------------------------===//
+// ReportUndefBasePtr.
+
+std::string ReportUndefBasePtr::getShortMessage() const {
+  return "The base pointer for this array is undefined";
+}
+
 std::string ReportUndefBasePtr::getMessage() const {
   return "Undefined base pointer";
 }
 
+//===----------------------------------------------------------------------===//
+// ReportVariantBasePtr.
+
+std::string ReportVariantBasePtr::getShortMessage() const {
+  return "The base address of this array is not invariant inside the loop";
+}
+
 std::string ReportVariantBasePtr::getMessage() const {
   return "Base address not invariant in current region:" + *BaseValue;
 }
 
+//===----------------------------------------------------------------------===//
+// ReportNonAffineAccess.
+
+std::string ReportNonAffineAccess::getShortMessage() const {
+  return "The access function is not affine";
+}
+
 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::getShortMessage() const {
+  return "(FIXME) SCEV of PHI node refers to SSA names in region";
+}
 
 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::getShortMessage() const {
+  return "PHI node is not in canonical form";
+}
+
 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::getShortMessage() const {
+  return "The loop's induction variable is not in canonical form";
+}
+
 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.
+
+std::string ReportIndEdge::getShortMessage() const {
+  return "The loop has invalid control flow";
+}
+
+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.
+
+std::string ReportLoopBound::getShortMessage() const {
+  return "The loop bound is not affine";
+}
+
 ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
-    : L(L), LoopCount(LoopCount) {
+    : RejectReason(), L(L), LoopCount(LoopCount) {
   ++BadLoopBoundForScop;
 }
 
@@ -158,7 +329,19 @@ std::string ReportLoopBound::getMessage() const {
          L->getHeader()->getName();
 }
 
-ReportFuncCall::ReportFuncCall(Instruction *Inst) : Inst(Inst) {
+const DebugLoc &ReportLoopBound::getDebugLoc() const {
+  const BasicBlock *BB = L->getHeader();
+  return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportFuncCall.
+
+std::string ReportFuncCall::getShortMessage() const {
+  return "This function call needs to be inlined.";
+}
+
+ReportFuncCall::ReportFuncCall(Instruction *Inst) : RejectReason(), Inst(Inst) {
   ++BadFuncCallForScop;
 }
 
@@ -166,7 +349,21 @@ std::string ReportFuncCall::getMessage() const {
   return "Call instruction: " + *Inst;
 }
 
-ReportAlias::ReportAlias(AliasSet *AS) : AS(AS) { ++BadAliasForScop; }
+const DebugLoc &ReportFuncCall::getDebugLoc() const {
+  return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlias.
+
+std::string ReportAlias::getShortMessage() const {
+  return "The array accessed may alias with others.";
+}
+
+ReportAlias::ReportAlias(Instruction *Inst, AliasSet *AS)
+    : RejectReason(), AS(AS), Inst(Inst) {
+  ++BadAliasForScop;
+}
 
 std::string ReportAlias::formatInvalidAlias(AliasSet &AS) const {
   std::string Message;
@@ -204,32 +401,126 @@ std::string ReportAlias::formatInvalidAlias(AliasSet &AS) const {
 
 std::string ReportAlias::getMessage() const { return formatInvalidAlias(*AS); }
 
-ReportSimpleLoop::ReportSimpleLoop() { ++BadSimpleLoopForScop; }
+const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
+
+//===----------------------------------------------------------------------===//
+// ReportSimpleLoop.
+
+std::string ReportSimpleLoop::getShortMessage() const {
+  return "Try simplifying the loop (-loop-simplify)";
+}
+
+ReportSimpleLoop::ReportSimpleLoop() : RejectReason() {
+  ++BadSimpleLoopForScop;
+}
 
 std::string ReportSimpleLoop::getMessage() const {
   return "Loop not in simplify form is invalid!";
 }
 
-ReportOther::ReportOther() { ++BadOtherForScop; }
+const DebugLoc &ReportSimpleLoop::getDebugLoc() const {
+  // FIXME:
+  return *(std::make_shared<DebugLoc>().get());
+}
+
+//===----------------------------------------------------------------------===//
+// ReportOther.
+
+std::string ReportOther::getShortMessage() const { return getMessage(); }
+
+std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
+
+ReportOther::ReportOther() : RejectReason() { ++BadOtherForScop; }
+
+const DebugLoc &ReportOther::getDebugLoc() const {
+  // FIXME:
+  return *(std::make_shared<DebugLoc>().get());
+}
+
+//===----------------------------------------------------------------------===//
+// ReportIntToPtr.
+ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
+    : ReportOther(), BaseValue(BaseValue) {}
+
+std::string ReportIntToPtr::getShortMessage() const {
+  return "Do not case this int to a pointer";
+}
 
 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::getShortMessage() const {
+  return "Try removing this stack allocation (-mem2reg)";
+}
+
 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::getShortMessage() const {
+  return "There is an unknown instruction";
+}
+
 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::getShortMessage() const {
+  return "This instruction causes a PHI node in the exit block of the loop";
+}
+
 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::getShortMessage() const {
+  return "The function entry cannot be part of a Scop";
+}
+
 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
-- 
2.0.0




More information about the llvm-commits mailing list