[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.

llvm-svn: 229632
This commit is contained in:
Adam Nemet 2015-02-18 03:44:25 +00:00
parent 8b12afbeee
commit d7350dbb85
3 changed files with 56 additions and 34 deletions

View File

@ -36,15 +36,18 @@ class SCEV;
/// Optimization analysis message produced during vectorization. Messages inform /// Optimization analysis message produced during vectorization. Messages inform
/// the user why vectorization did not occur. /// the user why vectorization did not occur.
class VectorizationReport { class LoopAccessReport {
std::string Message; std::string Message;
const Instruction *Instr; const Instruction *Instr;
public: protected:
VectorizationReport(const Instruction *I = nullptr) LoopAccessReport(const Twine &Message, const Instruction *I)
: Message("loop not vectorized: "), Instr(I) {} : Message(Message.str()), Instr(I) {}
template <typename A> VectorizationReport &operator<<(const A &Value) { public:
LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {}
template <typename A> LoopAccessReport &operator<<(const A &Value) {
raw_string_ostream Out(Message); raw_string_ostream Out(Message);
Out << Value; Out << Value;
return *this; return *this;
@ -59,7 +62,7 @@ public:
/// \brief Emit an analysis note for \p PassName with the debug location from /// \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 /// the instruction in \p Message if available. Otherwise use the location of
/// \p TheLoop. /// \p TheLoop.
static void emitAnalysis(const VectorizationReport &Message, static void emitAnalysis(const LoopAccessReport &Message,
const Function *TheFunction, const Function *TheFunction,
const Loop *TheLoop, const Loop *TheLoop,
const char *PassName); const char *PassName);
@ -169,7 +172,7 @@ public:
/// \brief The diagnostics report generated for the analysis. E.g. why we /// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop. /// 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 /// \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. /// value of symbolic strides, the client queries it with the same assumption.
@ -184,7 +187,7 @@ private:
/// pass. /// pass.
bool canAnalyzeLoop(); bool canAnalyzeLoop();
void emitAnalysis(VectorizationReport &Message); void emitAnalysis(LoopAccessReport &Message);
/// We need to check that all of the pointers in this list are disjoint /// We need to check that all of the pointers in this list are disjoint
/// at runtime. /// at runtime.
@ -206,7 +209,7 @@ private:
/// \brief The diagnostics report generated for the analysis. E.g. why we /// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop. /// couldn't analyze the loop.
Optional<VectorizationReport> Report; Optional<LoopAccessReport> Report;
}; };
Value *stripIntegerCast(Value *V); Value *stripIntegerCast(Value *V);

View File

@ -25,10 +25,10 @@ using namespace llvm;
#define DEBUG_TYPE "loop-accesses" #define DEBUG_TYPE "loop-accesses"
void VectorizationReport::emitAnalysis(const VectorizationReport &Message, void LoopAccessReport::emitAnalysis(const LoopAccessReport &Message,
const Function *TheFunction, const Function *TheFunction,
const Loop *TheLoop, const Loop *TheLoop,
const char *PassName) { const char *PassName) {
DebugLoc DL = TheLoop->getStartLoc(); DebugLoc DL = TheLoop->getStartLoc();
if (const Instruction *I = Message.getInstr()) if (const Instruction *I = Message.getInstr())
DL = I->getDebugLoc(); DL = I->getDebugLoc();
@ -833,14 +833,14 @@ bool MemoryDepChecker::areDepsSafe(AccessAnalysis::DepCandidates &AccessSets,
bool LoopAccessInfo::canAnalyzeLoop() { bool LoopAccessInfo::canAnalyzeLoop() {
// We can only analyze innermost loops. // We can only analyze innermost loops.
if (!TheLoop->empty()) { if (!TheLoop->empty()) {
emitAnalysis(VectorizationReport() << "loop is not the innermost loop"); emitAnalysis(LoopAccessReport() << "loop is not the innermost loop");
return false; return false;
} }
// We must have a single backedge. // We must have a single backedge.
if (TheLoop->getNumBackEdges() != 1) { if (TheLoop->getNumBackEdges() != 1) {
emitAnalysis( emitAnalysis(
VectorizationReport() << LoopAccessReport() <<
"loop control flow is not understood by analyzer"); "loop control flow is not understood by analyzer");
return false; return false;
} }
@ -848,7 +848,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
// We must have a single exiting block. // We must have a single exiting block.
if (!TheLoop->getExitingBlock()) { if (!TheLoop->getExitingBlock()) {
emitAnalysis( emitAnalysis(
VectorizationReport() << LoopAccessReport() <<
"loop control flow is not understood by analyzer"); "loop control flow is not understood by analyzer");
return false; return false;
} }
@ -858,7 +858,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
// instructions in the loop are executed the same number of times. // instructions in the loop are executed the same number of times.
if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) { if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) {
emitAnalysis( emitAnalysis(
VectorizationReport() << LoopAccessReport() <<
"loop control flow is not understood by analyzer"); "loop control flow is not understood by analyzer");
return false; return false;
} }
@ -870,7 +870,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
// ScalarEvolution needs to be able to find the exit count. // ScalarEvolution needs to be able to find the exit count.
const SCEV *ExitCount = SE->getBackedgeTakenCount(TheLoop); const SCEV *ExitCount = SE->getBackedgeTakenCount(TheLoop);
if (ExitCount == SE->getCouldNotCompute()) { if (ExitCount == SE->getCouldNotCompute()) {
emitAnalysis(VectorizationReport() << emitAnalysis(LoopAccessReport() <<
"could not determine number of loop iterations"); "could not determine number of loop iterations");
DEBUG(dbgs() << "LAA: SCEV could not compute the loop exit count.\n"); DEBUG(dbgs() << "LAA: SCEV could not compute the loop exit count.\n");
return false; return false;
@ -919,7 +919,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
LoadInst *Ld = dyn_cast<LoadInst>(it); LoadInst *Ld = dyn_cast<LoadInst>(it);
if (!Ld || (!Ld->isSimple() && !IsAnnotatedParallel)) { if (!Ld || (!Ld->isSimple() && !IsAnnotatedParallel)) {
emitAnalysis(VectorizationReport(Ld) emitAnalysis(LoopAccessReport(Ld)
<< "read with atomic ordering or volatile read"); << "read with atomic ordering or volatile read");
DEBUG(dbgs() << "LAA: Found a non-simple load.\n"); DEBUG(dbgs() << "LAA: Found a non-simple load.\n");
CanVecMem = false; CanVecMem = false;
@ -935,13 +935,13 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
if (it->mayWriteToMemory()) { if (it->mayWriteToMemory()) {
StoreInst *St = dyn_cast<StoreInst>(it); StoreInst *St = dyn_cast<StoreInst>(it);
if (!St) { if (!St) {
emitAnalysis(VectorizationReport(it) << emitAnalysis(LoopAccessReport(it) <<
"instruction cannot be vectorized"); "instruction cannot be vectorized");
CanVecMem = false; CanVecMem = false;
return; return;
} }
if (!St->isSimple() && !IsAnnotatedParallel) { if (!St->isSimple() && !IsAnnotatedParallel) {
emitAnalysis(VectorizationReport(St) emitAnalysis(LoopAccessReport(St)
<< "write with atomic ordering or volatile write"); << "write with atomic ordering or volatile write");
DEBUG(dbgs() << "LAA: Found a non-simple store.\n"); DEBUG(dbgs() << "LAA: Found a non-simple store.\n");
CanVecMem = false; CanVecMem = false;
@ -982,7 +982,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
if (isUniform(Ptr)) { if (isUniform(Ptr)) {
emitAnalysis( emitAnalysis(
VectorizationReport(ST) LoopAccessReport(ST)
<< "write to a loop invariant address could not be vectorized"); << "write to a loop invariant address could not be vectorized");
DEBUG(dbgs() << "LAA: We don't allow storing to uniform addresses\n"); DEBUG(dbgs() << "LAA: We don't allow storing to uniform addresses\n");
CanVecMem = false; CanVecMem = false;
@ -1083,7 +1083,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
} }
if (NeedRTCheck && !CanDoRT) { 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 " << DEBUG(dbgs() << "LAA: We can't vectorize because we can't find " <<
"the array bounds.\n"); "the array bounds.\n");
PtrRtCheck.reset(); PtrRtCheck.reset();
@ -1117,10 +1117,10 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
if (!CanDoRT || if (!CanDoRT ||
NumComparisons > VectorizerParams::RuntimeMemoryCheckThreshold) { NumComparisons > VectorizerParams::RuntimeMemoryCheckThreshold) {
if (!CanDoRT && NumComparisons > 0) if (!CanDoRT && NumComparisons > 0)
emitAnalysis(VectorizationReport() emitAnalysis(LoopAccessReport()
<< "cannot check memory dependencies at runtime"); << "cannot check memory dependencies at runtime");
else else
emitAnalysis(VectorizationReport() emitAnalysis(LoopAccessReport()
<< NumComparisons << " exceeds limit of " << NumComparisons << " exceeds limit of "
<< VectorizerParams::RuntimeMemoryCheckThreshold << VectorizerParams::RuntimeMemoryCheckThreshold
<< " dependent memory operations checked at runtime"); << " dependent memory operations checked at runtime");
@ -1135,7 +1135,7 @@ void LoopAccessInfo::analyzeLoop(ValueToValueMap &Strides) {
} }
if (!CanVecMem) if (!CanVecMem)
emitAnalysis(VectorizationReport() << emitAnalysis(LoopAccessReport() <<
"unsafe dependent memory operations in loop"); "unsafe dependent memory operations in loop");
DEBUG(dbgs() << "LAA: We" << (NeedRTCheck ? "" : " don't") << DEBUG(dbgs() << "LAA: We" << (NeedRTCheck ? "" : " don't") <<
@ -1151,7 +1151,7 @@ bool LoopAccessInfo::blockNeedsPredication(BasicBlock *BB, Loop *TheLoop,
return !DT->dominates(BB, Latch); return !DT->dominates(BB, Latch);
} }
void LoopAccessInfo::emitAnalysis(VectorizationReport &Message) { void LoopAccessInfo::emitAnalysis(LoopAccessReport &Message) {
assert(!Report && "Multiple report generated"); assert(!Report && "Multiple report generated");
Report = Message; Report = Message;
} }

View File

@ -224,6 +224,21 @@ class LoopVectorizationLegality;
class LoopVectorizationCostModel; class LoopVectorizationCostModel;
class LoopVectorizeHints; 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 /// InnerLoopVectorizer vectorizes loops which contain only one basic
/// block to a specified vectorization factor (VF). /// block to a specified vectorization factor (VF).
/// This class performs the widening of scalars into vectors, or multiple /// This class performs the widening of scalars into vectors, or multiple
@ -835,9 +850,11 @@ private:
void collectStridedAccess(Value *LoadOrStoreInst); void collectStridedAccess(Value *LoadOrStoreInst);
/// Report an analysis message to assist the user in diagnosing loops that are /// Report an analysis message to assist the user in diagnosing loops that are
/// not vectorized. /// not vectorized. These are handled as LoopAccessReport rather than
void emitAnalysis(const VectorizationReport &Message) { /// VectorizationReport because the << operator of VectorizationReport returns
VectorizationReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME); /// LoopAccessReport.
void emitAnalysis(const LoopAccessReport &Message) {
LoopAccessReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME);
} }
unsigned NumPredStores; unsigned NumPredStores;
@ -972,9 +989,11 @@ private:
bool isConsecutiveLoadOrStore(Instruction *I); bool isConsecutiveLoadOrStore(Instruction *I);
/// Report an analysis message to assist the user in diagnosing loops that are /// Report an analysis message to assist the user in diagnosing loops that are
/// not vectorized. /// not vectorized. These are handled as LoopAccessReport rather than
void emitAnalysis(const VectorizationReport &Message) { /// VectorizationReport because the << operator of VectorizationReport returns
VectorizationReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME); /// LoopAccessReport.
void emitAnalysis(const LoopAccessReport &Message) {
LoopAccessReport::emitAnalysis(Message, TheFunction, TheLoop, LV_NAME);
} }
/// Values used only by @llvm.assume calls. /// Values used only by @llvm.assume calls.
@ -3837,7 +3856,7 @@ bool LoopVectorizationLegality::canVectorizeMemory() {
LAI = &LAA->getInfo(TheLoop, Strides); LAI = &LAA->getInfo(TheLoop, Strides);
auto &OptionalReport = LAI->getReport(); auto &OptionalReport = LAI->getReport();
if (OptionalReport) if (OptionalReport)
emitAnalysis(*OptionalReport); emitAnalysis(VectorizationReport(*OptionalReport));
return LAI->canVectorizeMemory(); return LAI->canVectorizeMemory();
} }