157 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Instrumentation-based profile-guided optimization10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H14#define LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H15 16#include "CGBuilder.h"17#include "CodeGenModule.h"18#include "CodeGenTypes.h"19#include "MCDCState.h"20#include "llvm/ProfileData/InstrProfReader.h"21#include <array>22#include <memory>23#include <optional>24 25namespace clang {26namespace CodeGen {27 28/// Per-function PGO state.29class CodeGenPGO {30private:31 CodeGenModule &CGM;32 std::string FuncName;33 llvm::GlobalVariable *FuncNameVar;34 35 std::array <unsigned, llvm::IPVK_Last + 1> NumValueSites;36 unsigned NumRegionCounters;37 uint64_t FunctionHash;38 std::unique_ptr<llvm::DenseMap<const Stmt *, CounterPair>> RegionCounterMap;39 std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;40 std::unique_ptr<llvm::InstrProfRecord> ProfRecord;41 std::unique_ptr<MCDC::State> RegionMCDCState;42 std::vector<uint64_t> RegionCounts;43 uint64_t CurrentRegionCount;44 45public:46 CodeGenPGO(CodeGenModule &CGModule)47 : CGM(CGModule), FuncNameVar(nullptr), NumValueSites({{0}}),48 NumRegionCounters(0), FunctionHash(0), CurrentRegionCount(0) {}49 50 /// Whether or not we have PGO region data for the current function. This is51 /// false both when we have no data at all and when our data has been52 /// discarded.53 bool haveRegionCounts() const { return !RegionCounts.empty(); }54 55 /// Return the counter value of the current region.56 uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }57 58 /// Set the counter value for the current region. This is used to keep track59 /// of changes to the most recent counter from control flow and non-local60 /// exits.61 void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }62 63 /// Check if an execution count is known for a given statement. If so, return64 /// true and put the value in Count; else return false.65 std::optional<uint64_t> getStmtCount(const Stmt *S) const {66 if (!StmtCountMap)67 return std::nullopt;68 auto I = StmtCountMap->find(S);69 if (I == StmtCountMap->end())70 return std::nullopt;71 return I->second;72 }73 74 /// If the execution count for the current statement is known, record that75 /// as the current count.76 void setCurrentStmt(const Stmt *S) {77 if (auto Count = getStmtCount(S))78 setCurrentRegionCount(*Count);79 }80 81 /// Assign counters to regions and configure them for PGO of a given82 /// function. Does nothing if instrumentation is not enabled and either83 /// generates global variables or associates PGO data with each of the84 /// counters depending on whether we are generating or using instrumentation.85 void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn);86 /// Emit a coverage mapping range with a counter zero87 /// for an unused declaration.88 void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,89 llvm::GlobalValue::LinkageTypes Linkage);90 // Insert instrumentation or attach profile metadata at value sites91 void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,92 llvm::Instruction *ValueSite, llvm::Value *ValuePtr);93 94 // Set a module flag indicating if value profiling is enabled.95 void setValueProfilingFlag(llvm::Module &M);96 97 void setProfileVersion(llvm::Module &M);98 99private:100 void setFuncName(llvm::Function *Fn);101 void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);102 void mapRegionCounters(const Decl *D);103 void computeRegionCounts(const Decl *D);104 void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,105 llvm::Function *Fn);106 void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,107 bool IsInMainFile);108 bool skipRegionMappingForDecl(const Decl *D);109 void emitCounterRegionMapping(const Decl *D);110 bool canEmitMCDCCoverage(const CGBuilderTy &Builder);111 112public:113 std::pair<bool, bool> getIsCounterPair(const Stmt *S) const;114 void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,115 llvm::Value *StepV);116 void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,117 Address MCDCCondBitmapAddr,118 CodeGenFunction &CGF);119 void emitMCDCParameters(CGBuilderTy &Builder);120 void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S,121 Address MCDCCondBitmapAddr);122 void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S,123 Address MCDCCondBitmapAddr, llvm::Value *Val,124 CodeGenFunction &CGF);125 126 void markStmtAsUsed(bool Skipped, const Stmt *S) {127 // Do nothing.128 }129 130 void markStmtMaybeUsed(const Stmt *S) {131 // Do nothing.132 }133 134 void verifyCounterMap() const {135 // Do nothing.136 }137 138 /// Return the region count for the counter at the given index.139 uint64_t getRegionCount(const Stmt *S) {140 if (!RegionCounterMap)141 return 0;142 if (!haveRegionCounts())143 return 0;144 // With profiles from a differing version of clang we can have mismatched145 // decl counts. Don't crash in such a case.146 auto Index = (*RegionCounterMap)[S].Executed;147 if (Index >= RegionCounts.size())148 return 0;149 return RegionCounts[Index];150 }151};152 153} // end namespace CodeGen154} // end namespace clang155 156#endif157