[Polly] [OptDiag] Updating Polly Diagnostics Remarks

Utilizing newer LLVM diagnostic remark API in order to enable use of
opt-viewer tool. Polly Diagnostic Remarks also now appear in YAML
remark file.

In this patch, I've added the OptimizationRemarkEmitter into certain
classes where remarks are being emitted and update the remark emit calls
itself. I also provide each remark a BasicBlock or Instruction from where
it is being called, in order to compute the hotness of the remark.

Patch by Tarun Rajendran!

Differential Revision: https://reviews.llvm.org/D35399

llvm-svn: 308233
This commit is contained in:
Eli Friedman 2017-07-17 23:58:33 +00:00
parent 7828c88525
commit e737fc120e
9 changed files with 375 additions and 65 deletions

View File

@ -52,6 +52,7 @@
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionInfo.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include <map> #include <map>
@ -526,7 +527,8 @@ private:
public: public:
ScopDetection(Function &F, const DominatorTree &DT, ScalarEvolution &SE, ScopDetection(Function &F, const DominatorTree &DT, ScalarEvolution &SE,
LoopInfo &LI, RegionInfo &RI, AliasAnalysis &AA); LoopInfo &LI, RegionInfo &RI, AliasAnalysis &AA,
OptimizationRemarkEmitter &ORE);
/// Get the RegionInfo stored in this pass. /// Get the RegionInfo stored in this pass.
/// ///
@ -607,6 +609,9 @@ public:
static ScopDetection::LoopStats static ScopDetection::LoopStats
countBeneficialLoops(Region *R, ScalarEvolution &SE, LoopInfo &LI, countBeneficialLoops(Region *R, ScalarEvolution &SE, LoopInfo &LI,
unsigned MinProfitableTrips); unsigned MinProfitableTrips);
/// OptimizationRemarkEmitter object used to emit diagnostic remarks
OptimizationRemarkEmitter &ORE;
}; };
struct ScopAnalysis : public AnalysisInfoMixin<ScopAnalysis> { struct ScopAnalysis : public AnalysisInfoMixin<ScopAnalysis> {

View File

@ -25,6 +25,7 @@
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/BasicBlock.h" #include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Value.h" #include "llvm/IR/Value.h"
@ -59,7 +60,8 @@ class RejectLog;
/// Remember to at least track failures (-polly-detect-track-failures). /// Remember to at least track failures (-polly-detect-track-failures).
/// @param P The region delimiters (entry & exit) we emit remarks for. /// @param P The region delimiters (entry & exit) we emit remarks for.
/// @param Log The error log containing all messages being emitted as remark. /// @param Log The error log containing all messages being emitted as remark.
void emitRejectionRemarks(const BBPair &P, const RejectLog &Log); void emitRejectionRemarks(const BBPair &P, const RejectLog &Log,
OptimizationRemarkEmitter &ORE);
// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) // Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum class RejectReasonKind { enum class RejectReasonKind {
@ -123,6 +125,16 @@ public:
virtual ~RejectReason() {} virtual ~RejectReason() {}
/// Generate the remark name to identify this remark.
///
/// @return A short string that identifies the error.
virtual std::string getRemarkName() const = 0;
/// Get the Basic Block containing this remark.
///
/// @return The Basic Block containing this remark.
virtual const Value *getRemarkBB() const = 0;
/// Generate a reasonable diagnostic message describing this error. /// Generate a reasonable diagnostic message describing this error.
/// ///
/// @return A debug message representing this error. /// @return A debug message representing this error.
@ -203,6 +215,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
//@} //@}
@ -225,6 +239,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
@ -249,6 +265,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
@ -263,6 +281,7 @@ public:
class ReportAffFunc : public RejectReason { class ReportAffFunc : public RejectReason {
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
protected:
// The instruction that caused non-affinity to occur. // The instruction that caused non-affinity to occur.
const Instruction *Inst; const Instruction *Inst;
@ -301,6 +320,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -326,6 +347,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -349,6 +372,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -383,6 +408,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -402,6 +429,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -421,6 +450,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -445,6 +476,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
//@} //@}
@ -476,6 +509,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
//@} //@}
@ -501,6 +536,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
//@} //@}
@ -532,6 +569,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
@ -560,6 +599,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
@ -588,6 +629,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
@ -612,6 +655,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
@ -650,6 +695,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
@ -670,6 +717,7 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
//@} //@}
}; };
@ -692,6 +740,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
//@} //@}
@ -713,6 +763,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
//@} //@}
@ -734,6 +786,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
//@} //@}
@ -755,6 +809,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
@ -777,6 +833,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
@ -801,6 +859,8 @@ public:
/// @name RejectReason interface /// @name RejectReason interface
//@{ //@{
virtual std::string getRemarkName() const override;
virtual const Value *getRemarkBB() const override;
virtual std::string getMessage() const override; virtual std::string getMessage() const override;
virtual const DebugLoc &getDebugLoc() const override; virtual const DebugLoc &getDebugLoc() const override;
virtual std::string getEndUserMessage() const override; virtual std::string getEndUserMessage() const override;

View File

@ -1658,6 +1658,9 @@ private:
/// The context of the SCoP created during SCoP detection. /// The context of the SCoP created during SCoP detection.
ScopDetection::DetectionContext &DC; ScopDetection::DetectionContext &DC;
/// OptimizationRemarkEmitter object for displaying diagnostic remarks
OptimizationRemarkEmitter &ORE;
/// Isl context. /// Isl context.
/// ///
/// We need a shared_ptr with reference counter to delete the context when all /// We need a shared_ptr with reference counter to delete the context when all
@ -1822,7 +1825,7 @@ private:
/// Scop constructor; invoked from ScopBuilder::buildScop. /// Scop constructor; invoked from ScopBuilder::buildScop.
Scop(Region &R, ScalarEvolution &SE, LoopInfo &LI, Scop(Region &R, ScalarEvolution &SE, LoopInfo &LI,
ScopDetection::DetectionContext &DC); ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE);
//@} //@}
@ -2453,10 +2456,12 @@ public:
/// @param Loc The location in the source that caused this assumption. /// @param Loc The location in the source that caused this assumption.
/// @param Sign Enum to indicate if the assumptions in @p Set are positive /// @param Sign Enum to indicate if the assumptions in @p Set are positive
/// (needed/assumptions) or negative (invalid/restrictions). /// (needed/assumptions) or negative (invalid/restrictions).
/// @param BB The block in which this assumption was taken. Used to
/// calculate hotness when emitting remark.
/// ///
/// @returns True if the assumption is not trivial. /// @returns True if the assumption is not trivial.
bool trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, bool trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set,
DebugLoc Loc, AssumptionSign Sign); DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB);
/// Add assumptions to assumed context. /// Add assumptions to assumed context.
/// ///
@ -2474,8 +2479,10 @@ public:
/// @param Loc The location in the source that caused this assumption. /// @param Loc The location in the source that caused this assumption.
/// @param Sign Enum to indicate if the assumptions in @p Set are positive /// @param Sign Enum to indicate if the assumptions in @p Set are positive
/// (needed/assumptions) or negative (invalid/restrictions). /// (needed/assumptions) or negative (invalid/restrictions).
/// @param BB The block in which this assumption was taken. Used to
/// calculate hotness when emitting remark.
void addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, DebugLoc Loc, void addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, DebugLoc Loc,
AssumptionSign Sign); AssumptionSign Sign, BasicBlock *BB);
/// Record an assumption for later addition to the assumed context. /// Record an assumption for later addition to the assumed context.
/// ///
@ -2508,7 +2515,8 @@ public:
/// ///
/// @param Kind The assumption kind describing the underlying cause. /// @param Kind The assumption kind describing the underlying cause.
/// @param Loc The location in the source that triggered . /// @param Loc The location in the source that triggered .
void invalidate(AssumptionKind Kind, DebugLoc Loc); /// @param BB The BasicBlock where it was triggered.
void invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB = nullptr);
/// Get the invalid context for this Scop. /// Get the invalid context for this Scop.
/// ///

