1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[LAA, LV] Port to new streaming interface for opt remarks. Update LV

(Recommit after making sure IsVerbose gets properly initialized in
DiagnosticInfoOptimizationBase.  See previous commit that takes care of
this.)

OptimizationRemarkAnalysis directly takes the role of the report that is
generated by LAA.

Then we need the magic to be able to turn an LAA remark into an LV
remark.  This is done via a new OptimizationRemark ctor.

llvm-svn: 282813
This commit is contained in:
Adam Nemet 2016-09-30 00:01:30 +00:00
parent a367afa8b2
commit abdb6ed3d0
4 changed files with 78 additions and 30 deletions

View File

@ -22,6 +22,7 @@
#include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/LoopPassManager.h" #include "llvm/Analysis/LoopPassManager.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/ValueHandle.h" #include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -595,7 +596,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.
const Optional<LoopAccessReport> &getReport() const { return Report; } const OptimizationRemarkAnalysis *getReport() const { return Report.get(); }
/// \brief the Memory Dependence Checker which can determine the /// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses. /// loop-independent and loop-carried dependences between memory accesses.
@ -646,7 +647,8 @@ private:
/// LAA does not directly emits the remarks. Instead it stores it which the /// LAA does not directly emits the remarks. Instead it stores it which the
/// client can retrieve and presents as its own analysis /// client can retrieve and presents as its own analysis
/// (e.g. -Rpass-analysis=loop-vectorize). /// (e.g. -Rpass-analysis=loop-vectorize).
void recordAnalysis(LoopAccessReport &Message); OptimizationRemarkAnalysis &recordAnalysis(StringRef RemarkName,
Instruction *Instr = nullptr);
/// \brief Collect memory access with loop invariant strides. /// \brief Collect memory access with loop invariant strides.
/// ///
@ -680,7 +682,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<LoopAccessReport> Report; std::unique_ptr<OptimizationRemarkAnalysis> Report;
/// \brief If an access has a symbolic strides, this maps the pointer value to /// \brief If an access has a symbolic strides, this maps the pointer value to
/// the stride symbol. /// the stride symbol.

View File

@ -408,6 +408,24 @@ public:
: DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc), : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
PassName(PassName), RemarkName(RemarkName), CodeRegion(CodeRegion) {} PassName(PassName), RemarkName(RemarkName), CodeRegion(CodeRegion) {}
/// \brief This is ctor variant allows a pass to build an optimization remark
/// from an existing remark.
///
/// This is useful when a transformation pass (e.g LV) wants to emit a remark
/// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
/// remark. The string \p Prepend will be emitted before the original
/// message.
DiagnosticInfoOptimizationBase(const char *PassName, StringRef Prepend,
const DiagnosticInfoOptimizationBase &Orig)
: DiagnosticInfoWithDebugLocBase((DiagnosticKind)Orig.getKind(),
Orig.getSeverity(), Orig.getFunction(),
Orig.getDebugLoc()),
PassName(PassName), RemarkName(Orig.RemarkName),
CodeRegion(Orig.getCodeRegion()) {
*this << Prepend;
std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
}
/// Legacy interface. /// Legacy interface.
/// \p PassName is the name of the pass emitting this diagnostic. /// \p PassName is the name of the pass emitting this diagnostic.
/// \p Fn is the function where the diagnostic is being emitted. \p DLoc is /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
@ -577,6 +595,17 @@ public:
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
const DebugLoc &DLoc, Value *CodeRegion); const DebugLoc &DLoc, Value *CodeRegion);
/// \brief This is ctor variant allows a pass to build an optimization remark
/// from an existing remark.
///
/// This is useful when a transformation pass (e.g LV) wants to emit a remark
/// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
/// remark. The string \p Prepend will be emitted before the original
/// message.
OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
const OptimizationRemarkAnalysis &Orig)
: DiagnosticInfoOptimizationBase(PassName, Prepend, Orig) {}
/// \brief Same as above but \p Inst is used to derive code region and debug /// \brief Same as above but \p Inst is used to derive code region and debug
/// location. /// location.
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,

View File

