diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index a3dcb79ec34..71506ddc859 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -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; -public: - VectorizationReport(const Instruction *I = nullptr) - : Message("loop not vectorized: "), Instr(I) {} +protected: + LoopAccessReport(const Twine &Message, const Instruction *I) + : Message(Message.str()), Instr(I) {} - template VectorizationReport &operator<<(const A &Value) { +public: + LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {} + + template 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 &getReport() { return Report; } + Optional &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 Report; + Optional Report; }; Value *stripIntegerCast(Value *V); diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index 68f9ee1cb4e..550059519e2 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -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(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(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; } diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index a6dbeed6bc8..ed4210b5bcf 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -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(); }