View File

@ -427,7 +427,7 @@ bool ScopBuilder::buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt) {
cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue(); cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue();
Sizes.pop_back(); Sizes.pop_back();
if (ElementSize != DelinearizedSize) if (ElementSize != DelinearizedSize)
scop->invalidate(DELINEARIZATION, Inst->getDebugLoc()); scop->invalidate(DELINEARIZATION, Inst->getDebugLoc(), Inst->getParent());
addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType, addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
true, AccItr->second.DelinearizedSubscripts, Sizes, Val); true, AccItr->second.DelinearizedSubscripts, Sizes, Val);
@ -935,7 +935,7 @@ static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) {
} }
void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) {
scop.reset(new Scop(R, SE, LI, *SD.getDetectionContext(&R))); scop.reset(new Scop(R, SE, LI, *SD.getDetectionContext(&R), SD.ORE));
buildStmts(R); buildStmts(R);
buildAccessFunctions(); buildAccessFunctions();
@ -1038,12 +1038,13 @@ ScopBuilder::ScopBuilder(Region *R, AssumptionCache &AC, AliasAnalysis &AA,
ScopDetection &SD, ScalarEvolution &SE) ScopDetection &SD, ScalarEvolution &SE)
: AA(AA), DL(DL), DT(DT), LI(LI), SD(SD), SE(SE) { : AA(AA), DL(DL), DT(DT), LI(LI), SD(SD), SE(SE) {
Function *F = R->getEntry()->getParent();
DebugLoc Beg, End; DebugLoc Beg, End;
getDebugLocations(getBBPairForRegion(R), Beg, End); auto P = getBBPairForRegion(R);
getDebugLocations(P, Beg, End);
std::string Msg = "SCoP begins here."; std::string Msg = "SCoP begins here.";
emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, Beg, Msg); SD.ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEntry", Beg, P.first)
<< Msg);
buildScop(*R, AC); buildScop(*R, AC);
@ -1060,5 +1061,10 @@ ScopBuilder::ScopBuilder(Region *R, AssumptionCache &AC, AliasAnalysis &AA,
++RichScopFound; ++RichScopFound;
} }
emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, End, Msg); if (R->isTopLevelRegion())
SD.ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.first)
<< Msg);
else
SD.ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.second)
<< Msg);
} }

View File

