forked from OSchip/llvm-project
[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:
parent
8b12afbeee
commit
d7350dbb85
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue