From 4db669fb26764b55bd9c0b8b2c2b917b135efe24 Mon Sep 17 00:00:00 2001 From: Adam Nemet Date: Thu, 19 Feb 2015 19:15:15 +0000 Subject: [PATCH] [LoopAccesses] Split out LoopAccessReport from VectorizerReport 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@229897 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/LoopAccessAnalysis.h | 21 +++++++------ lib/Analysis/LoopAccessAnalysis.cpp | 36 +++++++++++----------- lib/Transforms/Vectorize/LoopVectorize.cpp | 33 +++++++++++++++----- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 91b572b6ae6..a2f938ca67c 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); @@ -171,7 +174,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. @@ -186,7 +189,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. @@ -208,7 +211,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 8588e611bc8..3e86cafd14f 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -50,10 +50,10 @@ bool VectorizerParams::isInterleaveForced() { return ::VectorizationInterleave.getNumOccurrences() > 0; } -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(); @@ -858,14 +858,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; } @@ -873,7 +873,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; } @@ -883,7 +883,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; } @@ -895,7 +895,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; @@ -944,7 +944,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; @@ -960,13 +960,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; @@ -1007,7 +1007,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; @@ -1108,7 +1108,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(); @@ -1142,10 +1142,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"); @@ -1160,7 +1160,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") << @@ -1176,7 +1176,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 reports generated"); Report = Message; } diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index e39375fa929..3b3cd5e1389 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -203,6 +203,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 @@ -814,9 +829,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; @@ -951,9 +968,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. @@ -3817,7 +3836,7 @@ bool LoopVectorizationLegality::canVectorizeMemory() { LAI = &LAA->getInfo(TheLoop, Strides); auto &OptionalReport = LAI->getReport(); if (OptionalReport) - emitAnalysis(*OptionalReport); + emitAnalysis(VectorizationReport(*OptionalReport)); return LAI->canVectorizeMemory(); }