@ -284,8 +284,8 @@ static bool IsFnNameListedInOnlyFunctions(StringRef FnName) {
ScopDetection::ScopDetection(Function &F, const DominatorTree &DT, ScopDetection::ScopDetection(Function &F, const DominatorTree &DT,
ScalarEvolution &SE, LoopInfo &LI, RegionInfo &RI, ScalarEvolution &SE, LoopInfo &LI, RegionInfo &RI,
AliasAnalysis &AA) AliasAnalysis &AA, OptimizationRemarkEmitter &ORE)
: DT(DT), SE(SE), LI(LI), RI(RI), AA(AA) { : DT(DT), SE(SE), LI(LI), RI(RI), AA(AA), ORE(ORE) {
if (!PollyProcessUnprofitable && LI.empty()) if (!PollyProcessUnprofitable && LI.empty())
return; return;
@ -1579,7 +1579,7 @@ void ScopDetection::emitMissedRemarks(const Function &F) {
for (auto &DIt : DetectionContextMap) { for (auto &DIt : DetectionContextMap) {
auto &DC = DIt.getSecond(); auto &DC = DIt.getSecond();
if (DC.Log.hasErrors()) if (DC.Log.hasErrors())
emitRejectionRemarks(DIt.getFirst(), DC.Log); emitRejectionRemarks(DIt.getFirst(), DC.Log, ORE);
} }
} }
@ -1728,7 +1728,8 @@ bool ScopDetectionWrapperPass::runOnFunction(llvm::Function &F) {
auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Result.reset(new ScopDetection(F, DT, SE, LI, RI, AA)); auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
Result.reset(new ScopDetection(F, DT, SE, LI, RI, AA, ORE));
return false; return false;
} }
@ -1736,6 +1737,7 @@ void ScopDetectionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfoWrapperPass>(); AU.addRequired<LoopInfoWrapperPass>();
AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>(); AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
// We also need AA and RegionInfo when we are verifying analysis. // We also need AA and RegionInfo when we are verifying analysis.
AU.addRequiredTransitive<AAResultsWrapperPass>(); AU.addRequiredTransitive<AAResultsWrapperPass>();
AU.addRequiredTransitive<RegionInfoPass>(); AU.addRequiredTransitive<RegionInfoPass>();
@ -1767,7 +1769,8 @@ ScopDetection ScopAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
auto &AA = FAM.getResult<AAManager>(F); auto &AA = FAM.getResult<AAManager>(F);
auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F); auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
return {F, DT, SE, LI, RI, AA}; auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
return {F, DT, SE, LI, RI, AA, ORE};
} }
PreservedAnalyses ScopAnalysisPrinterPass::run(Function &F, PreservedAnalyses ScopAnalysisPrinterPass::run(Function &F,
@ -1792,5 +1795,6 @@ INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass);
INITIALIZE_PASS_END(ScopDetectionWrapperPass, "polly-detect", INITIALIZE_PASS_END(ScopDetectionWrapperPass, "polly-detect",
"Polly - Detect static control parts (SCoPs)", false, false) "Polly - Detect static control parts (SCoPs)", false, false)

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionInfo.h"
#include "llvm/IR/BasicBlock.h" #include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfo.h"
@ -121,28 +122,36 @@ void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) {
} }
} }
void emitRejectionRemarks(const BBPair &P, const RejectLog &Log) { void emitRejectionRemarks(const BBPair &P, const RejectLog &Log,
Function &F = *P.first->getParent(); OptimizationRemarkEmitter &ORE) {
LLVMContext &Ctx = F.getContext();
DebugLoc Begin, End; DebugLoc Begin, End;
getDebugLocations(P, Begin, End); getDebugLocations(P, Begin, End);
emitOptimizationRemarkMissed( ORE.emit(
Ctx, DEBUG_TYPE, F, Begin, OptimizationRemarkMissed(DEBUG_TYPE, "RejectionErrors", Begin, P.first)
"The following errors keep this region from being a Scop."); << "The following errors keep this region from being a Scop.");
for (RejectReasonPtr RR : Log) { for (RejectReasonPtr RR : Log) {
if (const DebugLoc &Loc = RR->getDebugLoc()) if (const DebugLoc &Loc = RR->getDebugLoc())
emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc, ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc,
RR->getEndUserMessage()); RR->getRemarkBB())
<< RR->getEndUserMessage());
else else
emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Begin, ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Begin,
RR->getEndUserMessage()); RR->getRemarkBB())
<< RR->getEndUserMessage());
} }
emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, End, /* Check to see if Region is a top level region, getExit = NULL*/
"Invalid Scop candidate ends here."); if (P.second)
ORE.emit(
OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.second)
<< "Invalid Scop candidate ends here.");
else
ORE.emit(
OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first)
<< "Invalid Scop candidate ends here.");
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -179,6 +188,12 @@ bool ReportCFG::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportInvalidTerminator. // ReportInvalidTerminator.
std::string ReportInvalidTerminator::getRemarkName() const {
return "InvalidTerminator";
}
const Value *ReportInvalidTerminator::getRemarkBB() const { return BB; }
std::string ReportInvalidTerminator::getMessage() const { std::string ReportInvalidTerminator::getMessage() const {
return ("Invalid instruction terminates BB: " + BB->getName()).str(); return ("Invalid instruction terminates BB: " + BB->getName()).str();
} }
@ -194,6 +209,12 @@ bool ReportInvalidTerminator::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// UnreachableInExit. // UnreachableInExit.
std::string ReportUnreachableInExit::getRemarkName() const {
return "UnreachableInExit";
}
const Value *ReportUnreachableInExit::getRemarkBB() const { return BB; }
std::string ReportUnreachableInExit::getMessage() const { std::string ReportUnreachableInExit::getMessage() const {
std::string BBName = BB->getName(); std::string BBName = BB->getName();
return "Unreachable in exit block" + BBName; return "Unreachable in exit block" + BBName;
@ -212,6 +233,14 @@ bool ReportUnreachableInExit::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportIrreducibleRegion. // ReportIrreducibleRegion.
std::string ReportIrreducibleRegion::getRemarkName() const {
return "IrreducibleRegion";
}
const Value *ReportIrreducibleRegion::getRemarkBB() const {
return R->getEntry();
}
std::string ReportIrreducibleRegion::getMessage() const { std::string ReportIrreducibleRegion::getMessage() const {
return "Irreducible region encountered: " + R->getNameStr(); return "Irreducible region encountered: " + R->getNameStr();
} }
@ -240,6 +269,10 @@ bool ReportAffFunc::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportUndefCond. // ReportUndefCond.
std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; }
const Value *ReportUndefCond::getRemarkBB() const { return BB; }
std::string ReportUndefCond::getMessage() const { std::string ReportUndefCond::getMessage() const {
return ("Condition based on 'undef' value in BB: " + BB->getName()).str(); return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
} }
@ -251,6 +284,10 @@ bool ReportUndefCond::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportInvalidCond. // ReportInvalidCond.
std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; }
const Value *ReportInvalidCond::getRemarkBB() const { return BB; }
std::string ReportInvalidCond::getMessage() const { std::string ReportInvalidCond::getMessage() const {
return ("Condition in BB '" + BB->getName()).str() + return ("Condition in BB '" + BB->getName()).str() +
"' neither constant nor an icmp instruction"; "' neither constant nor an icmp instruction";
@ -263,6 +300,10 @@ bool ReportInvalidCond::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportUndefOperand. // ReportUndefOperand.
std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; }
const Value *ReportUndefOperand::getRemarkBB() const { return BB; }
std::string ReportUndefOperand::getMessage() const { std::string ReportUndefOperand::getMessage() const {
return ("undef operand in branch at BB: " + BB->getName()).str(); return ("undef operand in branch at BB: " + BB->getName()).str();
} }
@ -274,6 +315,10 @@ bool ReportUndefOperand::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportNonAffBranch. // ReportNonAffBranch.
std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; }
const Value *ReportNonAffBranch::getRemarkBB() const { return BB; }
std::string ReportNonAffBranch::getMessage() const { std::string ReportNonAffBranch::getMessage() const {
return ("Non affine branch in BB '" + BB->getName()).str() + return ("Non affine branch in BB '" + BB->getName()).str() +
"' with LHS: " + *LHS + " and RHS: " + *RHS; "' with LHS: " + *LHS + " and RHS: " + *RHS;
@ -286,6 +331,10 @@ bool ReportNonAffBranch::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportNoBasePtr. // ReportNoBasePtr.
std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; }
const Value *ReportNoBasePtr::getRemarkBB() const { return Inst->getParent(); }
std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; } std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
bool ReportNoBasePtr::classof(const RejectReason *RR) { bool ReportNoBasePtr::classof(const RejectReason *RR) {
@ -295,6 +344,12 @@ bool ReportNoBasePtr::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportUndefBasePtr. // ReportUndefBasePtr.
std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; }
const Value *ReportUndefBasePtr::getRemarkBB() const {
return Inst->getParent();
}
std::string ReportUndefBasePtr::getMessage() const { std::string ReportUndefBasePtr::getMessage() const {
return "Undefined base pointer"; return "Undefined base pointer";
} }
@ -306,6 +361,14 @@ bool ReportUndefBasePtr::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportVariantBasePtr. // ReportVariantBasePtr.
std::string ReportVariantBasePtr::getRemarkName() const {
return "VariantBasePtr";
}
const Value *ReportVariantBasePtr::getRemarkBB() const {
return Inst->getParent();
}
std::string ReportVariantBasePtr::getMessage() const { std::string ReportVariantBasePtr::getMessage() const {
return "Base address not invariant in current region:" + *BaseValue; return "Base address not invariant in current region:" + *BaseValue;
} }
@ -321,6 +384,14 @@ bool ReportVariantBasePtr::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportDifferentArrayElementSize // ReportDifferentArrayElementSize
std::string ReportDifferentArrayElementSize::getRemarkName() const {
return "DifferentArrayElementSize";
}
const Value *ReportDifferentArrayElementSize::getRemarkBB() const {
return Inst->getParent();
}
std::string ReportDifferentArrayElementSize::getMessage() const { std::string ReportDifferentArrayElementSize::getMessage() const {
return "Access to one array through data types of different size"; return "Access to one array through data types of different size";
} }
@ -340,6 +411,14 @@ std::string ReportDifferentArrayElementSize::getEndUserMessage() const {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportNonAffineAccess. // ReportNonAffineAccess.
std::string ReportNonAffineAccess::getRemarkName() const {
return "NonAffineAccess";
}
const Value *ReportNonAffineAccess::getRemarkBB() const {
return Inst->getParent();
}
std::string ReportNonAffineAccess::getMessage() const { std::string ReportNonAffineAccess::getMessage() const {
return "Non affine access function: " + *AccessFunction; return "Non affine access function: " + *AccessFunction;
} }
@ -361,6 +440,10 @@ ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
: RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount), : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount),
Loc(L->getStartLoc()) {} Loc(L->getStartLoc()) {}
std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; }
const Value *ReportLoopBound::getRemarkBB() const { return L->getHeader(); }
std::string ReportLoopBound::getMessage() const { std::string ReportLoopBound::getMessage() const {
return "Non affine loop bound '" + *LoopCount + return "Non affine loop bound '" + *LoopCount +
"' in loop: " + L->getHeader()->getName(); "' in loop: " + L->getHeader()->getName();
@ -379,6 +462,12 @@ std::string ReportLoopBound::getEndUserMessage() const {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportLoopHasNoExit. // ReportLoopHasNoExit.
std::string ReportLoopHasNoExit::getRemarkName() const {
return "LoopHasNoExit";
}
const Value *ReportLoopHasNoExit::getRemarkBB() const { return L->getHeader(); }
std::string ReportLoopHasNoExit::getMessage() const { std::string ReportLoopHasNoExit::getMessage() const {
return "Loop " + L->getHeader()->getName() + " has no exit."; return "Loop " + L->getHeader()->getName() + " has no exit.";
} }
@ -396,6 +485,14 @@ std::string ReportLoopHasNoExit::getEndUserMessage() const {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportLoopOnlySomeLatches // ReportLoopOnlySomeLatches
std::string ReportLoopOnlySomeLatches::getRemarkName() const {
return "LoopHasNoExit";
}
const Value *ReportLoopOnlySomeLatches::getRemarkBB() const {
return L->getHeader();
}
std::string ReportLoopOnlySomeLatches::getMessage() const { std::string ReportLoopOnlySomeLatches::getMessage() const {
return "Not all latches of loop " + L->getHeader()->getName() + return "Not all latches of loop " + L->getHeader()->getName() +
" part of scop."; " part of scop.";
@ -418,6 +515,10 @@ std::string ReportLoopOnlySomeLatches::getEndUserMessage() const {
ReportFuncCall::ReportFuncCall(Instruction *Inst) ReportFuncCall::ReportFuncCall(Instruction *Inst)
: RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {} : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {}
std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; }
const Value *ReportFuncCall::getRemarkBB() const { return Inst->getParent(); }
std::string ReportFuncCall::getMessage() const { std::string ReportFuncCall::getMessage() const {
return "Call instruction: " + *Inst; return "Call instruction: " + *Inst;
} }
@ -441,6 +542,14 @@ bool ReportFuncCall::classof(const RejectReason *RR) {
ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst) ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst)
: ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {} : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {}
std::string ReportNonSimpleMemoryAccess::getRemarkName() const {
return "NonSimpleMemoryAccess";
}
const Value *ReportNonSimpleMemoryAccess::getRemarkBB() const {
return Inst->getParent();
}
std::string ReportNonSimpleMemoryAccess::getMessage() const { std::string ReportNonSimpleMemoryAccess::getMessage() const {
return "Non-simple memory access: " + *Inst; return "Non-simple memory access: " + *Inst;
} }
@ -499,6 +608,10 @@ std::string ReportAlias::formatInvalidAlias(std::string Prefix,
return OS.str(); return OS.str();
} }
std::string ReportAlias::getRemarkName() const { return "Alias"; }
const Value *ReportAlias::getRemarkBB() const { return Inst->getParent(); }
std::string ReportAlias::getMessage() const { std::string ReportAlias::getMessage() const {
return formatInvalidAlias("Possible aliasing: "); return formatInvalidAlias("Possible aliasing: ");
} }
@ -517,6 +630,8 @@ bool ReportAlias::classof(const RejectReason *RR) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// ReportOther. // ReportOther.
std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; }
std::string ReportOther::getMessage() const { return "Unknown reject reason"; } std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {} ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {}
@ -531,6 +646,12 @@ bool ReportOther::classof(const RejectReason *RR) {
ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue) ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
: ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {} : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {}
std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; }
const Value *ReportIntToPtr::getRemarkBB() const {
return BaseValue->getParent();
}
std::string ReportIntToPtr::getMessage() const { std::string ReportIntToPtr::getMessage() const {
return "Find bad intToptr prt: " + *BaseValue; return "Find bad intToptr prt: " + *BaseValue;
} }
@ -549,6 +670,10 @@ bool ReportIntToPtr::classof(const RejectReason *RR) {
ReportAlloca::ReportAlloca(Instruction *Inst) ReportAlloca::ReportAlloca(Instruction *Inst)
: ReportOther(RejectReasonKind::Alloca), Inst(Inst) {} : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {}
std::string ReportAlloca::getRemarkName() const { return "Alloca"; }
const Value *ReportAlloca::getRemarkBB() const { return Inst->getParent(); }
std::string ReportAlloca::getMessage() const { std::string ReportAlloca::getMessage() const {
return "Alloca instruction: " + *Inst; return "Alloca instruction: " + *Inst;
} }
@ -567,6 +692,12 @@ bool ReportAlloca::classof(const RejectReason *RR) {
ReportUnknownInst::ReportUnknownInst(Instruction *Inst) ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
: ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {} : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {}
std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; }
const Value *ReportUnknownInst::getRemarkBB() const {
return Inst->getParent();
}
std::string ReportUnknownInst::getMessage() const { std::string ReportUnknownInst::getMessage() const {
return "Unknown instruction: " + *Inst; return "Unknown instruction: " + *Inst;
} }
@ -584,6 +715,10 @@ bool ReportUnknownInst::classof(const RejectReason *RR) {
ReportEntry::ReportEntry(BasicBlock *BB) ReportEntry::ReportEntry(BasicBlock *BB)
: ReportOther(RejectReasonKind::Entry), BB(BB) {} : ReportOther(RejectReasonKind::Entry), BB(BB) {}
std::string ReportEntry::getRemarkName() const { return "Entry"; }
const Value *ReportEntry::getRemarkBB() const { return BB; }
std::string ReportEntry::getMessage() const { std::string ReportEntry::getMessage() const {
return "Region containing entry block of function is invalid!"; return "Region containing entry block of function is invalid!";
} }
@ -605,6 +740,10 @@ bool ReportEntry::classof(const RejectReason *RR) {
ReportUnprofitable::ReportUnprofitable(Region *R) ReportUnprofitable::ReportUnprofitable(Region *R)
: ReportOther(RejectReasonKind::Unprofitable), R(R) {} : ReportOther(RejectReasonKind::Unprofitable), R(R) {}
std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; }
const Value *ReportUnprofitable::getRemarkBB() const { return R->getEntry(); }
std::string ReportUnprofitable::getMessage() const { std::string ReportUnprofitable::getMessage() const {
return "Region can not profitably be optimized!"; return "Region can not profitably be optimized!";
} }

View File

@ -1617,7 +1617,8 @@ buildConditionSets(Scop &S, BasicBlock *BB, Value *Condition,
} }
if (TooComplex) { if (TooComplex) {
S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc()); S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc(),
TI ? TI->getParent() : nullptr /* BasicBlock */);
isl_set_free(AlternativeCondSet); isl_set_free(AlternativeCondSet);
isl_set_free(ConsequenceCondSet); isl_set_free(ConsequenceCondSet);
return false; return false;
@ -2163,7 +2164,6 @@ bool Scop::isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const {
void Scop::addUserAssumptions( void Scop::addUserAssumptions(
AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI,
DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) { DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
auto &F = getFunction();
for (auto &Assumption : AC.assumptions()) { for (auto &Assumption : AC.assumptions()) {
auto *CI = dyn_cast_or_null<CallInst>(Assumption); auto *CI = dyn_cast_or_null<CallInst>(Assumption);
if (!CI || CI->getNumArgOperands() != 1) if (!CI || CI->getNumArgOperands() != 1)
@ -2177,9 +2177,9 @@ void Scop::addUserAssumptions(
auto *Val = CI->getArgOperand(0); auto *Val = CI->getArgOperand(0);
ParameterSetTy DetectedParams; ParameterSetTy DetectedParams;
if (!isAffineConstraint(Val, &R, L, *SE, DetectedParams)) { if (!isAffineConstraint(Val, &R, L, *SE, DetectedParams)) {
emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, ORE.emit(
CI->getDebugLoc(), OptimizationRemarkAnalysis(DEBUG_TYPE, "IgnoreUserAssumption", CI)
"Non-affine user assumption ignored."); << "Non-affine user assumption ignored.");
continue; continue;
} }
@ -2227,10 +2227,8 @@ void Scop::addUserAssumptions(
isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1); isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1);
} }
} }
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "UserAssumption", CI)
emitOptimizationRemarkAnalysis( << "Use user assumption: " << stringFromIslObj(AssumptionCtx));
F.getContext(), DEBUG_TYPE, F, CI->getDebugLoc(),
"Use user assumption: " + stringFromIslObj(AssumptionCtx));
Context = isl_set_intersect(Context, AssumptionCtx); Context = isl_set_intersect(Context, AssumptionCtx);
} }
} }
@ -2827,7 +2825,7 @@ bool Scop::propagateInvalidStmtDomains(
continue; continue;
InvalidDomainMap.erase(BB); InvalidDomainMap.erase(BB);
invalidate(COMPLEXITY, TI->getDebugLoc()); invalidate(COMPLEXITY, TI->getDebugLoc(), TI->getParent());
return false; return false;
} }
@ -3383,17 +3381,13 @@ bool Scop::buildAliasGroup(Scop::AliasGroupTy &AliasGroup,
SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays; SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays;
SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays; SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays;
auto &F = getFunction();
if (AliasGroup.size() < 2) if (AliasGroup.size() < 2)
return true; return true;
for (MemoryAccess *Access : AliasGroup) { for (MemoryAccess *Access : AliasGroup) {
emitOptimizationRemarkAnalysis( ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "PossibleAlias",
F.getContext(), DEBUG_TYPE, F, Access->getAccessInstruction())
Access->getAccessInstruction()->getDebugLoc(), << "Possibly aliasing pointer, use restrict keyword.");
"Possibly aliasing pointer, use restrict keyword.");
const ScopArrayInfo *Array = Access->getScopArrayInfo(); const ScopArrayInfo *Array = Access->getScopArrayInfo();
if (HasWriteAccess.count(Array)) { if (HasWriteAccess.count(Array)) {
ReadWriteArrays.insert(Array); ReadWriteArrays.insert(Array);
@ -3417,7 +3411,8 @@ bool Scop::buildAliasGroup(Scop::AliasGroupTy &AliasGroup,
// compute a sufficiently tight lower and upper bound: bail out. // compute a sufficiently tight lower and upper bound: bail out.
for (MemoryAccess *MA : AliasGroup) { for (MemoryAccess *MA : AliasGroup) {
if (!MA->isAffine()) { if (!MA->isAffine()) {
invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc()); invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc(),
MA->getAccessInstruction()->getParent());
return false; return false;
} }
} }
@ -3492,10 +3487,10 @@ int Scop::getNextID(std::string ParentFunc) {
} }
Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI, Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI,
ScopDetection::DetectionContext &DC) ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE)
: SE(&ScalarEvolution), R(R), name(R.getNameStr()), IsOptimized(false), : SE(&ScalarEvolution), R(R), name(R.getNameStr()), IsOptimized(false),
HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false), HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false),
MaxLoopDepth(0), CopyStmtsNum(0), SkipScop(false), DC(DC), MaxLoopDepth(0), CopyStmtsNum(0), SkipScop(false), DC(DC), ORE(ORE),
IslCtx(isl_ctx_alloc(), isl_ctx_free), Context(nullptr), IslCtx(isl_ctx_alloc(), isl_ctx_free), Context(nullptr),
Affinator(this, LI), AssumedContext(nullptr), InvalidContext(nullptr), Affinator(this, LI), AssumedContext(nullptr), InvalidContext(nullptr),
Schedule(nullptr), Schedule(nullptr),
@ -3850,7 +3845,7 @@ void Scop::addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs) {
if (isl_set_n_basic_set(DomainCtx) >= MaxDisjunctsInDomain) { if (isl_set_n_basic_set(DomainCtx) >= MaxDisjunctsInDomain) {
auto *AccInst = InvMAs.front().MA->getAccessInstruction(); auto *AccInst = InvMAs.front().MA->getAccessInstruction();
invalidate(COMPLEXITY, AccInst->getDebugLoc()); invalidate(COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent());
isl_set_free(DomainCtx); isl_set_free(DomainCtx);
for (auto &InvMA : InvMAs) for (auto &InvMA : InvMAs)
isl_set_free(InvMA.NonHoistableCtx); isl_set_free(InvMA.NonHoistableCtx);
@ -4024,7 +4019,7 @@ isl::set Scop::getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes) {
return nullptr; return nullptr;
addAssumption(INVARIANTLOAD, WrittenCtx.copy(), LI->getDebugLoc(), addAssumption(INVARIANTLOAD, WrittenCtx.copy(), LI->getDebugLoc(),
AS_RESTRICTION); AS_RESTRICTION, LI->getParent());
return WrittenCtx; return WrittenCtx;
} }
@ -4034,7 +4029,7 @@ void Scop::verifyInvariantLoads() {
assert(LI && contains(LI)); assert(LI && contains(LI));
ScopStmt *Stmt = getStmtFor(LI); ScopStmt *Stmt = getStmtFor(LI);
if (Stmt && Stmt->getArrayAccessOrNULLFor(LI)) { if (Stmt && Stmt->getArrayAccessOrNULLFor(LI)) {
invalidate(INVARIANTLOAD, LI->getDebugLoc()); invalidate(INVARIANTLOAD, LI->getDebugLoc(), LI->getParent());
return; return;
} }
} }
@ -4319,7 +4314,7 @@ bool Scop::isEffectiveAssumption(__isl_keep isl_set *Set, AssumptionSign Sign) {
} }
bool Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, bool Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set,
DebugLoc Loc, AssumptionSign Sign) { DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB) {
if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign)) if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign))
return false; return false;
@ -4370,19 +4365,24 @@ bool Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set,
break; break;
} }
auto &F = getFunction();
auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t"; auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t";
std::string Msg = toString(Kind) + Suffix + stringFromIslObj(Set); std::string Msg = toString(Kind) + Suffix + stringFromIslObj(Set);
emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, Loc, Msg); if (BB)
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, BB)
<< Msg);
else
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc,
R.getEntry())
<< Msg);
return true; return true;
} }
void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set,
DebugLoc Loc, AssumptionSign Sign) { DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB) {
// Simplify the assumptions/restrictions first. // Simplify the assumptions/restrictions first.
Set = isl_set_gist_params(Set, getContext()); Set = isl_set_gist_params(Set, getContext());
if (!trackAssumption(Kind, Set, Loc, Sign)) { if (!trackAssumption(Kind, Set, Loc, Sign, BB)) {
isl_set_free(Set); isl_set_free(Set);
return; return;
} }
@ -4408,7 +4408,7 @@ void Scop::addRecordedAssumptions() {
const Assumption &AS = RecordedAssumptions.pop_back_val(); const Assumption &AS = RecordedAssumptions.pop_back_val();
if (!AS.BB) { if (!AS.BB) {
addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign); addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign, nullptr /* BasicBlock */);
continue; continue;
} }
@ -4434,12 +4434,12 @@ void Scop::addRecordedAssumptions() {
else /* (AS.Sign == AS_ASSUMPTION) */ else /* (AS.Sign == AS_ASSUMPTION) */
S = isl_set_params(isl_set_subtract(Dom, S)); S = isl_set_params(isl_set_subtract(Dom, S));
addAssumption(AS.Kind, S, AS.Loc, AS_RESTRICTION); addAssumption(AS.Kind, S, AS.Loc, AS_RESTRICTION, AS.BB);
} }
} }
void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc) { void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) {
addAssumption(Kind, isl_set_empty(getParamSpace()), Loc, AS_ASSUMPTION); addAssumption(Kind, isl_set_empty(getParamSpace()), Loc, AS_ASSUMPTION, BB);
} }
__isl_give isl_set *Scop::getInvalidContext() const { __isl_give isl_set *Scop::getInvalidContext() const {
@ -4571,7 +4571,7 @@ __isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB,
} }
auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc(); auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
invalidate(COMPLEXITY, DL); invalidate(COMPLEXITY, DL, BB);
return Affinator.getPwAff(SE->getZero(E->getType()), BB); return Affinator.getPwAff(SE->getZero(E->getType()), BB);
} }

