diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h --- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h +++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h @@ -57,6 +57,7 @@ #define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZE_H #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/PassManager.h" #include "llvm/Support/CommandLine.h" #include @@ -170,9 +171,12 @@ /// purposes along with the corresponding optimization remark \p RemarkName. /// If \p I is passed, it is an instruction that prevents vectorization. /// Otherwise, the loop \p TheLoop is used for the location of the remark. -void reportVectorizationFailure(const StringRef DebugMsg, - const StringRef OREMsg, const StringRef ORETag, - OptimizationRemarkEmitter *ORE, Loop *TheLoop, Instruction *I = nullptr); +/// Optionally, a function can be passed to add extra arguments for further +/// explanation in optimization reports. +void reportVectorizationFailure( + const StringRef DebugMsg, const StringRef OREMsg, const StringRef ORETag, + OptimizationRemarkEmitter *ORE, Loop *TheLoop, Instruction *I = nullptr, + std::function ExtraInfo = nullptr); } // end namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp @@ -15,11 +15,14 @@ // #include "llvm/Transforms/Vectorize/LoopVectorizationLegality.h" #include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/VectorUtils.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PatternMatch.h" #include "llvm/Transforms/Vectorize/LoopVectorize.h" +#include +#include using namespace llvm; using namespace PatternMatch; @@ -1074,9 +1077,28 @@ // We must have a single backedge. if (Lp->getNumBackEdges() != 1) { - reportVectorizationFailure("The loop must have a single backedge", - "loop control flow is not understood by vectorizer", - "CFGNotUnderstood", ORE, TheLoop); + auto ExtraInfoCb = [&](OptimizationRemarkAnalysis &Analysis) { + SmallVector LoopLatches; + auto Head = Lp->getHeader(); + Lp->getLoopLatches(LoopLatches); + for (auto Latch : LoopLatches) { + auto T = Latch->getTerminator(); + for (unsigned i = 0; i < T->getNumSuccessors(); i++) { + if (T->getSuccessor(i) == Head) { + if (T->getNumSuccessors() > 1) { + std::string Description = "backedge (condition "; + Analysis << ore::NV(Description + (i ? "false)" : "true)"), T); + } else { + Analysis << ore::NV("backedge", T); + } + } + } + } + }; + reportVectorizationFailure( + "The loop must have a single backedge", + "loop control flow is not understood by vectorizer", "CFGNotUnderstood", + ORE, TheLoop, nullptr, ExtraInfoCb); if (DoExtraAnalysis) Result = false; else @@ -1085,9 +1107,22 @@ // We must have a single exiting block. if (!Lp->getExitingBlock()) { - reportVectorizationFailure("The loop must have an exiting block", - "loop control flow is not understood by vectorizer", - "CFGNotUnderstood", ORE, TheLoop); + auto ExtraInfoCb = [&](OptimizationRemarkAnalysis &Analysis) { + SmallVector Exits; + Lp->getExitingBlocks(Exits); + if (Exits.empty()) { + Analysis << ". There is no exiting block."; + return; + } + Analysis << ". Exiting blocks: "; + for (auto Exit : Exits) { + Analysis << ore::NV("exiting block terminator", Exit->getTerminator()); + } + }; + reportVectorizationFailure( + "The loop must have a single exiting block", + "loop control flow is not understood by vectorizer", "CFGNotUnderstood", + ORE, TheLoop, nullptr, ExtraInfoCb); if (DoExtraAnalysis) Result = false; else @@ -1098,9 +1133,25 @@ // checked at the end of each iteration. With that we can assume that all // instructions in the loop are executed the same number of times. if (Lp->getExitingBlock() != Lp->getLoopLatch()) { - reportVectorizationFailure("The exiting block is not the loop latch", - "loop control flow is not understood by vectorizer", - "CFGNotUnderstood", ORE, TheLoop); + auto ExtraInfoCb = [&](OptimizationRemarkAnalysis &Analysis) { + if (!Lp->getExitingBlock() || !Lp->getLoopLatch()) + return; + Analysis << ore::NV("exiting block terminator", + Lp->getExitingBlock()->getTerminator()) + << ore::NV("loop latch terminator", + Lp->getLoopLatch()->getTerminator()); + }; + Instruction *Term = nullptr; + // This will highlight one of the relevant BBs in case extra info is not + // included + if (Lp->getExitingBlock()) + Term = Lp->getExitingBlock()->getTerminator(); + else if (Lp->getLoopLatch()) + Term = Lp->getLoopLatch()->getTerminator(); + reportVectorizationFailure( + "The exiting block is not the loop latch", + "loop control flow is not understood by vectorizer", "CFGNotUnderstood", + ORE, TheLoop, Term, ExtraInfoCb); if (DoExtraAnalysis) Result = false; else diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -879,13 +879,20 @@ namespace llvm { -void reportVectorizationFailure(const StringRef DebugMsg, - const StringRef OREMsg, const StringRef ORETag, - OptimizationRemarkEmitter *ORE, Loop *TheLoop, Instruction *I) { +void reportVectorizationFailure( + const StringRef DebugMsg, const StringRef OREMsg, const StringRef ORETag, + OptimizationRemarkEmitter *ORE, Loop *TheLoop, Instruction *I, + std::function ExtraInfo) { LLVM_DEBUG(debugVectorizationFailure(DebugMsg, I)); LoopVectorizeHints Hints(TheLoop, true /* doesn't matter */, *ORE); - ORE->emit(createLVAnalysis(Hints.vectorizeAnalysisPassName(), - ORETag, TheLoop, I) << OREMsg); + auto Analysis = + createLVAnalysis(Hints.vectorizeAnalysisPassName(), ORETag, TheLoop, I) + << OREMsg; + Analysis << ore::setExtraArgs() << ore::NV("DebugMsg", DebugMsg); + if (ORE->allowExtraAnalysis(DEBUG_TYPE) && ExtraInfo) { + ExtraInfo(Analysis); + } + ORE->emit(Analysis); } } // end namespace llvm