Index: include/llvm/Analysis/LoopAccessAnalysis.h =================================================================== --- include/llvm/Analysis/LoopAccessAnalysis.h +++ include/llvm/Analysis/LoopAccessAnalysis.h @@ -36,15 +36,18 @@ /// 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 VectorizationReport &operator<<(const A &Value) { + template LoopAccessReport &operator<<(const A &Value) { raw_string_ostream Out(Message); Out << Value; return *this; @@ -58,7 +61,7 @@ /// \brief Emit an analysis note 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); }; @@ -160,13 +163,13 @@ /// \brief The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. - Optional &getReport() { return Report; } + Optional &getReport() { return Report; } private: /// \brief Analyze the loop. Substitute symbolic strides using Strides. void analyzeLoop(ValueToValueMap &Strides); - void emitAnalysis(VectorizationReport &Message); + void emitAnalysis(LoopAccessReport &Message); /// We need to check that all of the pointers in this list are disjoint /// at runtime. @@ -188,7 +191,8 @@ /// \brief The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. - Optional Report; + Optional Report; + #ifndef NDEBUG /// \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. Index: lib/Analysis/LoopAccessAnalysis.cpp =================================================================== --- lib/Analysis/LoopAccessAnalysis.cpp +++ lib/Analysis/LoopAccessAnalysis.cpp @@ -25,9 +25,9 @@ #define DEBUG_TYPE "loop-accesses" -void VectorizationReport::emitAnalysis(const VectorizationReport &Message, - const Function *TheFunction, - const Loop *TheLoop) { +void LoopAccessReport::emitAnalysis(const LoopAccessReport &Message, + const Function *TheFunction, + const Loop *TheLoop) { DebugLoc DL = TheLoop->getStartLoc(); if (const Instruction *I = Message.getInstr()) DL = I->getDebugLoc(); @@ -832,14 +832,14 @@ bool LoopAccessInfo::canAnalyzeLoop() { // We can only vectorize 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 vectorizer"); return false; } @@ -847,7 +847,7 @@ // We must have a single exiting block. if (!TheLoop->getExitingBlock()) { emitAnalysis( - VectorizationReport() << + LoopAccessReport() << "loop control flow is not understood by vectorizer"); return false; } @@ -857,7 +857,7 @@ // 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 vectorizer"); return false; } @@ -869,7 +869,7 @@ // 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; @@ -918,7 +918,7 @@ LoadInst *Ld = dyn_cast(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; @@ -934,13 +934,13 @@ if (it->mayWriteToMemory()) { StoreInst *St = dyn_cast(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; @@ -981,7 +981,7 @@ 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; @@ -1082,7 +1082,7 @@ } 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(); @@ -1116,10 +1116,10 @@ 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"); @@ -1134,7 +1134,7 @@ } if (!CanVecMem) - emitAnalysis(VectorizationReport() << + emitAnalysis(LoopAccessReport() << "unsafe dependent memory operations in loop"); DEBUG(dbgs() << "LAA: We" << (NeedRTCheck ? "" : " don't") << @@ -1154,7 +1154,7 @@ return blockNeedsPredication(BB, TheLoop, DT); } -void LoopAccessInfo::emitAnalysis(VectorizationReport &Message) { +void LoopAccessInfo::emitAnalysis(LoopAccessReport &Message) { assert(!Report && "Multiple report generated"); Report = Message; } Index: lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/LoopVectorize.cpp +++ lib/Transforms/Vectorize/LoopVectorize.cpp @@ -224,6 +224,21 @@ 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 @@ 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); + /// 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); } unsigned NumPredStores; @@ -969,9 +986,11 @@ 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); + /// 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); } /// Values used only by @llvm.assume calls. @@ -3835,7 +3854,7 @@ LAI = LAA->getInfo(TheLoop, Strides); auto &OptionalReport = LAI->getReport(); if (OptionalReport) - emitAnalysis(*OptionalReport); + emitAnalysis(VectorizationReport(*OptionalReport)); return LAI->canVectorizeMemory(); }