View File

@ -1,13 +1,18 @@
; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \
; RUN: -polly-detect-track-failures -polly-detect -analyze \ ; RUN: -polly-detect-track-failures -polly-detect -analyze \
; RUN: -polly-process-unprofitable=false < %s 2>&1| FileCheck %s ; RUN: -polly-process-unprofitable=false < %s 2>&1| FileCheck %s
; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \
; RUN: -polly-detect-track-failures -polly-detect -analyze \
; RUN: -polly-process-unprofitable=false < %s 2>&1 -pass-remarks-output=%t.yaml
; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; void onlyWrite(float *A) { ; void onlyWrite(float *A) {
; for (long i = 0; i < 100; i++) ; for (long i = 0; i < 100; i++)
; A[i] = 0; ; A[i] = 0;
; } ; }
; ;
; void onlyRead(float *A) { ; void onlyRead(float *A) {
; for (long i = 0; i < 100; i++) ; for (long i = 0; i < 100; i++)
; A[i]; ; A[i];
@ -21,6 +26,54 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; CHECK: remark: /tmp/test.c:7:3: No profitable polyhedral optimization found ; CHECK: remark: /tmp/test.c:7:3: No profitable polyhedral optimization found
; CHECK: remark: /tmp/test.c:8:10: Invalid Scop candidate ends here. ; CHECK: remark: /tmp/test.c:8:10: Invalid Scop candidate ends here.
; YAML: --- !Missed
; YAML: Pass: polly-detect
; YAML: Name: RejectionErrors
; YAML: DebugLoc: { File: /tmp/test.c, Line: 2, Column: 3 }
; YAML: Function: onlyWrite
; YAML: Args:
; YAML: - String: The following errors keep this region from being a Scop.
; YAML: ...
; YAML: --- !Missed
; YAML: Pass: polly-detect
; YAML: Name: Unprofitable
; YAML: DebugLoc: { File: /tmp/test.c, Line: 2, Column: 3 }
; YAML: Function: onlyWrite
; YAML: Args:
; YAML: - String: No profitable polyhedral optimization found
; YAML: ...
; YAML: --- !Missed
; YAML: Pass: polly-detect
; YAML: Name: InvalidScopEnd
; YAML: DebugLoc: { File: /tmp/test.c, Line: 3, Column: 10 }
; YAML: Function: onlyWrite
; YAML: Args:
; YAML: - String: Invalid Scop candidate ends here.
; YAML: ...
; YAML: --- !Missed
; YAML: Pass: polly-detect
; YAML: Name: RejectionErrors
; YAML: DebugLoc: { File: /tmp/test.c, Line: 7, Column: 3 }
; YAML: Function: onlyRead
; YAML: Args:
; YAML: - String: The following errors keep this region from being a Scop.
; YAML: ...
; YAML: --- !Missed
; YAML: Pass: polly-detect
; YAML: Name: Unprofitable
; YAML: DebugLoc: { File: /tmp/test.c, Line: 7, Column: 3 }
; YAML: Function: onlyRead
; YAML: Args:
; YAML: - String: No profitable polyhedral optimization found
; YAML: ...
; YAML: --- !Missed
; YAML: Pass: polly-detect
; YAML: Name: InvalidScopEnd
; YAML: DebugLoc: { File: /tmp/test.c, Line: 8, Column: 10 }
; YAML: Function: onlyRead
; YAML: Args:
; YAML: - String: Invalid Scop candidate ends here.
; Function Attrs: nounwind uwtable ; Function Attrs: nounwind uwtable
define void @onlyWrite(float* %A) #0 !dbg !4 { define void @onlyWrite(float* %A) #0 !dbg !4 {

View File

@ -16,6 +16,41 @@
; } ; }
; } ; }
; ;
; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \
; RUN: -polly-precise-inbounds -disable-output < %s 2>&1 -pass-remarks-output=%t.yaml
; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
; YAML: --- !Analysis
; YAML: Pass: polly-scops
; YAML: Name: ScopEntry
; YAML: Function: f
; YAML: Args:
; YAML: - String: SCoP begins here.
; YAML: ...
; YAML: --- !Analysis
; YAML: Pass: polly-scops
; YAML: Name: UserAssumption
; YAML: Function: f
; YAML: Args:
; YAML: - String: 'Use user assumption: '
; YAML: - String: '[i, N, M] -> { : N <= i or (N > i and N >= 0) }'
; YAML: ...
; YAML: --- !Analysis
; YAML: Pass: polly-scops
; YAML: Name: AssumpRestrict
; YAML: Function: f
; YAML: Args:
; YAML: - String: 'Inbounds assumption: [i, N, M] -> { : N <= i or (N > i and M <= 100) }'
; YAML: ...
; YAML: --- !Analysis
; YAML: Pass: polly-scops
; YAML: Name: ScopEnd
; YAML: Function: f
; YAML: Args:
; YAML: - String: SCoP ends here.
; YAML: ...
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @f(i32* noalias %A, i32* noalias %B, i32 %i, i32 %N, i32 %M, [100 x i32]* %C) { define void @f(i32* noalias %A, i32* noalias %B, i32 %i, i32 %N, i32 %M, [100 x i32]* %C) {