1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02: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:
Adam Nemet 2016-07-20 21:44:26 +00:00
parent c8216345a3
commit 46bb1fa09e
7 changed files with 299 additions and 60 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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(

View File

@ -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;

View 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}