diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 |
commit | 6148c19c738a92f344008aa3f88f4e008bada0ee (patch) | |
tree | d4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h | |
parent | 2c8643c6396b0a3db33430cf9380e70bbb9efce0 (diff) | |
parent | 173a4f43a911175643bda81ee675e8d9269056ea (diff) | |
download | FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.zip FreeBSD-src-6148c19c738a92f344008aa3f88f4e008bada0ee.tar.gz |
Merge clang 3.5.0 release from ^/vendor/clang/dist, resolve conflicts,
and preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h new file mode 100644 index 0000000..2f4aa66 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenPGO.h @@ -0,0 +1,236 @@ +//===--- 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/StringMap.h" +#include "llvm/Support/MemoryBuffer.h" +#include <memory> + +namespace clang { +namespace CodeGen { +class RegionCounter; + +/// 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; + std::unique_ptr<std::string> PrefixedFuncName; + StringRef RawFuncName; + llvm::GlobalValue::LinkageTypes VarLinkage; + + unsigned NumRegionCounters; + uint64_t FunctionHash; + llvm::GlobalVariable *RegionCounters; + std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap; + std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap; + std::unique_ptr<std::vector<uint64_t>> RegionCounts; + uint64_t CurrentRegionCount; + +public: + CodeGenPGO(CodeGenModule &CGM) + : CGM(CGM), NumRegionCounters(0), FunctionHash(0), + RegionCounters(nullptr), CurrentRegionCount(0) {} + + /// 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 != nullptr; } + + /// Get the string used to identify this function in the profile data. + /// For functions with local linkage, this includes the main file name. + StringRef getFuncName() const { return StringRef(*PrefixedFuncName); } + std::string getFuncVarName(StringRef VarName) const { + return ("__llvm_profile_" + VarName + "_" + RawFuncName).str(); + } + + /// Return the counter value of the current region. + uint64_t getCurrentRegionCount() const { return 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; } + + /// Indicate that the current region is never reached, and thus should have a + /// counter value of zero. This is important so that subsequent regions can + /// correctly track their parent counts. + void setCurrentRegionUnreachable() { setCurrentRegionCount(0); } + + /// Check if an execution count is known for a given statement. If so, return + /// true and put the value in Count; else return false. + bool getStmtCount(const Stmt *S, uint64_t &Count) { + if (!StmtCountMap) + return false; + llvm::DenseMap<const Stmt*, uint64_t>::const_iterator + I = StmtCountMap->find(S); + if (I == StmtCountMap->end()) + return false; + Count = I->second; + return true; + } + + /// If the execution count for the current statement is known, record that + /// as the current count. + void setCurrentStmt(const Stmt *S) { + uint64_t Count; + if (getStmtCount(S, Count)) + setCurrentRegionCount(Count); + } + + /// Calculate branch weights appropriate for PGO data + llvm::MDNode *createBranchWeights(uint64_t TrueCount, uint64_t FalseCount); + llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights); + llvm::MDNode *createLoopWeights(const Stmt *Cond, RegionCounter &Cnt); + + /// 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(const Decl *D, llvm::Function *Fn); + /// Emit static data structures for instrumentation data. + void emitInstrumentationData(); + /// Clean up region counter state. Must be called if assignRegionCounters is + /// used. + void destroyRegionCounters(); + /// Emit static initialization code, if any. + static llvm::Function *emitInitialization(CodeGenModule &CGM); + +private: + void setFuncName(llvm::Function *Fn); + void mapRegionCounters(const Decl *D); + void computeRegionCounts(const Decl *D); + void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, + llvm::Function *Fn); + void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, + bool IsInMainFile); + void emitCounterVariables(); + llvm::GlobalVariable *buildDataVar(); + + /// 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) + 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; i.e., 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 { + return Count + Adjust; + } + + /// Get the value of the counter in this region's parent, i.e., 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; } + + /// 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) { + beginRegion(AddIncomingFallThrough); + PGO->emitCounterIncrement(Builder, Counter); + } + void beginRegion(bool AddIncomingFallThrough=false) { + RegionCount = Count; + if (AddIncomingFallThrough) + RegionCount += PGO->getCurrentRegionCount(); + PGO->setCurrentRegionCount(RegionCount); + } + + /// For counters on boolean branches, begins tracking adjustments for the + /// uncounted path. + void beginElseRegion() { + RegionCount = ParentCount - Count; + PGO->setCurrentRegionCount(RegionCount); + } + + /// Reset the current region count. + void setCurrentRegionCount(uint64_t CurrentCount) { + RegionCount = CurrentCount; + PGO->setCurrentRegionCount(RegionCount); + } + + /// Adjust for non-local control flow after emitting a subexpression or + /// substatement. This must be called to account for constructs such as gotos, + /// labels, and returns, so that we can ensure that our region's count is + /// correct in the code that follows. + void adjustForControlFlow() { + Adjust += PGO->getCurrentRegionCount() - RegionCount; + // Reset the region count in case this is called again later. + RegionCount = PGO->getCurrentRegionCount(); + } + + /// Commit all adjustments to the current region. If the region is a loop, + /// the LoopAdjust value should be the count of all the breaks and continues + /// from the loop, to compensate for those counts being deducted from the + /// adjustments for the body of the loop. + void applyAdjustmentsToRegion(uint64_t LoopAdjust) { + PGO->setCurrentRegionCount(ParentCount + Adjust + LoopAdjust); + } +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif |