#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H
#define LLVM_CLANG_LIB_CODEGEN_CODEGENPGO_H
#include "CGBuilder.h"
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
#include "MCDCState.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include <array>
#include <memory>
#include <optional>
namespace clang {
namespace CodeGen {
class CodeGenPGO {
private:
CodeGenModule &CGM;
std::string FuncName;
llvm::GlobalVariable *FuncNameVar;
std::array <unsigned, llvm::IPVK_Last + 1> NumValueSites;
unsigned NumRegionCounters;
uint64_t FunctionHash;
std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap;
std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;
std::unique_ptr<llvm::InstrProfRecord> ProfRecord;
std::unique_ptr<MCDC::State> RegionMCDCState;
std::vector<uint64_t> RegionCounts;
uint64_t CurrentRegionCount;
public:
CodeGenPGO(CodeGenModule &CGModule)
: CGM(CGModule), FuncNameVar(nullptr), NumValueSites({{0}}),
NumRegionCounters(0), FunctionHash(0), CurrentRegionCount(0) {}
bool haveRegionCounts() const { return !RegionCounts.empty(); }
uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }
void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }
std::optional<uint64_t> getStmtCount(const Stmt *S) const {
if (!StmtCountMap)
return std::nullopt;
auto I = StmtCountMap->find(S);
if (I == StmtCountMap->end())
return std::nullopt;
return I->second;
}
void setCurrentStmt(const Stmt *S) {
if (auto Count = getStmtCount(S))
setCurrentRegionCount(*Count);
}
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn);
void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
llvm::GlobalValue::LinkageTypes Linkage);
void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
llvm::Instruction *ValueSite, llvm::Value *ValuePtr);
void setValueProfilingFlag(llvm::Module &M);
void setProfileVersion(llvm::Module &M);
private:
void setFuncName(llvm::Function *Fn);
void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
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);
bool skipRegionMappingForDecl(const Decl *D);
void emitCounterRegionMapping(const Decl *D);
bool canEmitMCDCCoverage(const CGBuilderTy &Builder);
public:
void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
llvm::Value *StepV);
void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
Address MCDCCondBitmapAddr,
CodeGenFunction &CGF);
void emitMCDCParameters(CGBuilderTy &Builder);
void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S,
Address MCDCCondBitmapAddr);
void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
Address MCDCCondBitmapAddr, llvm::Value *Val,
CodeGenFunction &CGF);
uint64_t getRegionCount(const Stmt *S) {
if (!RegionCounterMap)
return 0;
if (!haveRegionCounts())
return 0;
auto Index = (*RegionCounterMap)[S];
if (Index >= RegionCounts.size())
return 0;
return RegionCounts[Index];
}
};
}
}
#endif