mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-15 07:39:31 +00:00
[OptDiag,LV] Add hotness attribute to analysis remarks
The earlier change added hotness attribute to missed-optimization remarks. This follows up with the analysis remarks (the ones explaining the reason for the missed optimization). llvm-svn: 276192
This commit is contained in:
parent
c8216345a3
commit
46bb1fa09e
@ -34,6 +34,7 @@ class Loop;
|
||||
class SCEV;
|
||||
class SCEVUnionPredicate;
|
||||
class LoopAccessInfo;
|
||||
class OptimizationRemarkEmitter;
|
||||
|
||||
/// Optimization analysis message produced during vectorization. Messages inform
|
||||
/// the user why vectorization did not occur.
|
||||
@ -63,10 +64,9 @@ public:
|
||||
/// \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
|
||||
/// \p TheLoop.
|
||||
static void emitAnalysis(const LoopAccessReport &Message,
|
||||
const Function *TheFunction,
|
||||
const Loop *TheLoop,
|
||||
const char *PassName);
|
||||
static void emitAnalysis(const LoopAccessReport &Message, const Loop *TheLoop,
|
||||
const char *PassName,
|
||||
OptimizationRemarkEmitter &ORE);
|
||||
};
|
||||
|
||||
/// \brief Collection of parameters shared beetween the Loop Vectorizer and the
|
||||
|
@ -58,6 +58,22 @@ public:
|
||||
void emitOptimizationRemarkMissed(const char *PassName, Loop *L,
|
||||
const Twine &Msg);
|
||||
|
||||
/// Emit an optimization analysis remark message.
|
||||
///
|
||||
/// \p PassName is the name of the pass emitting the message. If
|
||||
/// -Rpass-analysis= is given and \p PassName matches the regular expression
|
||||
/// in -Rpass, then the remark will be emitted. \p DLoc is the debug location
|
||||
/// where the diagnostic is generated. \p V is the IR Value that identifies
|
||||
/// the code region. \p Msg is the message string to use.
|
||||
void emitOptimizationRemarkAnalysis(const char *PassName,
|
||||
const DebugLoc &DLoc, const Value *V,
|
||||
const Twine &Msg);
|
||||
|
||||
/// \brief Same as above but derives the IR Value for the code region and the
|
||||
/// debug location from the Loop parameter \p L.
|
||||
void emitOptimizationRemarkAnalysis(const char *PassName, Loop *L,
|
||||
const Twine &Msg);
|
||||
|
||||
private:
|
||||
Function *F;
|
||||
|
||||
|
@ -487,9 +487,10 @@ public:
|
||||
DiagnosticInfoOptimizationRemarkAnalysis(const char *PassName,
|
||||
const Function &Fn,
|
||||
const DebugLoc &DLoc,
|
||||
const Twine &Msg)
|
||||
const Twine &Msg,
|
||||
Optional<uint64_t> Hotness = None)
|
||||
: DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark,
|
||||
PassName, Fn, DLoc, Msg) {}
|
||||
PassName, Fn, DLoc, Msg, Hotness) {}
|
||||
|
||||
static bool classof(const DiagnosticInfo *DI) {
|
||||
return DI->getKind() == DK_OptimizationRemarkAnalysis;
|
||||
|
@ -15,11 +15,11 @@
|
||||
#include "llvm/Analysis/LoopAccessAnalysis.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPassManager.h"
|
||||
#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpander.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Analysis/VectorUtils.h"
|
||||
#include "llvm/IR/DiagnosticInfo.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
@ -94,14 +94,15 @@ bool VectorizerParams::isInterleaveForced() {
|
||||
}
|
||||
|
||||
void LoopAccessReport::emitAnalysis(const LoopAccessReport &Message,
|
||||
const Function *TheFunction,
|
||||
const Loop *TheLoop,
|
||||
const char *PassName) {
|
||||
const Loop *TheLoop, const char *PassName,
|
||||
OptimizationRemarkEmitter &ORE) {
|
||||
DebugLoc DL = TheLoop->getStartLoc();
|
||||
if (const Instruction *I = Message.getInstr())
|
||||
const Value *V = TheLoop->getHeader();
|
||||
if (const Instruction *I = Message.getInstr()) {
|
||||
DL = I->getDebugLoc();
|
||||
emitOptimizationRemarkAnalysis(TheFunction->getContext(), PassName,
|
||||
*TheFunction, DL, Message.str());
|
||||
V = I->getParent();
|
||||
}
|
||||
ORE.emitOptimizationRemarkAnalysis(PassName, DL, V, Message.str());
|
||||
}
|
||||
|
||||
Value *llvm::stripIntegerCast(Value *V) {
|
||||
|
@ -40,6 +40,20 @@ void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
|
||||
emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg);
|
||||
}
|
||||
|
||||
void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
|
||||
const char *PassName, const DebugLoc &DLoc, const Value *V,
|
||||
const Twine &Msg) {
|
||||
LLVMContext &Ctx = F->getContext();
|
||||
Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysis(PassName, *F, DLoc, Msg,
|
||||
computeHotness(V)));
|
||||
}
|
||||
|
||||
void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
|
||||
const char *PassName, Loop *L, const Twine &Msg) {
|
||||
emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
|
||||
Msg);
|
||||
}
|
||||
|
||||
OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
|
||||
: FunctionPass(ID) {
|
||||
initializeOptimizationRemarkEmitterWrapperPassPass(
|
||||
|
@ -290,9 +290,10 @@ public:
|
||||
LoopInfo *LI, DominatorTree *DT,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const TargetTransformInfo *TTI, AssumptionCache *AC,
|
||||
unsigned VecWidth, unsigned UnrollFactor)
|
||||
OptimizationRemarkEmitter *ORE, unsigned VecWidth,
|
||||
unsigned UnrollFactor)
|
||||
: OrigLoop(OrigLoop), PSE(PSE), LI(LI), DT(DT), TLI(TLI), TTI(TTI),
|
||||
AC(AC), VF(VecWidth), UF(UnrollFactor),
|
||||
AC(AC), ORE(ORE), VF(VecWidth), UF(UnrollFactor),
|
||||
Builder(PSE.getSE()->getContext()), Induction(nullptr),
|
||||
OldInduction(nullptr), WidenMap(UnrollFactor), TripCount(nullptr),
|
||||
VectorTripCount(nullptr), Legal(nullptr), AddedSafetyChecks(false) {}
|
||||
@ -529,6 +530,8 @@ protected:
|
||||
const TargetTransformInfo *TTI;
|
||||
/// Assumption Cache.
|
||||
AssumptionCache *AC;
|
||||
/// Interface to emit optimization remarks.
|
||||
OptimizationRemarkEmitter *ORE;
|
||||
|
||||
/// \brief LoopVersioning. It's only set up (non-null) if memchecks were
|
||||
/// used.
|
||||
@ -613,8 +616,8 @@ public:
|
||||
LoopInfo *LI, DominatorTree *DT,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const TargetTransformInfo *TTI, AssumptionCache *AC,
|
||||
unsigned UnrollFactor)
|
||||
: InnerLoopVectorizer(OrigLoop, PSE, LI, DT, TLI, TTI, AC, 1,
|
||||
OptimizationRemarkEmitter *ORE, unsigned UnrollFactor)
|
||||
: InnerLoopVectorizer(OrigLoop, PSE, LI, DT, TLI, TTI, AC, ORE, 1,
|
||||
UnrollFactor) {}
|
||||
|
||||
private:
|
||||
@ -1073,12 +1076,13 @@ public:
|
||||
FK_Enabled = 1, ///< Forcing enabled.
|
||||
};
|
||||
|
||||
LoopVectorizeHints(const Loop *L, bool DisableInterleaving)
|
||||
LoopVectorizeHints(const Loop *L, bool DisableInterleaving,
|
||||
OptimizationRemarkEmitter &ORE)
|
||||
: Width("vectorize.width", VectorizerParams::VectorizationFactor,
|
||||
HK_WIDTH),
|
||||
Interleave("interleave.count", DisableInterleaving, HK_UNROLL),
|
||||
Force("vectorize.enable", FK_Undefined, HK_FORCE),
|
||||
PotentiallyUnsafe(false), TheLoop(L) {
|
||||
PotentiallyUnsafe(false), TheLoop(L), ORE(ORE) {
|
||||
// Populate values with existing loop metadata.
|
||||
getHintsFromMetadata();
|
||||
|
||||
@ -1100,17 +1104,15 @@ public:
|
||||
bool allowVectorization(Function *F, Loop *L, bool AlwaysVectorize) const {
|
||||
if (getForce() == LoopVectorizeHints::FK_Disabled) {
|
||||
DEBUG(dbgs() << "LV: Not vectorizing: #pragma vectorize disable.\n");
|
||||
emitOptimizationRemarkAnalysis(F->getContext(),
|
||||
vectorizeAnalysisPassName(), *F,
|
||||
L->getStartLoc(), emitRemark());
|
||||
ORE.emitOptimizationRemarkAnalysis(vectorizeAnalysisPassName(), L,
|
||||
emitRemark());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AlwaysVectorize && getForce() != LoopVectorizeHints::FK_Enabled) {
|
||||
DEBUG(dbgs() << "LV: Not vectorizing: No #pragma vectorize enable.\n");
|
||||
emitOptimizationRemarkAnalysis(F->getContext(),
|
||||
vectorizeAnalysisPassName(), *F,
|
||||
L->getStartLoc(), emitRemark());
|
||||
ORE.emitOptimizationRemarkAnalysis(vectorizeAnalysisPassName(), L,
|
||||
emitRemark());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1121,8 +1123,8 @@ public:
|
||||
// FIXME: Add interleave.disable metadata. This will allow
|
||||
// vectorize.disable to be used without disabling the pass and errors
|
||||
// to differentiate between disabled vectorization and a width of 1.
|
||||
emitOptimizationRemarkAnalysis(
|
||||
F->getContext(), vectorizeAnalysisPassName(), *F, L->getStartLoc(),
|
||||
ORE.emitOptimizationRemarkAnalysis(
|
||||
vectorizeAnalysisPassName(), L,
|
||||
"loop not vectorized: vectorization and interleaving are explicitly "
|
||||
"disabled, or vectorize width and interleave count are both set to "
|
||||
"1");
|
||||
@ -1303,13 +1305,17 @@ private:
|
||||
|
||||
/// The loop these hints belong to.
|
||||
const Loop *TheLoop;
|
||||
|
||||
/// Interface to emit optimization remarks.
|
||||
OptimizationRemarkEmitter &ORE;
|
||||
};
|
||||
|
||||
static void emitAnalysisDiag(const Function *TheFunction, const Loop *TheLoop,
|
||||
static void emitAnalysisDiag(const Loop *TheLoop,
|
||||
const LoopVectorizeHints &Hints,
|
||||
OptimizationRemarkEmitter &ORE,
|
||||
const LoopAccessReport &Message) {
|
||||
const char *Name = Hints.vectorizeAnalysisPassName();
|
||||
LoopAccessReport::emitAnalysis(Message, TheFunction, TheLoop, Name);
|
||||
LoopAccessReport::emitAnalysis(Message, TheLoop, Name, ORE);
|
||||
}
|
||||
|
||||
static void emitMissedWarning(Function *F, Loop *L,
|
||||
@ -1349,12 +1355,12 @@ public:
|
||||
TargetLibraryInfo *TLI, AliasAnalysis *AA, Function *F,
|
||||
const TargetTransformInfo *TTI,
|
||||
std::function<const LoopAccessInfo &(Loop &)> *GetLAA, LoopInfo *LI,
|
||||
LoopVectorizationRequirements *R, LoopVectorizeHints *H)
|
||||
: NumPredStores(0), TheLoop(L), PSE(PSE), TLI(TLI), TheFunction(F),
|
||||
TTI(TTI), DT(DT), GetLAA(GetLAA), LAI(nullptr),
|
||||
InterleaveInfo(PSE, L, DT, LI), Induction(nullptr),
|
||||
WidestIndTy(nullptr), HasFunNoNaNAttr(false), Requirements(R),
|
||||
Hints(H) {}
|
||||
OptimizationRemarkEmitter *ORE, LoopVectorizationRequirements *R,
|
||||
LoopVectorizeHints *H)
|
||||
: NumPredStores(0), TheLoop(L), PSE(PSE), TLI(TLI), TTI(TTI), DT(DT),
|
||||
GetLAA(GetLAA), LAI(nullptr), ORE(ORE), InterleaveInfo(PSE, L, DT, LI),
|
||||
Induction(nullptr), WidestIndTy(nullptr), HasFunNoNaNAttr(false),
|
||||
Requirements(R), Hints(H) {}
|
||||
|
||||
/// ReductionList contains the reduction descriptors for all
|
||||
/// of the reductions that were found in the loop.
|
||||
@ -1512,7 +1518,7 @@ private:
|
||||
/// VectorizationReport because the << operator of VectorizationReport returns
|
||||
/// LoopAccessReport.
|
||||
void emitAnalysis(const LoopAccessReport &Message) const {
|
||||
emitAnalysisDiag(TheFunction, TheLoop, *Hints, Message);
|
||||
emitAnalysisDiag(TheLoop, *Hints, *ORE, Message);
|
||||
}
|
||||
|
||||
/// \brief If an access has a symbolic strides, this maps the pointer value to
|
||||
@ -1537,8 +1543,6 @@ private:
|
||||
PredicatedScalarEvolution &PSE;
|
||||
/// Target Library Info.
|
||||
TargetLibraryInfo *TLI;
|
||||
/// Parent function
|
||||
Function *TheFunction;
|
||||
/// Target Transform Info
|
||||
const TargetTransformInfo *TTI;
|
||||
/// Dominator Tree.
|
||||
@ -1548,6 +1552,8 @@ private:
|
||||
// And the loop-accesses info corresponding to this loop. This pointer is
|
||||
// null until canVectorizeMemory sets it up.
|
||||
const LoopAccessInfo *LAI;
|
||||
/// Interface to emit optimization remarks.
|
||||
OptimizationRemarkEmitter *ORE;
|
||||
|
||||
/// The interleave access information contains groups of interleaved accesses
|
||||
/// with the same stride and close to each other.
|
||||
@ -1603,10 +1609,11 @@ public:
|
||||
LoopInfo *LI, LoopVectorizationLegality *Legal,
|
||||
const TargetTransformInfo &TTI,
|
||||
const TargetLibraryInfo *TLI, DemandedBits *DB,
|
||||
AssumptionCache *AC, const Function *F,
|
||||
AssumptionCache *AC,
|
||||
OptimizationRemarkEmitter *ORE, const Function *F,
|
||||
const LoopVectorizeHints *Hints)
|
||||
: TheLoop(L), PSE(PSE), LI(LI), Legal(Legal), TTI(TTI), TLI(TLI), DB(DB),
|
||||
AC(AC), TheFunction(F), Hints(Hints) {}
|
||||
AC(AC), ORE(ORE), TheFunction(F), Hints(Hints) {}
|
||||
|
||||
/// Information about vectorization costs
|
||||
struct VectorizationFactor {
|
||||
@ -1689,7 +1696,7 @@ private:
|
||||
/// VectorizationReport because the << operator of VectorizationReport returns
|
||||
/// LoopAccessReport.
|
||||
void emitAnalysis(const LoopAccessReport &Message) const {
|
||||
emitAnalysisDiag(TheFunction, TheLoop, *Hints, Message);
|
||||
emitAnalysisDiag(TheLoop, *Hints, *ORE, Message);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1714,6 +1721,9 @@ public:
|
||||
DemandedBits *DB;
|
||||
/// Assumption cache.
|
||||
AssumptionCache *AC;
|
||||
/// Interface to emit optimization remarks.
|
||||
OptimizationRemarkEmitter *ORE;
|
||||
|
||||
const Function *TheFunction;
|
||||
/// Loop Vectorize Hint.
|
||||
const LoopVectorizeHints *Hints;
|
||||
@ -3125,7 +3135,7 @@ void InnerLoopVectorizer::createEmptyLoop() {
|
||||
if (MDNode *LID = OrigLoop->getLoopID())
|
||||
Lp->setLoopID(LID);
|
||||
|
||||
LoopVectorizeHints Hints(Lp, true);
|
||||
LoopVectorizeHints Hints(Lp, true, *ORE);
|
||||
Hints.setAlreadyVectorized();
|
||||
}
|
||||
|
||||
@ -6378,7 +6388,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
<< L->getHeader()->getParent()->getName() << "\" from "
|
||||
<< DebugLocStr << "\n");
|
||||
|
||||
LoopVectorizeHints Hints(L, DisableUnrolling);
|
||||
LoopVectorizeHints Hints(L, DisableUnrolling, *ORE);
|
||||
|
||||
DEBUG(dbgs() << "LV: Loop hints:"
|
||||
<< " force="
|
||||
@ -6416,9 +6426,9 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
DEBUG(dbgs() << " But vectorizing was explicitly forced.\n");
|
||||
else {
|
||||
DEBUG(dbgs() << "\n");
|
||||
emitAnalysisDiag(F, L, Hints, VectorizationReport()
|
||||
<< "vectorization is not beneficial "
|
||||
"and is not explicitly forced");
|
||||
emitAnalysisDiag(L, Hints, *ORE, VectorizationReport()
|
||||
<< "vectorization is not beneficial "
|
||||
"and is not explicitly forced");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -6427,7 +6437,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
|
||||
// Check if it is legal to vectorize the loop.
|
||||
LoopVectorizationRequirements Requirements;
|
||||
LoopVectorizationLegality LVL(L, PSE, DT, TLI, AA, F, TTI, GetLAA, LI,
|
||||
LoopVectorizationLegality LVL(L, PSE, DT, TLI, AA, F, TTI, GetLAA, LI, ORE,
|
||||
&Requirements, &Hints);
|
||||
if (!LVL.canVectorize()) {
|
||||
DEBUG(dbgs() << "LV: Not vectorizing: Cannot prove legality.\n");
|
||||
@ -6436,7 +6446,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
}
|
||||
|
||||
// Use the cost model.
|
||||
LoopVectorizationCostModel CM(L, PSE, LI, &LVL, *TTI, TLI, DB, AC, F,
|
||||
LoopVectorizationCostModel CM(L, PSE, LI, &LVL, *TTI, TLI, DB, AC, ORE, F,
|
||||
&Hints);
|
||||
CM.collectValuesToIgnore();
|
||||
|
||||
@ -6465,7 +6475,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
DEBUG(dbgs() << "LV: Can't vectorize when the NoImplicitFloat"
|
||||
"attribute is used.\n");
|
||||
emitAnalysisDiag(
|
||||
F, L, Hints,
|
||||
L, Hints, *ORE,
|
||||
VectorizationReport()
|
||||
<< "loop not vectorized due to NoImplicitFloat attribute");
|
||||
emitMissedWarning(F, L, Hints, ORE);
|
||||
@ -6479,7 +6489,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
if (Hints.isPotentiallyUnsafe() &&
|
||||
TTI->isFPVectorizationPotentiallyUnsafe()) {
|
||||
DEBUG(dbgs() << "LV: Potentially unsafe FP op prevents vectorization.\n");
|
||||
emitAnalysisDiag(F, L, Hints,
|
||||
emitAnalysisDiag(L, Hints, *ORE,
|
||||
VectorizationReport()
|
||||
<< "loop not vectorized due to unsafe FP support.");
|
||||
emitMissedWarning(F, L, Hints, ORE);
|
||||
@ -6538,20 +6548,16 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
const char *VAPassName = Hints.vectorizeAnalysisPassName();
|
||||
if (!VectorizeLoop && !InterleaveLoop) {
|
||||
// Do not vectorize or interleaving the loop.
|
||||
emitOptimizationRemarkAnalysis(F->getContext(), VAPassName, *F,
|
||||
L->getStartLoc(), VecDiagMsg);
|
||||
emitOptimizationRemarkAnalysis(F->getContext(), LV_NAME, *F,
|
||||
L->getStartLoc(), IntDiagMsg);
|
||||
ORE->emitOptimizationRemarkAnalysis(VAPassName, L, VecDiagMsg);
|
||||
ORE->emitOptimizationRemarkAnalysis(LV_NAME, L, IntDiagMsg);
|
||||
return false;
|
||||
} else if (!VectorizeLoop && InterleaveLoop) {
|
||||
DEBUG(dbgs() << "LV: Interleave Count is " << IC << '\n');
|
||||
emitOptimizationRemarkAnalysis(F->getContext(), VAPassName, *F,
|
||||
L->getStartLoc(), VecDiagMsg);
|
||||
ORE->emitOptimizationRemarkAnalysis(VAPassName, L, VecDiagMsg);
|
||||
} else if (VectorizeLoop && !InterleaveLoop) {
|
||||
DEBUG(dbgs() << "LV: Found a vectorizable loop (" << VF.Width << ") in "
|
||||
<< DebugLocStr << '\n');
|
||||
emitOptimizationRemarkAnalysis(F->getContext(), LV_NAME, *F,
|
||||
L->getStartLoc(), IntDiagMsg);
|
||||
ORE->emitOptimizationRemarkAnalysis(LV_NAME, L, IntDiagMsg);
|
||||
} else if (VectorizeLoop && InterleaveLoop) {
|
||||
DEBUG(dbgs() << "LV: Found a vectorizable loop (" << VF.Width << ") in "
|
||||
<< DebugLocStr << '\n');
|
||||
@ -6562,7 +6568,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
assert(IC > 1 && "interleave count should not be 1 or 0");
|
||||
// If we decided that it is not legal to vectorize the loop, then
|
||||
// interleave it.
|
||||
InnerLoopUnroller Unroller(L, PSE, LI, DT, TLI, TTI, AC, IC);
|
||||
InnerLoopUnroller Unroller(L, PSE, LI, DT, TLI, TTI, AC, ORE, IC);
|
||||
Unroller.vectorize(&LVL, CM.MinBWs, CM.VecValuesToIgnore);
|
||||
|
||||
emitOptimizationRemark(F->getContext(), LV_NAME, *F, L->getStartLoc(),
|
||||
@ -6570,7 +6576,7 @@ bool LoopVectorizePass::processLoop(Loop *L) {
|
||||
Twine(IC) + ")");
|
||||
} else {
|
||||
// If we decided that it is *legal* to vectorize the loop, then do it.
|
||||
InnerLoopVectorizer LB(L, PSE, LI, DT, TLI, TTI, AC, VF.Width, IC);
|
||||
InnerLoopVectorizer LB(L, PSE, LI, DT, TLI, TTI, AC, ORE, VF.Width, IC);
|
||||
LB.vectorize(&LVL, CM.MinBWs, CM.VecValuesToIgnore);
|
||||
++LoopsVectorized;
|
||||
|
||||
|
201
test/Transforms/LoopVectorize/diag-with-hotness-info-2.ll
Normal file
201
test/Transforms/LoopVectorize/diag-with-hotness-info-2.ll
Normal file
@ -0,0 +1,201 @@
|
||||
; RUN: opt -S -loop-vectorize -pass-remarks-analysis=loop-vectorize -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -S -passes=loop-vectorize -pass-remarks-analysis=loop-vectorize -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s
|
||||
|
||||
; 1 void cold(char *A, char *B, char *C, char *D, char *E, int N) {
|
||||
; 2 for(int i = 0; i < N; i++) {
|
||||
; 3 A[i + 1] = A[i] + B[i];
|
||||
; 4 C[i] = D[i] * E[i];
|
||||
; 5 }
|
||||
; 6 }
|
||||
; 7
|
||||
; 8 void hot(char *A, char *B, char *C, char *D, char *E, int N) {
|
||||
; 9 for(int i = 0; i < N; i++) {
|
||||
; 10 A[i + 1] = A[i] + B[i];
|
||||
; 11 C[i] = D[i] * E[i];
|
||||
; 12 }
|
||||
; 13 }
|
||||
; 14
|
||||
; 15 void unknown(char *A, char *B, char *C, char *D, char *E, int N) {
|
||||
; 16 for(int i = 0; i < N; i++) {
|
||||
; 17 A[i + 1] = A[i] + B[i];
|
||||
; 18 C[i] = D[i] * E[i];
|
||||
; 19 }
|
||||
; 20 }
|
||||
|
||||
; CHECK: remark: /tmp/s.c:2:3: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop (hotness: 300)
|
||||
; CHECK: remark: /tmp/s.c:9:3: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop (hotness: 5000)
|
||||
; CHECK: remark: /tmp/s.c:16:3: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop{{$}}
|
||||
|
||||
; ModuleID = '/tmp/s.c'
|
||||
source_filename = "/tmp/s.c"
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-macosx10.11.0"
|
||||
|
||||
; Function Attrs: norecurse nounwind ssp uwtable
|
||||
define void @cold(i8* nocapture %A, i8* nocapture readonly %B, i8* nocapture %C, i8* nocapture readonly %D, i8* nocapture readonly %E, i32 %N) local_unnamed_addr #0 !dbg !7 !prof !56 {
|
||||
entry:
|
||||
%cmp28 = icmp sgt i32 %N, 0, !dbg !9
|
||||
br i1 %cmp28, label %ph, label %for.cond.cleanup, !dbg !10, !prof !58
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !12
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !12, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !16
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !16, !tbaa !13
|
||||
%add = add i8 %1, %0, !dbg !17
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10
|
||||
%arrayidx7 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv.next, !dbg !18
|
||||
store i8 %add, i8* %arrayidx7, align 1, !dbg !19, !tbaa !13
|
||||
%arrayidx9 = getelementptr inbounds i8, i8* %D, i64 %indvars.iv, !dbg !20
|
||||
%2 = load i8, i8* %arrayidx9, align 1, !dbg !20, !tbaa !13
|
||||
%arrayidx12 = getelementptr inbounds i8, i8* %E, i64 %indvars.iv, !dbg !21
|
||||
%3 = load i8, i8* %arrayidx12, align 1, !dbg !21, !tbaa !13
|
||||
%mul = mul i8 %3, %2, !dbg !22
|
||||
%arrayidx16 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !23
|
||||
store i8 %mul, i8* %arrayidx16, align 1, !dbg !24, !tbaa !13
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !10
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !10, !llvm.loop !25, !prof !59
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !11
|
||||
}
|
||||
|
||||
; Function Attrs: norecurse nounwind ssp uwtable
|
||||
define void @hot(i8* nocapture %A, i8* nocapture readonly %B, i8* nocapture %C, i8* nocapture readonly %D, i8* nocapture readonly %E, i32 %N) local_unnamed_addr #0 !dbg !26 !prof !57 {
|
||||
entry:
|
||||
%cmp28 = icmp sgt i32 %N, 0, !dbg !27
|
||||
br i1 %cmp28, label %ph, label %for.cond.cleanup, !dbg !28, !prof !58
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !30
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !30, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !31
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !31, !tbaa !13
|
||||
%add = add i8 %1, %0, !dbg !32
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !28
|
||||
%arrayidx7 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv.next, !dbg !33
|
||||
store i8 %add, i8* %arrayidx7, align 1, !dbg !34, !tbaa !13
|
||||
%arrayidx9 = getelementptr inbounds i8, i8* %D, i64 %indvars.iv, !dbg !35
|
||||
%2 = load i8, i8* %arrayidx9, align 1, !dbg !35, !tbaa !13
|
||||
%arrayidx12 = getelementptr inbounds i8, i8* %E, i64 %indvars.iv, !dbg !36
|
||||
%3 = load i8, i8* %arrayidx12, align 1, !dbg !36, !tbaa !13
|
||||
%mul = mul i8 %3, %2, !dbg !37
|
||||
%arrayidx16 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !38
|
||||
store i8 %mul, i8* %arrayidx16, align 1, !dbg !39, !tbaa !13
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !28
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !28
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !28, !llvm.loop !40, !prof !59
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !29
|
||||
}
|
||||
|
||||
; Function Attrs: norecurse nounwind ssp uwtable
|
||||
define void @unknown(i8* nocapture %A, i8* nocapture readonly %B, i8* nocapture %C, i8* nocapture readonly %D, i8* nocapture readonly %E, i32 %N) local_unnamed_addr #0 !dbg !41 {
|
||||
entry:
|
||||
%cmp28 = icmp sgt i32 %N, 0, !dbg !42
|
||||
br i1 %cmp28, label %ph, label %for.cond.cleanup, !dbg !43
|
||||
|
||||
ph:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %ph ]
|
||||
%arrayidx = getelementptr inbounds i8, i8* %A, i64 %indvars.iv, !dbg !45
|
||||
%0 = load i8, i8* %arrayidx, align 1, !dbg !45, !tbaa !13
|
||||
%arrayidx2 = getelementptr inbounds i8, i8* %B, i64 %indvars.iv, !dbg !46
|
||||
%1 = load i8, i8* %arrayidx2, align 1, !dbg !46, !tbaa !13
|
||||
%add = add i8 %1, %0, !dbg !47
|
||||
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !43
|
||||
%arrayidx7 = getelementptr inbounds i8, i8* %A, i64 %indvars.iv.next, !dbg !48
|
||||
store i8 %add, i8* %arrayidx7, align 1, !dbg !49, !tbaa !13
|
||||
%arrayidx9 = getelementptr inbounds i8, i8* %D, i64 %indvars.iv, !dbg !50
|
||||
%2 = load i8, i8* %arrayidx9, align 1, !dbg !50, !tbaa !13
|
||||
%arrayidx12 = getelementptr inbounds i8, i8* %E, i64 %indvars.iv, !dbg !51
|
||||
%3 = load i8, i8* %arrayidx12, align 1, !dbg !51, !tbaa !13
|
||||
%mul = mul i8 %3, %2, !dbg !52
|
||||
%arrayidx16 = getelementptr inbounds i8, i8* %C, i64 %indvars.iv, !dbg !53
|
||||
store i8 %mul, i8* %arrayidx16, align 1, !dbg !54, !tbaa !13
|
||||
%lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !43
|
||||
%exitcond = icmp eq i32 %lftr.wideiv, %N, !dbg !43
|
||||
br i1 %exitcond, label %for.cond.cleanup, label %for.body, !dbg !43, !llvm.loop !55
|
||||
|
||||
for.cond.cleanup:
|
||||
ret void, !dbg !44
|
||||
}
|
||||
|
||||
attributes #0 = { norecurse nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 273572) (llvm/trunk 273585)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
|
||||
!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 2}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"PIC Level", i32 2}
|
||||
!6 = !{!"clang version 3.9.0 (trunk 273572) (llvm/trunk 273585)"}
|
||||
!7 = distinct !DISubprogram(name: "cold", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!8 = !DISubroutineType(types: !2)
|
||||
!9 = !DILocation(line: 2, column: 20, scope: !7)
|
||||
!10 = !DILocation(line: 2, column: 3, scope: !7)
|
||||
!11 = !DILocation(line: 6, column: 1, scope: !7)
|
||||
!12 = !DILocation(line: 3, column: 16, scope: !7)
|
||||
!13 = !{!14, !14, i64 0}
|
||||
!14 = !{!"omnipotent char", !15, i64 0}
|
||||
!15 = !{!"Simple C/C++ TBAA"}
|
||||
!16 = !DILocation(line: 3, column: 23, scope: !7)
|
||||
!17 = !DILocation(line: 3, column: 21, scope: !7)
|
||||
!18 = !DILocation(line: 3, column: 5, scope: !7)
|
||||
!19 = !DILocation(line: 3, column: 14, scope: !7)
|
||||
!20 = !DILocation(line: 4, column: 12, scope: !7)
|
||||
!21 = !DILocation(line: 4, column: 19, scope: !7)
|
||||
!22 = !DILocation(line: 4, column: 17, scope: !7)
|
||||
!23 = !DILocation(line: 4, column: 5, scope: !7)
|
||||
!24 = !DILocation(line: 4, column: 10, scope: !7)
|
||||
!25 = distinct !{!25, !10}
|
||||
!26 = distinct !DISubprogram(name: "hot", scope: !1, file: !1, line: 8, type: !8, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!27 = !DILocation(line: 9, column: 20, scope: !26)
|
||||
!28 = !DILocation(line: 9, column: 3, scope: !26)
|
||||
!29 = !DILocation(line: 13, column: 1, scope: !26)
|
||||
!30 = !DILocation(line: 10, column: 16, scope: !26)
|
||||
!31 = !DILocation(line: 10, column: 23, scope: !26)
|
||||
!32 = !DILocation(line: 10, column: 21, scope: !26)
|
||||
!33 = !DILocation(line: 10, column: 5, scope: !26)
|
||||
!34 = !DILocation(line: 10, column: 14, scope: !26)
|
||||
!35 = !DILocation(line: 11, column: 12, scope: !26)
|
||||
!36 = !DILocation(line: 11, column: 19, scope: !26)
|
||||
!37 = !DILocation(line: 11, column: 17, scope: !26)
|
||||
!38 = !DILocation(line: 11, column: 5, scope: !26)
|
||||
!39 = !DILocation(line: 11, column: 10, scope: !26)
|
||||
!40 = distinct !{!40, !28}
|
||||
!41 = distinct !DISubprogram(name: "unknown", scope: !1, file: !1, line: 15, type: !8, isLocal: false, isDefinition: true, scopeLine: 15, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !2)
|
||||
!42 = !DILocation(line: 16, column: 20, scope: !41)
|
||||
!43 = !DILocation(line: 16, column: 3, scope: !41)
|
||||
!44 = !DILocation(line: 20, column: 1, scope: !41)
|
||||
!45 = !DILocation(line: 17, column: 16, scope: !41)
|
||||
!46 = !DILocation(line: 17, column: 23, scope: !41)
|
||||
!47 = !DILocation(line: 17, column: 21, scope: !41)
|
||||
!48 = !DILocation(line: 17, column: 5, scope: !41)
|
||||
!49 = !DILocation(line: 17, column: 14, scope: !41)
|
||||
!50 = !DILocation(line: 18, column: 12, scope: !41)
|
||||
!51 = !DILocation(line: 18, column: 19, scope: !41)
|
||||
!52 = !DILocation(line: 18, column: 17, scope: !41)
|
||||
!53 = !DILocation(line: 18, column: 5, scope: !41)
|
||||
!54 = !DILocation(line: 18, column: 10, scope: !41)
|
||||
!55 = distinct !{!55, !43}
|
||||
!56 = !{!"function_entry_count", i64 3}
|
||||
!57 = !{!"function_entry_count", i64 50}
|
||||
!58 = !{!"branch_weights", i32 99, i32 1}
|
||||
!59 = !{!"branch_weights", i32 1, i32 99}
|
Loading…
Reference in New Issue
Block a user