@ -1482,23 +1482,23 @@ bool LoopAccessInfo::canAnalyzeLoop() {
// We can only analyze innermost loops. // We can only analyze innermost loops.
if (!TheLoop->empty()) { if (!TheLoop->empty()) {
DEBUG(dbgs() << "LAA: loop is not the innermost loop\n"); DEBUG(dbgs() << "LAA: loop is not the innermost loop\n");
recordAnalysis(LoopAccessReport() << "loop is not the innermost loop"); recordAnalysis("NotInnerMostLoop") << "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) {
DEBUG(dbgs() << "LAA: loop control flow is not understood by analyzer\n"); DEBUG(dbgs() << "LAA: loop control flow is not understood by analyzer\n");
recordAnalysis(LoopAccessReport() recordAnalysis("CFGNotUnderstood")
<< "loop control flow is not understood by analyzer"); << "loop control flow is not understood by analyzer";
return false; return false;
} }
// We must have a single exiting block. // We must have a single exiting block.
if (!TheLoop->getExitingBlock()) { if (!TheLoop->getExitingBlock()) {
DEBUG(dbgs() << "LAA: loop control flow is not understood by analyzer\n"); DEBUG(dbgs() << "LAA: loop control flow is not understood by analyzer\n");
recordAnalysis(LoopAccessReport() recordAnalysis("CFGNotUnderstood")
<< "loop control flow is not understood by analyzer"); << "loop control flow is not understood by analyzer";
return false; return false;
} }
@ -1507,16 +1507,16 @@ 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()) {
DEBUG(dbgs() << "LAA: loop control flow is not understood by analyzer\n"); DEBUG(dbgs() << "LAA: loop control flow is not understood by analyzer\n");
recordAnalysis(LoopAccessReport() recordAnalysis("CFGNotUnderstood")
<< "loop control flow is not understood by analyzer"); << "loop control flow is not understood by analyzer";
return false; return false;
} }
// ScalarEvolution needs to be able to find the exit count. // ScalarEvolution needs to be able to find the exit count.
const SCEV *ExitCount = PSE->getBackedgeTakenCount(); const SCEV *ExitCount = PSE->getBackedgeTakenCount();
if (ExitCount == PSE->getSE()->getCouldNotCompute()) { if (ExitCount == PSE->getSE()->getCouldNotCompute()) {
recordAnalysis(LoopAccessReport() recordAnalysis("CantComputeNumberOfIterations")
<< "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;
} }
@ -1565,8 +1565,8 @@ void LoopAccessInfo::analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
auto *Ld = dyn_cast<LoadInst>(&I); auto *Ld = dyn_cast<LoadInst>(&I);
if (!Ld || (!Ld->isSimple() && !IsAnnotatedParallel)) { if (!Ld || (!Ld->isSimple() && !IsAnnotatedParallel)) {
recordAnalysis(LoopAccessReport(Ld) recordAnalysis("NonSimpleLoad", 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;
return; return;
@ -1583,14 +1583,14 @@ void LoopAccessInfo::analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
if (I.mayWriteToMemory()) { if (I.mayWriteToMemory()) {
auto *St = dyn_cast<StoreInst>(&I); auto *St = dyn_cast<StoreInst>(&I);
if (!St) { if (!St) {
recordAnalysis(LoopAccessReport(St) recordAnalysis("CantVectorizeInstruction", St)
<< "instruction cannot be vectorized"); << "instruction cannot be vectorized";
CanVecMem = false; CanVecMem = false;
return; return;
} }
if (!St->isSimple() && !IsAnnotatedParallel) { if (!St->isSimple() && !IsAnnotatedParallel) {
recordAnalysis(LoopAccessReport(St) recordAnalysis("NonSimpleStore", 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;
return; return;
@ -1698,7 +1698,7 @@ void LoopAccessInfo::analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
bool CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(*PtrRtChecking, PSE->getSE(), bool CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(*PtrRtChecking, PSE->getSE(),
TheLoop, SymbolicStrides); TheLoop, SymbolicStrides);
if (!CanDoRTIfNeeded) { if (!CanDoRTIfNeeded) {
recordAnalysis(LoopAccessReport() << "cannot identify array bounds"); recordAnalysis("CantIdentifyArrayBounds") << "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");
CanVecMem = false; CanVecMem = false;
@ -1729,8 +1729,8 @@ void LoopAccessInfo::analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
// Check that we found the bounds for the pointer. // Check that we found the bounds for the pointer.
if (!CanDoRTIfNeeded) { if (!CanDoRTIfNeeded) {
recordAnalysis(LoopAccessReport() recordAnalysis("CantCheckMemDepsAtRunTime")
<< "cannot check memory dependencies at runtime"); << "cannot check memory dependencies at runtime";
DEBUG(dbgs() << "LAA: Can't vectorize with memory checks\n"); DEBUG(dbgs() << "LAA: Can't vectorize with memory checks\n");
CanVecMem = false; CanVecMem = false;
return; return;
@ -1745,12 +1745,11 @@ void LoopAccessInfo::analyzeLoop(AliasAnalysis *AA, LoopInfo *LI,
<< (PtrRtChecking->Need ? "" : " don't") << (PtrRtChecking->Need ? "" : " don't")
<< " need runtime memory checks.\n"); << " need runtime memory checks.\n");
else { else {
recordAnalysis( recordAnalysis("UnsafeMemDep")
LoopAccessReport()
<< "unsafe dependent memory operations in loop. Use " << "unsafe dependent memory operations in loop. Use "
"#pragma loop distribute(enable) to allow loop distribution " "#pragma loop distribute(enable) to allow loop distribution "
"to attempt to isolate the offending operations into a separate " "to attempt to isolate the offending operations into a separate "
"loop"); "loop";
DEBUG(dbgs() << "LAA: unsafe dependent memory operations in loop\n"); DEBUG(dbgs() << "LAA: unsafe dependent memory operations in loop\n");
} }
} }
@ -1764,9 +1763,24 @@ bool LoopAccessInfo::blockNeedsPredication(BasicBlock *BB, Loop *TheLoop,
return !DT->dominates(BB, Latch); return !DT->dominates(BB, Latch);
} }
void LoopAccessInfo::recordAnalysis(LoopAccessReport &Message) { OptimizationRemarkAnalysis &LoopAccessInfo::recordAnalysis(StringRef RemarkName,
Instruction *I) {
assert(!Report && "Multiple reports generated"); assert(!Report && "Multiple reports generated");
Report = Message;
Value *CodeRegion = TheLoop->getHeader();
DebugLoc DL = TheLoop->getStartLoc();
if (I) {
CodeRegion = I->getParent();
// If there is no debug location attached to the instruction, revert back to
// using the loop's.
if (I->getDebugLoc())
DL = I->getDebugLoc();
}
Report = make_unique<OptimizationRemarkAnalysis>(DEBUG_TYPE, RemarkName, DL,
CodeRegion);
return *Report;
} }
bool LoopAccessInfo::isUniform(Value *V) const { bool LoopAccessInfo::isUniform(Value *V) const {
@ -1974,7 +1988,7 @@ void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const {
} }
if (Report) if (Report)
OS.indent(Depth) << "Report: " << Report->str() << "\n"; OS.indent(Depth) << "Report: " << Report->getMsg() << "\n";
if (auto *Dependences = DepChecker->getDependences()) { if (auto *Dependences = DepChecker->getDependences()) {
OS.indent(Depth) << "Dependences:\n"; OS.indent(Depth) << "Dependences:\n";

View File

@ -5505,9 +5505,12 @@ void LoopVectorizationLegality::collectLoopUniforms() {
bool LoopVectorizationLegality::canVectorizeMemory() { bool LoopVectorizationLegality::canVectorizeMemory() {
LAI = &(*GetLAA)(*TheLoop); LAI = &(*GetLAA)(*TheLoop);
InterleaveInfo.setLAI(LAI); InterleaveInfo.setLAI(LAI);
auto &OptionalReport = LAI->getReport(); const OptimizationRemarkAnalysis *LAR = LAI->getReport();
if (OptionalReport) if (LAR) {
emitAnalysis(VectorizationReport(*OptionalReport)); OptimizationRemarkAnalysis VR(Hints->vectorizeAnalysisPassName(),
"loop not vectorized: ", *LAR);
ORE->emit(VR);
}
if (!LAI->canVectorizeMemory()) if (!LAI->canVectorizeMemory())
return false; return false;