View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -53,6 +53,7 @@ add_clang_library(clangCodeGen
CodeGenModule.cpp
CodeGenTBAA.cpp
CodeGenTypes.cpp
CodeGenPGO.cpp
ItaniumCXXABI.cpp
MicrosoftCXXABI.cpp
ModuleBuilder.cpp
View
@@ -16,6 +16,7 @@
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CodeGenModule.h"
#include "CodeGenPGO.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -44,7 +45,8 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
NextCleanupDestIndex(1), FirstBlockInfo(0), EHResumeBlock(0),
ExceptionSlot(0), EHSelectorSlot(0), DebugInfo(CGM.getModuleDebugInfo()),
DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(0),
SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), NumReturnExprs(0),
PGO(cgm), SwitchInsn(0), SwitchWeights(0),
CaseRangeBlock(0), UnreachableBlock(0), NumReturnExprs(0),
NumSimpleReturnExprs(0), CXXABIThisDecl(0), CXXABIThisValue(0),
CXXThisValue(0), CXXDefaultInitExprThis(0),
CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
@@ -571,6 +573,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (CGM.getCodeGenOpts().InstrumentForProfiling)
EmitMCountInstrumentation();
PGO.assignRegionCounters(GD);
if (RetTy->isVoidType()) {
// Void type; nothing to return.
ReturnValue = 0;
@@ -643,6 +647,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args,
const Stmt *Body) {
RegionCounter Cnt = getPGORegionCounter(Body);
Cnt.beginRegion(Builder);
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
@@ -772,6 +778,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// a quick pass now to see if we can.
if (!CurFn->doesNotThrow())
TryMarkNoThrow(CurFn);
PGO.emitWriteoutFunction(CurGD);
PGO.destroyRegionCounters();
}
/// ContainsLabel - Return true if the statement contains a label in it. If
@@ -870,10 +879,13 @@ ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APSInt &ResultInt) {
///
void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
llvm::BasicBlock *TrueBlock,
llvm::BasicBlock *FalseBlock) {
llvm::BasicBlock *FalseBlock,
uint64_t TrueCount) {
Cond = Cond->IgnoreParens();
if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
RegionCounter Cnt = getPGORegionCounter(CondBOp);
// Handle X && Y in a condition.
if (CondBOp->getOpcode() == BO_LAnd) {
// If we have "1 && X", simplify the code. "0 && X" would have constant
@@ -882,29 +894,38 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) &&
ConstantBool) {
// br(1 && X) -> br(X).
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
Cnt.beginRegion(Builder);
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
TrueCount);
}
// If we have "X && 1", simplify the code to use an uncond branch.
// "X && 0" would have been constant folded to 0.
if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
ConstantBool) {
// br(X && 1) -> br(X).
return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock);
return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
TrueCount);
}
// Emit the LHS as a conditional. If the LHS conditional is false, we
// want to jump to the FalseBlock.
llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true");
// The counter tells us how often we evaluate RHS, and all of TrueCount
// can be propagated to that branch.
uint64_t RHSCount = Cnt.getCount();
ConditionalEvaluation eval(*this);
EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock);
EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount);
EmitBlock(LHSTrue);
// Any temporaries created here are conditional.
Cnt.beginRegion(Builder);
eval.begin(*this);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount);
eval.end(*this);
Cnt.adjustFallThroughCount();
Cnt.applyAdjustmentsToRegion();
return;
}
@@ -916,56 +937,89 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (ConstantFoldsToSimpleInteger(CondBOp->getLHS(), ConstantBool) &&
!ConstantBool) {
// br(0 || X) -> br(X).
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
Cnt.beginRegion(Builder);
return EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock,
TrueCount);
}
// If we have "X || 0", simplify the code to use an uncond branch.
// "X || 1" would have been constant folded to 1.
if (ConstantFoldsToSimpleInteger(CondBOp->getRHS(), ConstantBool) &&
!ConstantBool) {
// br(X || 0) -> br(X).
return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock);
return EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, FalseBlock,
TrueCount);
}
// Emit the LHS as a conditional. If the LHS conditional is true, we
// want to jump to the TrueBlock.
llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false");
// We have the count for entry to the RHS and for the whole expression
// being true, so we can divy up True count between the short circuit and
// the RHS.
uint64_t LHSCount = TrueCount - Cnt.getCount();
uint64_t RHSCount = TrueCount - LHSCount;
ConditionalEvaluation eval(*this);
EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse);
EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount);
EmitBlock(LHSFalse);
// Any temporaries created here are conditional.
Cnt.beginRegion(Builder);
eval.begin(*this);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock);
EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount);
eval.end(*this);
Cnt.adjustFallThroughCount();
Cnt.applyAdjustmentsToRegion();
return;
}
}
if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) {
// br(!x, t, f) -> br(x, f, t)
if (CondUOp->getOpcode() == UO_LNot)
return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock);
if (CondUOp->getOpcode() == UO_LNot) {
// Negate the count.
uint64_t FalseCount = PGO.getCurrentRegionCount() - TrueCount;
// Negate the condition and swap the destination blocks.
return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock,
FalseCount);
}
}
if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(Cond)) {
// br(c ? x : y, t, f) -> br(c, br(x, t, f), br(y, t, f))
llvm::BasicBlock *LHSBlock = createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = createBasicBlock("cond.false");
RegionCounter Cnt = getPGORegionCounter(CondOp);
ConditionalEvaluation cond(*this);
EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock);
EmitBranchOnBoolExpr(CondOp->getCond(), LHSBlock, RHSBlock, Cnt.getCount());
// When computing PGO branch weights, we only know the overall count for
// the true block. This code is essentially doing tail duplication of the
// naive code-gen, introducing new edges for which counts are not
// available. Divide the counts proportionally between the LHS and RHS of
// the conditional operator.
uint64_t LHSScaledTrueCount = 0;
if (TrueCount) {
double LHSRatio = Cnt.getCount() / (double) PGO.getCurrentRegionCount();
LHSScaledTrueCount = TrueCount * LHSRatio;
}
cond.begin(*this);
EmitBlock(LHSBlock);
EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock);
Cnt.beginRegion(Builder);
EmitBranchOnBoolExpr(CondOp->getLHS(), TrueBlock, FalseBlock,
LHSScaledTrueCount);
cond.end(*this);
cond.begin(*this);
EmitBlock(RHSBlock);
EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock);
Cnt.beginElseRegion();
EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock,
TrueCount - LHSScaledTrueCount);
cond.end(*this);
return;
@@ -981,9 +1035,15 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
return;
}
// Create branch weights based on the number of times we get here and the
// number of times the condition should be true.
uint64_t CurrentCount = PGO.getCurrentRegionCountWithMin(TrueCount);
llvm::MDNode *Weights = PGO.createBranchWeights(TrueCount,
CurrentCount - TrueCount);
// Emit the code with the fully general case.
llvm::Value *CondV = EvaluateExprAsBool(Cond);
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock);
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights);
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
View
@@ -19,6 +19,7 @@
#include "CGValue.h"
#include "EHScopeStack.h"
#include "CodeGenModule.h"
#include "CodeGenPGO.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -817,19 +818,36 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
// BreakContinueStack - This keeps track of where break and continue
// statements should jump to.
// statements should jump to and the associated base counter for
// instrumentation.
struct BreakContinue {
BreakContinue(JumpDest Break, JumpDest Continue)
: BreakBlock(Break), ContinueBlock(Continue) {}
BreakContinue(JumpDest Break, JumpDest Continue, RegionCounter *LoopCnt,
bool CountBreak = true)
: BreakBlock(Break), ContinueBlock(Continue), LoopCnt(LoopCnt),
CountBreak(CountBreak) {}
JumpDest BreakBlock;
JumpDest ContinueBlock;
RegionCounter *LoopCnt;
bool CountBreak;
};
SmallVector<BreakContinue, 8> BreakContinueStack;
CodeGenPGO PGO;
public:
/// Get a counter for instrumentation of the region associated with the given
/// statement.
RegionCounter getPGORegionCounter(const Stmt *S) {
return RegionCounter(PGO, S);
}
private:
/// SwitchInsn - This is nearest current switch instruction. It is null if
/// current context is not in a switch.
llvm::SwitchInst *SwitchInsn;
/// The branch weights of SwitchInsn when doing instrumentation based PGO.
SmallVector<uint64_t, 16> *SwitchWeights;
/// CaseRangeBlock - This block holds if condition check for last case
/// statement range in current switch instruction.
@@ -2413,8 +2431,10 @@ class CodeGenFunction : public CodeGenTypeCache {
/// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an
/// if statement) to the specified blocks. Based on the condition, this might
/// try to simplify the codegen of the conditional based on the branch.
/// TrueCount should be the number of times we expect the condition to
/// evaluate to true based on PGO data.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock,
llvm::BasicBlock *FalseBlock);
llvm::BasicBlock *FalseBlock, uint64_t TrueCount);
/// \brief Emit a description of a type in a format suitable for passing to
/// a runtime sanitizer handler.
View
@@ -20,6 +20,7 @@
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenTBAA.h"
#include "CodeGenPGO.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
@@ -77,7 +78,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(0),
TheTargetCodeGenInfo(0), Types(*this), VTables(*this), ObjCRuntime(0),
OpenCLRuntime(0), CUDARuntime(0), DebugInfo(0), ARCData(0),
NoObjCARCExceptionsMetadata(0), RRData(0), CFConstantStringClassRef(0),
NoObjCARCExceptionsMetadata(0), RRData(0), PGOData(0),
CFConstantStringClassRef(0),
ConstantStringClassRef(0), NSConstantStringType(0),
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0),
BlockObjectDispose(0), BlockDescriptorType(0), GenericBlockLiteralType(0),
@@ -131,6 +133,9 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
if (C.getLangOpts().ObjCAutoRefCount)
ARCData = new ARCEntrypoints();
RRData = new RREntrypoints();
if (!CodeGenOpts.InstrProfileInput.empty())
PGOData = new PGOProfileData(*this, CodeGenOpts.InstrProfileInput);
}
CodeGenModule::~CodeGenModule() {
@@ -2181,6 +2186,10 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
AddGlobalDtor(Fn, DA->getPriority());
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, Fn);
llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this);
if (PGOInit)
AddGlobalCtor(PGOInit, 0);
}
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
View
@@ -85,7 +85,8 @@ namespace CodeGen {
class CGCUDARuntime;
class BlockFieldFlags;
class FunctionArgList;
class PGOProfileData;
struct OrderGlobalInits {
unsigned int priority;
unsigned int lex_order;
@@ -258,6 +259,7 @@ class CodeGenModule : public CodeGenTypeCache {
ARCEntrypoints *ARCData;
llvm::MDNode *NoObjCARCExceptionsMetadata;
RREntrypoints *RRData;
PGOProfileData *PGOData;
// WeakRefReferences - A set of references that have only been seen via
// a weakref so far. This is used to remove the weak of the reference if we
@@ -479,6 +481,10 @@ class CodeGenModule : public CodeGenTypeCache {
return *RRData;
}
PGOProfileData *getPGOData() const {
return PGOData;
}
llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
return StaticLocalDeclMap[D];
}
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,216 @@
//===--- CodeGenPGO.h - PGO Instrumentation for LLVM CodeGen ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Instrumentation-based profile-guided optimization
//
//===----------------------------------------------------------------------===//
#ifndef CLANG_CODEGEN_CODEGENPGO_H
#define CLANG_CODEGEN_CODEGENPGO_H
#include "CGBuilder.h"
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/MemoryBuffer.h"
namespace clang {
namespace CodeGen {
class RegionCounter;
/// The raw counter data from an instrumented PGO binary
class PGOProfileData {
private:
/// The PGO data
llvm::OwningPtr<llvm::MemoryBuffer> DataBuffer;
/// Offsets into DataBuffer for each function's counters
llvm::StringMap<unsigned> DataOffsets;
CodeGenModule &CGM;
public:
PGOProfileData(CodeGenModule &CGM, std::string Path);
/// Fill Counts with the profile data for the given function name. Returns
/// false on success.
bool getFunctionCounts(StringRef MangledName, std::vector<uint64_t> &Counts);
};
/// Per-function PGO state. This class should generally not be used directly,
/// but instead through the CodeGenFunction and RegionCounter types.
class CodeGenPGO {
private:
CodeGenModule &CGM;
unsigned NumRegionCounters;
llvm::GlobalVariable *RegionCounters;
llvm::DenseMap<const Stmt*, unsigned> *RegionCounterMap;
std::vector<uint64_t> *RegionCounts;
uint64_t CurrentRegionCount;
public:
CodeGenPGO(CodeGenModule &CGM)
: CGM(CGM), NumRegionCounters(0), RegionCounters(0), RegionCounterMap(0),
RegionCounts(0), CurrentRegionCount(0) {}
~CodeGenPGO() {}
/// Whether or not we have PGO region data for the current function. This is
/// false both when we have no data at all and when our data has been
/// discarded.
bool haveRegionCounts() const { return RegionCounts != 0; }
/// Return the counter value of the current region.
uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }
/// Return the counter value of the current region, or \p Min if it is larger.
uint64_t getCurrentRegionCountWithMin(uint64_t Min) {
return std::max(Min, CurrentRegionCount);
}
/// Set the counter value for the current region. This is used to keep track
/// of changes to the most recent counter from control flow and non-local
/// exits.
void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }
/// Calculate branch weights appropriate for PGO data
llvm::MDNode *createBranchWeights(uint64_t TrueCount, uint64_t FalseCount);
llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights);
/// Assign counters to regions and configure them for PGO of a given
/// function. Does nothing if instrumentation is not enabled and either
/// generates global variables or associates PGO data with each of the
/// counters depending on whether we are generating or using instrumentation.
void assignRegionCounters(GlobalDecl &GD);
/// Emit code to write counts for a given function to disk, if necessary.
void emitWriteoutFunction(GlobalDecl &GD);
/// Clean up region counter state. Must be called if assignRegionCounters is
/// used.
void destroyRegionCounters();
/// Emit the logic to register region counter write out functions. Returns a
/// function that implements this logic.
static llvm::Function *emitInitialization(CodeGenModule &CGM);
private:
void mapRegionCounters(const Decl *D);
void loadRegionCounts(GlobalDecl &GD, PGOProfileData *PGOData);
void emitCounterVariables();
/// Emit code to increment the counter at the given index
void emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter);
/// Return the region counter for the given statement. This should only be
/// called on statements that have a dedicated counter.
unsigned getRegionCounter(const Stmt *S) {
if (RegionCounterMap == 0)
return 0;
return (*RegionCounterMap)[S];
}
/// Return the region count for the counter at the given index.
uint64_t getRegionCount(unsigned Counter) {
if (!haveRegionCounts())
return 0;
return (*RegionCounts)[Counter];
}
friend class RegionCounter;
};
/// A counter for a particular region. This is the primary interface through
/// which clients manage PGO counters and their values.
class RegionCounter {
CodeGenPGO *PGO;
unsigned Counter;
uint64_t Count;
uint64_t ParentCount;
uint64_t RegionCount;
int64_t Adjust;
RegionCounter(CodeGenPGO &PGO, unsigned CounterIndex)
: PGO(&PGO), Counter(CounterIndex), Count(PGO.getRegionCount(Counter)),
ParentCount(PGO.getCurrentRegionCount()), Adjust(0) {}
public:
RegionCounter(CodeGenPGO &PGO, const Stmt *S)
: PGO(&PGO), Counter(PGO.getRegionCounter(S)),
Count(PGO.getRegionCount(Counter)),
ParentCount(PGO.getCurrentRegionCount()), Adjust(0) {}
/// Get the value of the counter. In most cases this is the number of times
/// the region of the counter was entered, but for switch labels it's the
/// number of direct jumps to that label.
uint64_t getCount() const { return Count; }
/// Get the value of the counter with adjustments applied. Adjustments occur
/// when control enters or leaves the region abnormally, ie, if there is a
/// jump to a label within the region, or if the function can return from
/// within the region. The adjusted count, then, is the value of the counter
/// at the end of the region.
uint64_t getAdjustedCount() const {
assert(Adjust > 0 || (uint64_t)(-Adjust) <= Count && "Negative count");
return Count + Adjust;
}
/// Get the value of the counter in this region's parent, ie, the region that
/// was active when this region began. This is useful for deriving counts in
/// implicitly counted regions, like the false case of a condition or the
/// normal exits of a loop.
uint64_t getParentCount() const { return ParentCount; }
/// Get the number of times the condition of a loop will evaluate false. This
/// is the number of times we enter the loop, adjusted by the difference
/// between entering and exiting the loop body normally, excepting that
/// 'continue' statements also bring us back here.
///
/// Undefined if this counter is not counting a loop.
uint64_t getLoopExitCount() const {
return getParentCount() + getContinueCounter().getCount() +
getAdjustedCount() - getCount();
}
/// Get the associated break counter. Undefined if this counter is not
/// counting a loop.
RegionCounter getBreakCounter() const {
return RegionCounter(*PGO, Counter + 1);
}
/// Get the associated continue counter. Undefined if this counter is not
/// counting a loop.
RegionCounter getContinueCounter() const {
return RegionCounter(*PGO, Counter + 2);
}
/// Activate the counter by emitting an increment and starting to track
/// adjustments. If AddIncomingFallThrough is true, the current region count
/// will be added to the counter for the purposes of tracking the region.
void beginRegion(CGBuilderTy &Builder, bool AddIncomingFallThrough=false) {
RegionCount = Count;
if (AddIncomingFallThrough)
RegionCount += PGO->getCurrentRegionCount();
PGO->setCurrentRegionCount(RegionCount);
PGO->emitCounterIncrement(Builder, Counter);
}
/// For counters on boolean branches, begins tracking adjustments for the
/// uncounted path.
void beginElseRegion() {
RegionCount = ParentCount - Count;
PGO->setCurrentRegionCount(RegionCount);
}
/// Control may either enter or leave the region, so the count at the end may
/// be different from the start. Call this to track that adjustment without
/// modifying the current count. Must not be called before one of beginRegion
/// or beginElseRegion.
void adjustFallThroughCount() {
Adjust += PGO->getCurrentRegionCount() - RegionCount;
}
/// Commit all adjustments to the current region. This should be called after
/// all blocks that adjust the fallthrough count have been emitted.
void applyAdjustmentsToRegion() {
PGO->setCurrentRegionCount(ParentCount + Adjust);
}
};
} // end namespace CodeGen
} // end namespace clang
#endif
View
@@ -0,0 +1,127 @@
simple_loops 10
1
100
0
0
100
0
0
76
0
0
conditionals 13
1
100
0
0
50
50
33
33
16
99
100
99
100
early_exits 13
1
0
51
1
25
1
25
1
26
0
0
1
0
jumps 30
1
1
0
0
0
1
0
0
0
0
1
0
1
2
3
2
0
0
0
3
0
1
1
1
10
0
0
0
10
9
switches 21
1
1
1
15
0
7
7
1
0
3
2
3
3
4
4
0
4
4
5
1
0
big_switch 19
1
32
0
0
32
1
0
2
1
11
11
1
1
15
15
1
1
2
2
no_usable_data 5
1
1
1
1
1
main 1
1
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,16 @@
_Z6throwsv 11
1
100
0
0
100
66
33
17
50
33
100
main 1
1
View
@@ -0,0 +1,73 @@
// Test that instrumentation based profiling feeds branch prediction
// correctly. This tests both generation of profile data and use of the same,
// and the input file for the -fprofile-instr-use case is expected to be result
// of running the program generated by the -fprofile-instr-generate case. As
// such, main() should call every function in this test.
// RUN: %clangxx %s -o - -emit-llvm -S -fprofile-instr-generate | FileCheck -check-prefix=PGOGEN %s
// RUN: %clangxx %s -o - -emit-llvm -S -fprofile-instr-generate | FileCheck -check-prefix=PGOGEN-EXC %s
// RUN: %clang %s -o - -emit-llvm -S -fprofile-instr-use=%S/Inputs/instr-profile.pgodata | FileCheck -check-prefix=PGOUSE %s
// RUN: %clang %s -o - -emit-llvm -S -fprofile-instr-use=%S/Inputs/instr-profile.pgodata | FileCheck -check-prefix=PGOUSE-EXC %s
// PGOGEN: @[[THC:__llvm_pgo_ctr[0-9]*]] = private global [11 x i64] zeroinitializer
// PGOGEN-EXC: @[[THC:__llvm_pgo_ctr[0-9]*]] = private global [11 x i64] zeroinitializer
// PGOGEN-LABEL: @_Z6throwsv()
// PGOUSE-LABEL: @_Z6throwsv()
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 0
void throws() {
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 1
// PGOUSE: br {{.*}} !prof ![[TH1:[0-9]+]]
for (int i = 0; i < 100; ++i) {
try {
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 5
// PGOUSE: br {{.*}} !prof ![[TH2:[0-9]+]]
if (i % 3) {
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 6
// PGOUSE: br {{.*}} !prof ![[TH3:[0-9]+]]
if (i < 50)
throw 1;
} else {
// The catch block may be emitted after the throw above, we can skip it
// by looking for an else block, but this will break if anyone puts an
// else in the catch
// PGOUSE: if.else{{.*}}:
// PGOGEN: if.else{{.*}}:
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 7
// PGOUSE: br {{.*}} !prof ![[TH4:[0-9]+]]
if (i >= 50)
throw 0;
}
} catch (int e) {
// PGOUSE-EXC: catch{{.*}}:
// PGOGEN-EXC: catch{{.*}}:
// PGOGEN-EXC: store {{.*}} @[[THC]], i64 0, i64 8
// PGOGEN-EXC: store {{.*}} @[[THC]], i64 0, i64 9
// PGOUSE-EXC: br {{.*}} !prof ![[TH5:[0-9]+]]
if (e) {}
}
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 4
// PGOGEN: store {{.*}} @[[THC]], i64 0, i64 10
// PGOUSE: br {{.*}} !prof ![[TH6:[0-9]+]]
if (i < 100) {}
}
// PGOUSE-NOT: br {{.*}} !prof ![0-9]+
// PGOUSE: ret void
}
// PGOUSE-DAG: ![[TH1]] = metadata !{metadata !"branch_weights", i32 101, i32 2}
// PGOUSE-DAG: ![[TH2]] = metadata !{metadata !"branch_weights", i32 67, i32 35}
// PGOUSE-DAG: ![[TH3]] = metadata !{metadata !"branch_weights", i32 34, i32 34}
// PGOUSE-DAG: ![[TH4]] = metadata !{metadata !"branch_weights", i32 18, i32 18}
// PGOUSE-EXC: ![[TH5]] = metadata !{metadata !"branch_weights", i32 34, i32 18}
// PGOUSE-DAG: ![[TH6]] = metadata !{metadata !"branch_weights", i32 101, i32 1}
int main(int argc, const char *argv[]) {
throws();
return 0;
}