[LoopAccesses] Split out LoopAccessReport from VectorizerReport
authorAdam Nemet <anemet@apple.com>
Wed, 18 Feb 2015 03:44:25 +0000 (03:44 +0000)
committerAdam Nemet <anemet@apple.com>
Wed, 18 Feb 2015 03:44:25 +0000 (03:44 +0000)
The only difference between these two is that VectorizerReport adds a
vectorizer-specific prefix to its messages.  When LAA is used in the
vectorizer context the prefix is added when we promote the
LoopAccessReport into a VectorizerReport via one of the constructors.

This is part of the patchset that converts LoopAccessAnalysis into an
actual analysis pass.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229632 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/LoopAccessAnalysis.h
lib/Analysis/LoopAccessAnalysis.cpp
lib/Transforms/Vectorize/LoopVectorize.cpp

index a3dcb79ec3495b69b56c8528232ffbd11c608daa..71506ddc859ca14115dac058950da186cb9c5bca 100644 (file)
@@ -36,15 +36,18 @@ class SCEV;
 
 /// Optimization analysis message produced during vectorization. Messages inform
 /// the user why vectorization did not occur.
-class VectorizationReport {
+class LoopAccessReport {
   std::string Message;
   const Instruction *Instr;
 
+protected:
+  LoopAccessReport(const Twine &Message, const Instruction *I)
+      : Message(Message.str()), Instr(I) {}
+
 public:
-  VectorizationReport(const Instruction *I = nullptr)
-      : Message("loop not vectorized: "), Instr(I) {}
+  LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {}
 
-  template <typename A> VectorizationReport &operator<<(const A &Value) {
+  template <typename A> LoopAccessReport &operator<<(const A &Value) {
     raw_string_ostream Out(Message);
     Out << Value;
     return *this;
@@ -59,7 +62,7 @@ public:
   /// \brief Emit an analysis note for \p PassName with the debug location from
   /// the instruction in \p Message if available.  Otherwise use the location of
   /// \p TheLoop.
-  static void emitAnalysis(const VectorizationReport &Message,
+  static void emitAnalysis(const LoopAccessReport &Message,
                            const Function *TheFunction,
                            const Loop *TheLoop,
                            const char *PassName);
@@ -169,7 +172,7 @@ public:
 
   /// \brief The diagnostics report generated for the analysis.  E.g. why we
   /// couldn't analyze the loop.
-  Optional<VectorizationReport> &getReport() { return Report; }
+  Optional<LoopAccessReport> &getReport() { return Report; }
 
   /// \brief Used to ensure that if the analysis was run with speculating the
   /// value of symbolic strides, the client queries it with the same assumption.
@@ -184,7 +187,7 @@ private:
   /// pass.
   bool canAnalyzeLoop();
 
-  void emitAnalysis(VectorizationReport &Message);
+  void emitAnalysis(LoopAccessReport &Message);
 
   /// We need to check that all of the pointers in this list are disjoint
   /// at runtime.
@@ -206,7 +209,7 @@ private:
 
   /// \brief The diagnostics report generated for the analysis.  E.g. why we
   /// couldn't analyze the loop.
-  Optional<VectorizationReport> Report;
+  Optional<LoopAccessReport> Report;
 };
 
 Value *stripIntegerCast(Value *V);
index 68f9ee1cb4e227b7d7f11666679ec31c764dcfa3..550059519e20963dd997ebc14ffa1bf61f4df69c 100644 (file)
@@ -25,10 +25,10 @@ using namespace llvm;
 
 #define DEBUG_TYPE "loop-accesses"
 
-void VectorizationReport::emitAnalysis(const VectorizationReport &Message,
-                                       const Function *TheFunction,
-                                       const Loop *TheLoop,
-                                       const char *PassName) {
+void LoopAccessReport::emitAnalysis(const LoopAccessReport &Message,
+                                    const Function *TheFunction,
+                                    const Loop *TheLoop,
+                                    const char *PassName) {
   DebugLoc DL = TheLoop->getStartLoc();
   if (const Instruction *I = Message.getInstr())
     DL = I->getDebugLoc();
@@ -833,14 +833,14 @@ bool MemoryDepChecker::areDepsSafe(AccessAnalysis::DepCandidates &AccessSets,
 bool LoopAccessInfo::canAnalyzeLoop() {
     // We can only analyze innermost loops.
   if (!TheLoop->empty()) {
-    emitAnalysis(VectorizationReport() << "loop is not the innermost loop");
+    emitAnalysis(LoopAccessReport() << "loop is not the innermost loop");
     return false;
   }
 
   // We must have a single backedge.
   if (TheLoop->getNumBackEdges() != 1) {
     emitAnalysis(
-        VectorizationReport() <<
+        LoopAccessReport() <<
         "loop control flow is not understood by analyzer");
     return false;
   }
@@ -848,7 +848,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
   // We must have a single exiting block.
   if (!TheLoop->getExitingBlock()) {
     emitAnalysis(
-        VectorizationReport() <<
+        LoopAccessReport() <<
         "loop control flow is not understood by analyzer");
     return false;
   }
@@ -858,7 +858,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
   // instructions in the loop are executed the same number of times.
   if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) {
     emitAnalysis(
-        VectorizationReport() <<
+        LoopAccessReport() <<
         "loop control flow is not understood by analyzer");
     return false;
   }
@@ -870,7 +870,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
   // ScalarEvolution needs to be able to find the exit count.
   const SCEV *ExitCount = SE->getBackedgeTakenCount(TheLoop);
   if (ExitCount == SE->getCouldNotCompute()) {
-    emitAnalysis(VectorizationReport() <<
+    emitAnalysis(LoopAccessReport() <<
                  "could not determine number of loop iterations");
     DEBUG(dbgs() << "LAA: SCEV could not compute the loop exit count.\n");
     return false;
@@ -919,7 +919,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
 
         LoadInst *Ld = dyn_cast<LoadInst>(it);
         if (!Ld || (!Ld->isSimple() && !IsAnnotatedParallel)) {
-          emitAnalysis(VectorizationReport(Ld)
+          emitAnalysis(LoopAccessReport(Ld)
                        << "read with atomic ordering or volatile read");
           DEBUG(dbgs() << "LAA: Found a non-simple load.\n");
           CanVecMem = false;
@@ -935,13 +935,13 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
       if (it->mayWriteToMemory()) {
         StoreInst *St = dyn_cast<StoreInst>(it);
         if (!St) {
-          emitAnalysis(VectorizationReport(it) <<
+          emitAnalysis(LoopAccessReport(it) <<
                        "instruction cannot be vectorized");
           CanVecMem = false;
           return;
         }
         if (!St->isSimple() && !IsAnnotatedParallel) {
-          emitAnalysis(VectorizationReport(St)
+          emitAnalysis(LoopAccessReport(St)
                        << "write with atomic ordering or volatile write");
           DEBUG(dbgs() << "LAA: Found a non-simple store.\n");
           CanVecMem = false;
@@ -982,7 +982,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
 
     if (isUniform(Ptr)) {
       emitAnalysis(
-          VectorizationReport(ST)
+          LoopAccessReport(ST)
           << "write to a loop invariant address could not be vectorized");
       DEBUG(dbgs() << "LAA: We don't allow storing to uniform addresses\n");
       CanVecMem = false;
@@ -1083,7 +1083,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
   }
 
   if (NeedRTCheck && !CanDoRT) {
-    emitAnalysis(VectorizationReport() << "cannot identify array bounds");
+    emitAnalysis(LoopAccessReport() << "cannot identify array bounds");
     DEBUG(dbgs() << "LAA: We can't vectorize because we can't find " <<
           "the array bounds.\n");
     PtrRtCheck.reset();
@@ -1117,10 +1117,10 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
       if (!CanDoRT ||
           NumComparisons > VectorizerParams::RuntimeMemoryCheckThreshold) {
         if (!CanDoRT && NumComparisons > 0)
-          emitAnalysis(VectorizationReport()
+          emitAnalysis(LoopAccessReport()
                        << "cannot check memory dependencies at runtime");
         else
-          emitAnalysis(VectorizationReport()
+          emitAnalysis(LoopAccessReport()
                        << NumComparisons << " exceeds limit of "
                        << VectorizerParams::RuntimeMemoryCheckThreshold
                        << " dependent memory operations checked at runtime");
@@ -1135,7 +1135,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
   }
 
   if (!CanVecMem)
-    emitAnalysis(VectorizationReport() <<
+    emitAnalysis(LoopAccessReport() <<
                  "unsafe dependent memory operations in loop");
 
   DEBUG(dbgs() << "LAA: We" << (NeedRTCheck ? "" : " don't") <<
@@ -1151,7 +1151,7 @@ bool LoopAccessInfo::blockNeedsPredication(BasicBlock *BB, Loop *TheLoop,
   return !DT->dominates(BB, Latch);
 }
 
-void LoopAccessInfo::emitAnalysis(VectorizationReport &Message) {
+void LoopAccessInfo::emitAnalysis(LoopAccessReport &Message) {
   assert(!Report && "Multiple report generated");
   Report = Message;
 }
index a6dbeed6bc860f6f38820fd8628515c490ebffd7..ed4210b5bcf0b65dca9c8f351184f9ac2d4f0c9a 100644 (file)
@@ -224,6 +224,21 @@ class LoopVectorizationLegality;
 class LoopVectorizationCostModel;
 class LoopVectorizeHints;
 
+/// \brief This modifies LoopAccessReport to initialize message with
+/// loop-vectorizer-specific part.
+class VectorizationReport : public LoopAccessReport {
+public:
+  VectorizationReport(Instruction *I = nullptr)
+      : LoopAccessReport("loop not vectorized: ", I) {}
+
+  /// \brief This allows promotion of the loop-access analysis report into the
+  /// loop-vectorizer report.  It modifies the message to add the
+  /// loop-vectorizer-specific part of the message.
+  explicit VectorizationReport(const LoopAccessReport &R)
+      : LoopAccessReport(Twine("loop not vectorized: ") + R.str(),
+                         R.getInstr()) {}
+};
+
 /// InnerLoopVectorizer vectorizes loops which contain only one basic
 /// block to a specified vectorization factor (VF).
 /// This class performs the widening of scalars into vectors, or multiple
@@ -835,9 +850,11 @@ private:
   void collectStridedAccess(Value *LoadOrStoreInst);
 
   /// Report an analysis message to assist the user in diagnosing loops that are
-  /// not vectorized.
-  void emitAnalysis(const VectorizationReport &Message) {
-    VectorizationReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME);
+  /// not vectorized.  These are handled as LoopAccessReport rather than
+  /// VectorizationReport because the << operator of VectorizationReport returns
+  /// LoopAccessReport.
+  void emitAnalysis(const LoopAccessReport &Message) {
+    LoopAccessReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME);
   }
 
   unsigned NumPredStores;
@@ -972,9 +989,11 @@ private:
   bool isConsecutiveLoadOrStore(Instruction *I);
 
   /// Report an analysis message to assist the user in diagnosing loops that are
-  /// not vectorized.
-  void emitAnalysis(const VectorizationReport &Message) {
-    VectorizationReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME);
+  /// not vectorized.  These are handled as LoopAccessReport rather than
+  /// VectorizationReport because the << operator of VectorizationReport returns
+  /// LoopAccessReport.
+  void emitAnalysis(const LoopAccessReport &Message) {
+    LoopAccessReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME);
   }
 
   /// Values used only by @llvm.assume calls.
@@ -3837,7 +3856,7 @@ bool LoopVectorizationLegality::canVectorizeMemory() {
   LAI = &LAA->getInfo(TheLoop, Strides);
   auto &OptionalReport = LAI->getReport();
   if (OptionalReport)
-    emitAnalysis(*OptionalReport);
+    emitAnalysis(VectorizationReport(*OptionalReport));
   return LAI->canVectorizeMemory();
 }