Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===--- CodeGenPGO.h - PGO Instrumentation for LLVM CodeGen ----*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // Instrumentation-based profile-guided optimization
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H
     14 #define LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H
     15 
     16 #include "CGBuilder.h"
     17 #include "CodeGenModule.h"
     18 #include "CodeGenTypes.h"
     19 #include "llvm/ProfileData/InstrProfReader.h"
     20 #include <array>
     21 #include <memory>
     22 
     23 namespace clang {
     24 namespace CodeGen {
     25 
     26 /// Per-function PGO state.
     27 class CodeGenPGO {
     28 private:
     29   CodeGenModule &CGM;
     30   std::string FuncName;
     31   llvm::GlobalVariable *FuncNameVar;
     32 
     33   std::array <unsigned, llvm::IPVK_Last + 1> NumValueSites;
     34   unsigned NumRegionCounters;
     35   uint64_t FunctionHash;
     36   std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap;
     37   std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;
     38   std::unique_ptr<llvm::InstrProfRecord> ProfRecord;
     39   std::vector<uint64_t> RegionCounts;
     40   uint64_t CurrentRegionCount;
     41 
     42 public:
     43   CodeGenPGO(CodeGenModule &CGModule)
     44       : CGM(CGModule), FuncNameVar(nullptr), NumValueSites({{0}}),
     45         NumRegionCounters(0), FunctionHash(0), CurrentRegionCount(0) {}
     46 
     47   /// Whether or not we have PGO region data for the current function. This is
     48   /// false both when we have no data at all and when our data has been
     49   /// discarded.
     50   bool haveRegionCounts() const { return !RegionCounts.empty(); }
     51 
     52   /// Return the counter value of the current region.
     53   uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }
     54 
     55   /// Set the counter value for the current region. This is used to keep track
     56   /// of changes to the most recent counter from control flow and non-local
     57   /// exits.
     58   void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }
     59 
     60   /// Check if an execution count is known for a given statement. If so, return
     61   /// true and put the value in Count; else return false.
     62   Optional<uint64_t> getStmtCount(const Stmt *S) const {
     63     if (!StmtCountMap)
     64       return None;
     65     auto I = StmtCountMap->find(S);
     66     if (I == StmtCountMap->end())
     67       return None;
     68     return I->second;
     69   }
     70 
     71   /// If the execution count for the current statement is known, record that
     72   /// as the current count.
     73   void setCurrentStmt(const Stmt *S) {
     74     if (auto Count = getStmtCount(S))
     75       setCurrentRegionCount(*Count);
     76   }
     77 
     78   /// Assign counters to regions and configure them for PGO of a given
     79   /// function. Does nothing if instrumentation is not enabled and either
     80   /// generates global variables or associates PGO data with each of the
     81   /// counters depending on whether we are generating or using instrumentation.
     82   void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn);
     83   /// Emit a coverage mapping range with a counter zero
     84   /// for an unused declaration.
     85   void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
     86                                llvm::GlobalValue::LinkageTypes Linkage);
     87   // Insert instrumentation or attach profile metadata at value sites
     88   void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
     89                     llvm::Instruction *ValueSite, llvm::Value *ValuePtr);
     90 
     91   // Set a module flag indicating if value profiling is enabled.
     92   void setValueProfilingFlag(llvm::Module &M);
     93 
     94 private:
     95   void setFuncName(llvm::Function *Fn);
     96   void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
     97   void mapRegionCounters(const Decl *D);
     98   void computeRegionCounts(const Decl *D);
     99   void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
    100                                llvm::Function *Fn);
    101   void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
    102                         bool IsInMainFile);
    103   bool skipRegionMappingForDecl(const Decl *D);
    104   void emitCounterRegionMapping(const Decl *D);
    105 
    106 public:
    107   void emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
    108                             llvm::Value *StepV);
    109 
    110   /// Return the region count for the counter at the given index.
    111   uint64_t getRegionCount(const Stmt *S) {
    112     if (!RegionCounterMap)
    113       return 0;
    114     if (!haveRegionCounts())
    115       return 0;
    116     return RegionCounts[(*RegionCounterMap)[S]];
    117   }
    118 };
    119 
    120 }  // end namespace CodeGen
    121 }  // end namespace clang
    122 
    123 #endif
    124