20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/MDBuilder.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/Endian.h"
24#include "llvm/Support/MD5.h"
31static llvm::cl::opt<bool>
33 llvm::cl::desc(
"Enable value profiling"),
34 llvm::cl::Hidden, llvm::cl::init(
false));
39void CodeGenPGO::setFuncName(StringRef Name,
40 llvm::GlobalValue::LinkageTypes
Linkage) {
41 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
42 FuncName = llvm::getPGOFuncName(
44 PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
48 FuncNameVar = llvm::createPGOFuncNameVar(CGM.
getModule(),
Linkage, FuncName);
51void CodeGenPGO::setFuncName(llvm::Function *Fn) {
52 setFuncName(
Fn->getName(),
Fn->getLinkage());
54 llvm::createPGOFuncNameMetadata(*Fn, FuncName);
85 static const int NumBitsPerType = 6;
86 static const unsigned NumTypesPerWord =
sizeof(
uint64_t) * 8 / NumBitsPerType;
87 static const unsigned TooBig = 1u << NumBitsPerType;
97 enum HashType :
unsigned char {
104 ObjCForCollectionStmt,
114 BinaryConditionalOperator,
138 static_assert(LastHashType <= TooBig,
"Too many types in HashType");
141 : Working(0), Count(0), HashVersion(HashVersion) {}
142 void combine(HashType
Type);
146const int PGOHash::NumBitsPerType;
147const unsigned PGOHash::NumTypesPerWord;
148const unsigned PGOHash::TooBig;
151static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
153 if (PGOReader->getVersion() <= 4)
155 if (PGOReader->getVersion() <= 5)
157 if (PGOReader->getVersion() <= 12)
163struct MapRegionCounters :
public RecursiveASTVisitor<MapRegionCounters> {
164 using Base = RecursiveASTVisitor<MapRegionCounters>;
167 unsigned NextCounter;
171 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
173 MCDC::State &MCDCState;
175 unsigned MCDCMaxCond;
179 DiagnosticsEngine &
Diag;
181 MapRegionCounters(
PGOHashVersion HashVersion, uint64_t ProfileVersion,
182 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
183 MCDC::State &MCDCState,
unsigned MCDCMaxCond,
184 DiagnosticsEngine &
Diag)
185 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
186 MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
187 ProfileVersion(ProfileVersion),
Diag(
Diag) {}
191 bool TraverseBlockExpr(BlockExpr *BE) {
return true; }
194 for (
auto C : zip(
LE->captures(),
LE->capture_inits()))
195 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
198 bool TraverseCapturedStmt(CapturedStmt *CS) {
return true; }
200 bool VisitDecl(
const Decl *D) {
205 case Decl::CXXMethod:
206 case Decl::CXXConstructor:
207 case Decl::CXXDestructor:
208 case Decl::CXXConversion:
209 case Decl::ObjCMethod:
212 CounterMap[D->
getBody()] = NextCounter++;
220 PGOHash::HashType updateCounterMappings(Stmt *S) {
222 if (
Type != PGOHash::None)
223 CounterMap[S] = NextCounter++;
236 unsigned NumCond = 0;
237 bool SplitNestedLogicalOp =
false;
238 SmallVector<const Stmt *, 16> NonLogOpStack;
239 SmallVector<const BinaryOperator *, 16> LogOpStack;
242 bool dataTraverseStmtPre(Stmt *S) {
244 if (MCDCMaxCond == 0)
249 if (LogOpStack.empty()) {
251 SplitNestedLogicalOp =
false;
254 if (
const Expr *E = dyn_cast<Expr>(S)) {
255 if (
const auto *BinOp =
257 BinOp && BinOp->isLogicalOp()) {
265 SplitNestedLogicalOp = SplitNestedLogicalOp || !NonLogOpStack.empty();
267 LogOpStack.push_back(BinOp);
274 if (!LogOpStack.empty())
275 NonLogOpStack.push_back(S);
283 bool dataTraverseStmtPost(Stmt *S) {
285 if (MCDCMaxCond == 0)
288 if (
const Expr *E = dyn_cast<Expr>(S)) {
289 const BinaryOperator *BinOp =
292 assert(LogOpStack.back() == BinOp);
293 LogOpStack.pop_back();
296 if (LogOpStack.empty()) {
298 if (SplitNestedLogicalOp) {
304 if (NumCond > MCDCMaxCond) {
306 << NumCond << MCDCMaxCond;
317 if (!LogOpStack.empty())
318 NonLogOpStack.pop_back();
328 bool VisitBinaryOperator(BinaryOperator *S) {
334 if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
335 CounterMap[S->
getRHS()] = NextCounter++;
340 return Base::VisitBinaryOperator(S);
343 bool VisitConditionalOperator(ConditionalOperator *S) {
348 return Base::VisitConditionalOperator(S);
352 bool VisitStmt(Stmt *S) {
353 auto Type = updateCounterMappings(S);
355 Type = getHashType(Hash.getHashVersion(), S);
356 if (
Type != PGOHash::None)
361 bool TraverseIfStmt(IfStmt *
If) {
364 return Base::TraverseIfStmt(
If);
369 for (Stmt *CS :
If->children()) {
370 if (!CS || NoSingleByteCoverage)
372 if (CS ==
If->getThen())
373 CounterMap[
If->getThen()] = NextCounter++;
374 else if (CS ==
If->getElse())
375 CounterMap[
If->getElse()] = NextCounter++;
381 for (Stmt *CS :
If->children()) {
384 if (CS ==
If->getThen())
385 Hash.combine(PGOHash::IfThenBranch);
386 else if (CS ==
If->getElse())
387 Hash.combine(PGOHash::IfElseBranch);
390 Hash.combine(PGOHash::EndOfScope);
394 bool TraverseWhileStmt(WhileStmt *While) {
398 for (Stmt *CS : While->
children()) {
399 if (!CS || NoSingleByteCoverage)
402 CounterMap[While->
getCond()] = NextCounter++;
403 else if (CS == While->
getBody())
404 CounterMap[While->
getBody()] = NextCounter++;
407 Base::TraverseWhileStmt(While);
409 Hash.combine(PGOHash::EndOfScope);
413 bool TraverseDoStmt(DoStmt *Do) {
418 if (!CS || NoSingleByteCoverage)
421 CounterMap[Do->
getCond()] = NextCounter++;
423 CounterMap[Do->
getBody()] = NextCounter++;
426 Base::TraverseDoStmt(Do);
428 Hash.combine(PGOHash::EndOfScope);
432 bool TraverseForStmt(ForStmt *For) {
437 if (!CS || NoSingleByteCoverage)
440 CounterMap[For->
getCond()] = NextCounter++;
441 else if (CS == For->
getInc())
442 CounterMap[For->
getInc()] = NextCounter++;
444 CounterMap[For->
getBody()] = NextCounter++;
447 Base::TraverseForStmt(For);
449 Hash.combine(PGOHash::EndOfScope);
453 bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) {
456 for (Stmt *CS : ForRange->
children()) {
457 if (!CS || NoSingleByteCoverage)
460 CounterMap[ForRange->
getBody()] = NextCounter++;
463 Base::TraverseCXXForRangeStmt(ForRange);
465 Hash.combine(PGOHash::EndOfScope);
472#define DEFINE_NESTABLE_TRAVERSAL(N) \
473 bool Traverse##N(N *S) { \
474 Base::Traverse##N(S); \
475 if (Hash.getHashVersion() != PGO_HASH_V1) \
476 Hash.combine(PGOHash::EndOfScope); \
489 case Stmt::LabelStmtClass:
490 return PGOHash::LabelStmt;
491 case Stmt::WhileStmtClass:
492 return PGOHash::WhileStmt;
493 case Stmt::DoStmtClass:
494 return PGOHash::DoStmt;
495 case Stmt::ForStmtClass:
496 return PGOHash::ForStmt;
497 case Stmt::CXXForRangeStmtClass:
498 return PGOHash::CXXForRangeStmt;
499 case Stmt::ObjCForCollectionStmtClass:
500 return PGOHash::ObjCForCollectionStmt;
501 case Stmt::SwitchStmtClass:
502 return PGOHash::SwitchStmt;
503 case Stmt::CaseStmtClass:
504 return PGOHash::CaseStmt;
505 case Stmt::DefaultStmtClass:
506 return PGOHash::DefaultStmt;
507 case Stmt::IfStmtClass:
508 return PGOHash::IfStmt;
509 case Stmt::CXXTryStmtClass:
510 return PGOHash::CXXTryStmt;
511 case Stmt::CXXCatchStmtClass:
512 return PGOHash::CXXCatchStmt;
513 case Stmt::ConditionalOperatorClass:
514 return PGOHash::ConditionalOperator;
515 case Stmt::BinaryConditionalOperatorClass:
516 return PGOHash::BinaryConditionalOperator;
517 case Stmt::BinaryOperatorClass: {
520 return PGOHash::BinaryOperatorLAnd;
522 return PGOHash::BinaryOperatorLOr;
528 return PGOHash::BinaryOperatorLT;
530 return PGOHash::BinaryOperatorGT;
532 return PGOHash::BinaryOperatorLE;
534 return PGOHash::BinaryOperatorGE;
536 return PGOHash::BinaryOperatorEQ;
538 return PGOHash::BinaryOperatorNE;
549 case Stmt::GotoStmtClass:
550 return PGOHash::GotoStmt;
551 case Stmt::IndirectGotoStmtClass:
552 return PGOHash::IndirectGotoStmt;
553 case Stmt::BreakStmtClass:
554 return PGOHash::BreakStmt;
555 case Stmt::ContinueStmtClass:
556 return PGOHash::ContinueStmt;
557 case Stmt::ReturnStmtClass:
558 return PGOHash::ReturnStmt;
559 case Stmt::CXXThrowExprClass:
560 return PGOHash::ThrowExpr;
561 case Stmt::UnaryOperatorClass: {
564 return PGOHash::UnaryOperatorLNot;
570 return PGOHash::None;
576struct ComputeRegionCounts :
public ConstStmtVisitor<ComputeRegionCounts> {
582 bool RecordNextStmtCount;
588 llvm::DenseMap<const Stmt *, uint64_t> &
CountMap;
591 struct BreakContinue {
594 BreakContinue() =
default;
596 SmallVector<BreakContinue, 8> BreakContinueStack;
598 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &
CountMap,
602 void RecordStmtCount(
const Stmt *S) {
603 if (RecordNextStmtCount) {
605 RecordNextStmtCount =
false;
611 CurrentCount = Count;
615 void VisitStmt(
const Stmt *S) {
617 for (
const Stmt *Child : S->
children())
622 void VisitFunctionDecl(
const FunctionDecl *D) {
634 void VisitCapturedDecl(
const CapturedDecl *D) {
641 void VisitObjCMethodDecl(
const ObjCMethodDecl *D) {
648 void VisitBlockDecl(
const BlockDecl *D) {
655 void VisitReturnStmt(
const ReturnStmt *S) {
660 RecordNextStmtCount =
true;
663 void VisitCXXThrowExpr(
const CXXThrowExpr *E) {
668 RecordNextStmtCount =
true;
671 void VisitGotoStmt(
const GotoStmt *S) {
674 RecordNextStmtCount =
true;
677 void VisitLabelStmt(
const LabelStmt *S) {
678 RecordNextStmtCount =
false;
685 void VisitBreakStmt(
const BreakStmt *S) {
687 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
688 BreakContinueStack.back().BreakCount += CurrentCount;
690 RecordNextStmtCount =
true;
693 void VisitContinueStmt(
const ContinueStmt *S) {
695 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
696 BreakContinueStack.back().ContinueCount += CurrentCount;
698 RecordNextStmtCount =
true;
701 void VisitWhileStmt(
const WhileStmt *S) {
703 uint64_t ParentCount = CurrentCount;
705 BreakContinueStack.push_back(BreakContinue());
711 uint64_t BackedgeCount = CurrentCount;
717 BreakContinue BC = BreakContinueStack.pop_back_val();
719 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
722 setCount(BC.BreakCount + CondCount - BodyCount);
723 RecordNextStmtCount =
true;
726 void VisitDoStmt(
const DoStmt *S) {
730 BreakContinueStack.push_back(BreakContinue());
732 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
735 uint64_t BackedgeCount = CurrentCount;
737 BreakContinue BC = BreakContinueStack.pop_back_val();
740 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
743 setCount(BC.BreakCount + CondCount - LoopCount);
744 RecordNextStmtCount =
true;
747 void VisitForStmt(
const ForStmt *S) {
752 uint64_t ParentCount = CurrentCount;
754 BreakContinueStack.push_back(BreakContinue());
760 uint64_t BackedgeCount = CurrentCount;
761 BreakContinue BC = BreakContinueStack.pop_back_val();
766 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
773 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
778 setCount(BC.BreakCount + CondCount - BodyCount);
779 RecordNextStmtCount =
true;
782 void VisitCXXForRangeStmt(
const CXXForRangeStmt *S) {
791 uint64_t ParentCount = CurrentCount;
792 BreakContinueStack.push_back(BreakContinue());
798 uint64_t BackedgeCount = CurrentCount;
799 BreakContinue BC = BreakContinueStack.pop_back_val();
803 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
809 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
812 setCount(BC.BreakCount + CondCount - BodyCount);
813 RecordNextStmtCount =
true;
816 void VisitObjCForCollectionStmt(
const ObjCForCollectionStmt *S) {
819 uint64_t ParentCount = CurrentCount;
820 BreakContinueStack.push_back(BreakContinue());
825 uint64_t BackedgeCount = CurrentCount;
826 BreakContinue BC = BreakContinueStack.pop_back_val();
828 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
830 RecordNextStmtCount =
true;
833 void VisitSwitchStmt(
const SwitchStmt *S) {
839 BreakContinueStack.push_back(BreakContinue());
842 BreakContinue BC = BreakContinueStack.pop_back_val();
843 if (!BreakContinueStack.empty())
844 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
847 RecordNextStmtCount =
true;
850 void VisitSwitchCase(
const SwitchCase *S) {
851 RecordNextStmtCount =
false;
856 setCount(CurrentCount + CaseCount);
860 RecordNextStmtCount =
true;
864 void VisitIfStmt(
const IfStmt *S) {
874 uint64_t ParentCount = CurrentCount;
886 uint64_t ElseCount = ParentCount - ThenCount;
891 OutCount += CurrentCount;
893 OutCount += ElseCount;
895 RecordNextStmtCount =
true;
898 void VisitCXXTryStmt(
const CXXTryStmt *S) {
905 RecordNextStmtCount =
true;
908 void VisitCXXCatchStmt(
const CXXCatchStmt *S) {
909 RecordNextStmtCount =
false;
916 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *E) {
918 uint64_t ParentCount = CurrentCount;
928 uint64_t FalseCount = setCount(ParentCount - TrueCount);
931 OutCount += CurrentCount;
934 RecordNextStmtCount =
true;
937 void VisitBinLAnd(
const BinaryOperator *E) {
939 uint64_t ParentCount = CurrentCount;
945 setCount(ParentCount + RHSCount - CurrentCount);
946 RecordNextStmtCount =
true;
949 void VisitBinLOr(
const BinaryOperator *E) {
951 uint64_t ParentCount = CurrentCount;
957 setCount(ParentCount + RHSCount - CurrentCount);
958 RecordNextStmtCount =
true;
963void PGOHash::combine(HashType
Type) {
965 assert(
Type &&
"Hash is invalid: unexpected type 0");
966 assert(
unsigned(
Type) < TooBig &&
"Hash is invalid: too many types");
969 if (Count && Count % NumTypesPerWord == 0) {
970 using namespace llvm::support;
972 endian::byte_swap<uint64_t>(Working, llvm::endianness::little);
973 MD5.update(llvm::ArrayRef((uint8_t *)&Swapped,
sizeof(Swapped)));
979 Working = Working << NumBitsPerType |
Type;
984 if (Count <= NumTypesPerWord)
995 MD5.update({(uint8_t)Working});
997 using namespace llvm::support;
999 endian::byte_swap<uint64_t>(Working, llvm::endianness::little);
1000 MD5.update(llvm::ArrayRef((uint8_t *)&Swapped,
sizeof(Swapped)));
1005 llvm::MD5::MD5Result
Result;
1016 if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice &&
1020 bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
1021 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1022 if (!InstrumentRegions && !PGOReader)
1029 if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
1030 if (
const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
1038 CGM.ClearUnusedCoverageMapping(D);
1039 if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
1041 if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
1051 mapRegionCounters(D);
1052 if (CGM.getCodeGenOpts().CoverageMapping)
1053 emitCounterRegionMapping(D);
1055 loadRegionCounts(PGOReader,
SM.isInMainFile(D->
getLocation()));
1056 computeRegionCounts(D);
1057 applyFunctionAttributes(PGOReader, Fn);
1061void CodeGenPGO::mapRegionCounters(
const Decl *D) {
1065 uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
1067 HashVersion = getPGOHashVersion(PGOReader, CGM);
1068 ProfileVersion = PGOReader->getVersion();
1080 unsigned MCDCMaxConditions =
1084 RegionCounterMap.reset(
new llvm::DenseMap<const Stmt *, CounterPair>);
1086 MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
1087 *RegionMCDCState, MCDCMaxConditions, CGM.
getDiags());
1088 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
1090 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
1092 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
1093 Walker.TraverseDecl(
const_cast<BlockDecl *
>(BD));
1094 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
1096 assert(Walker.NextCounter > 0 &&
"no entry counter mapped for decl");
1097 NumRegionCounters = Walker.NextCounter;
1098 FunctionHash = Walker.Hash.finalize();
1100 FunctionHash &= llvm::NamedInstrProfRecord::FUNC_HASH_MASK;
1103bool CodeGenPGO::skipRegionMappingForDecl(
const Decl *D) {
1113 !D->
hasAttr<CUDAGlobalAttr>()) ||
1115 (D->
hasAttr<CUDAGlobalAttr>() ||
1116 (!D->
hasAttr<CUDAHostAttr>() && D->
hasAttr<CUDADeviceAttr>())))))
1125void CodeGenPGO::emitCounterRegionMapping(
const Decl *D) {
1126 if (skipRegionMappingForDecl(D))
1129 std::string CoverageMapping;
1130 llvm::raw_string_ostream
OS(CoverageMapping);
1131 RegionMCDCState->BranchByStmt.clear();
1132 CoverageMappingGen MappingGen(
1133 *CGM.getCoverageMapping(), CGM.getContext().getSourceManager(),
1134 CGM.getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1135 MappingGen.emitCounterMapping(D, OS);
1137 if (CoverageMapping.empty())
1141 unsigned MaxNumCounters = NumRegionCounters;
1142 for (
const auto &[_,
V] : *RegionCounterMap) {
1143 assert((!
V.Executed.hasValue() || MaxNumCounters >
V.Executed) &&
1144 "TrueCnt should not be reassigned");
1145 if (
V.Skipped.hasValue())
1146 MaxNumCounters = std::max(MaxNumCounters,
V.Skipped + 1);
1148 NumRegionCounters = MaxNumCounters;
1150 CGM.getCoverageMapping()->addFunctionMappingRecord(
1151 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1156 llvm::GlobalValue::LinkageTypes
Linkage) {
1157 if (skipRegionMappingForDecl(D))
1160 std::string CoverageMapping;
1161 llvm::raw_string_ostream OS(CoverageMapping);
1163 CGM.getContext().getSourceManager(),
1167 if (CoverageMapping.empty())
1171 CGM.getCoverageMapping()->addFunctionMappingRecord(
1172 FuncNameVar, FuncName, FunctionHash, CoverageMapping,
false);
1175void CodeGenPGO::computeRegionCounts(
const Decl *D) {
1176 StmtCountMap.reset(
new llvm::DenseMap<const Stmt *, uint64_t>);
1177 ComputeRegionCounts Walker(*StmtCountMap, *
this);
1178 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
1179 Walker.VisitFunctionDecl(FD);
1180 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
1181 Walker.VisitObjCMethodDecl(MD);
1182 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
1183 Walker.VisitBlockDecl(BD);
1184 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
1185 Walker.VisitCapturedDecl(
const_cast<CapturedDecl *
>(CD));
1189CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1190 llvm::Function *Fn) {
1195 Fn->setEntryCount(FunctionCount);
1199 if (!RegionCounterMap)
1200 return {
false,
false};
1202 auto I = RegionCounterMap->find(S);
1203 if (I == RegionCounterMap->end())
1204 return {
false,
false};
1206 return {I->second.Executed.hasValue(), I->second.Skipped.hasValue()};
1210 bool UseSkipPath,
bool UseBoth,
1211 llvm::Value *StepV) {
1212 if (!RegionCounterMap)
1216 const auto &TheCounterPair = (*RegionCounterMap)[S];
1218 if (!Builder.GetInsertBlock())
1222 (UseSkipPath ? TheCounterPair.Skipped : TheCounterPair.Executed);
1228 auto *NormalizedFuncNameVarPtr =
1229 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1230 FuncNameVar, llvm::PointerType::get(CGM.getLLVMContext(), 0));
1232 llvm::Value *Args[] = {
1233 NormalizedFuncNameVarPtr, Builder.getInt64(FunctionHash),
1234 Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV};
1237 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover),
1240 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
1244 CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
1247bool CodeGenPGO::canEmitMCDCCoverage(
const CGBuilderTy &Builder) {
1253 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1256 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1261 llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1262 Builder.getInt64(FunctionHash),
1263 Builder.getInt32(RegionMCDCState->BitmapBits)};
1265 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
1269std::vector<Address *>
1271 std::vector<Address *>
Result;
1273 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1277 for (
auto &[_,
V] : RegionMCDCState->DecisionByStmt)
1279 SortedPair.emplace_back(
V.ID, &
V.MCDCCondBitmapAddr);
1281 llvm::sort(SortedPair);
1283 for (
auto &[_, MCDCCondBitmapAddr] : SortedPair)
1284 Result.push_back(MCDCCondBitmapAddr);
1292 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1297 auto DecisionStateIter = RegionMCDCState->DecisionByStmt.find(S);
1298 if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
1301 auto &MCDCCondBitmapAddr = DecisionStateIter->second.MCDCCondBitmapAddr;
1302 if (!MCDCCondBitmapAddr.isValid())
1307 if (DecisionStateIter->second.Indices.size() == 0)
1311 unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
1312 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1319 llvm::Value *Args[4] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1320 Builder.getInt64(FunctionHash),
1321 Builder.getInt32(MCDCTestVectorBitmapOffset),
1322 MCDCCondBitmapAddr.emitRawPointer(CGF)};
1324 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
1328 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1331 auto I = RegionMCDCState->DecisionByStmt.find(S->
IgnoreParens());
1332 if (I == RegionMCDCState->DecisionByStmt.end())
1335 auto &MCDCCondBitmapAddr = I->second.MCDCCondBitmapAddr;
1336 if (!MCDCCondBitmapAddr.isValid())
1340 Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr);
1346 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1358 auto BranchStateIter = RegionMCDCState->BranchByStmt.find(S);
1359 if (BranchStateIter == RegionMCDCState->BranchByStmt.end())
1363 const auto &Branch = BranchStateIter->second;
1364 assert(Branch.ID >= 0 &&
"Condition has no ID!");
1365 assert(Branch.DecisionStmt);
1368 const auto DecisionIter =
1369 RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
1370 if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
1373 auto &MCDCCondBitmapAddr = DecisionIter->second.MCDCCondBitmapAddr;
1374 if (!MCDCCondBitmapAddr.isValid())
1377 const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
1379 auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
1380 "mcdc." + Twine(Branch.ID + 1) +
".cur");
1381 auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
true]));
1382 NewTV = Builder.CreateSelect(
1383 Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
false])));
1384 Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
1388 if (CGM.getCodeGenOpts().hasProfileClangInstr())
1389 M.addModuleFlag(llvm::Module::Warning,
"EnableValueProfiling",
1394 if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
1396 const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1397 llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
1398 uint64_t ProfileVersion =
1399 (INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);
1401 auto IRLevelVersionVariable =
new llvm::GlobalVariable(
1402 M, IntTy64,
true, llvm::GlobalValue::WeakAnyLinkage,
1403 llvm::Constant::getIntegerValue(IntTy64,
1404 llvm::APInt(64, ProfileVersion)),
1407 IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1408 llvm::Triple TT(M.getTargetTriple());
1410 IRLevelVersionVariable->setVisibility(
1411 llvm::GlobalValue::ProtectedVisibility);
1412 if (TT.supportsCOMDAT()) {
1413 IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
1414 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
1416 IRLevelVersionVariable->setDSOLocal(
true);
1423 llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
1428 if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
1434 bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
1435 if (InstrumentValueSites && RegionCounterMap) {
1436 auto BuilderInsertPoint = Builder.saveIP();
1437 Builder.SetInsertPoint(ValueSite);
1438 llvm::Value *Args[5] = {
1440 Builder.getInt64(FunctionHash),
1441 Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1442 Builder.getInt32(ValueKind),
1443 Builder.getInt32(NumValueSites[ValueKind]++)
1446 CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1447 Builder.restoreIP(BuilderInsertPoint);
1451 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1459 if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1462 llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
1463 (llvm::InstrProfValueKind)ValueKind,
1464 NumValueSites[ValueKind]);
1466 NumValueSites[ValueKind]++;
1470void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
1471 bool IsInMainFile) {
1473 RegionCounts.clear();
1474 auto RecordExpected = PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1475 if (
auto E = RecordExpected.takeError()) {
1476 auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(E)));
1477 if (IPE == llvm::instrprof_error::unknown_function)
1479 else if (IPE == llvm::instrprof_error::hash_mismatch)
1481 else if (IPE == llvm::instrprof_error::malformed)
1487 std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1488 RegionCounts = ProfRecord->Counts;
1496 return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
1509 assert(Scale &&
"scale by 0?");
1510 uint64_t Scaled = Weight / Scale + 1;
1511 assert(Scaled <= UINT32_MAX &&
"overflow 32-bits");
1515llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1516 uint64_t FalseCount)
const {
1518 if (!TrueCount && !FalseCount)
1524 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
1530CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights)
const {
1532 if (Weights.size() < 2)
1536 uint64_t MaxWeight = *llvm::max_element(Weights);
1543 SmallVector<uint32_t, 16> ScaledWeights;
1544 ScaledWeights.reserve(Weights.size());
1545 for (uint64_t W : Weights)
1548 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
1549 return MDHelper.createBranchWeights(ScaledWeights);
1553CodeGenFunction::createProfileWeightsForLoop(
const Stmt *
Cond,
1554 uint64_t LoopCount)
const {
1555 if (!PGO->haveRegionCounts())
1557 std::optional<uint64_t> CondCount = PGO->getStmtCount(
Cond);
1558 if (!CondCount || *CondCount == 0)
1560 return createProfileWeights(LoopCount,
1561 std::max(*CondCount, LoopCount) - LoopCount);
1565 const Stmt *S,
bool UseBoth,
1566 llvm::Value *StepV) {
1567 if (
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1568 !
CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
1569 !
CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) {
1574 PGO->setCurrentStmt(S);
1578 return PGO->getIsCounterPair(S);
1581 PGO->markStmtAsUsed(Skipped, S);
1584 PGO->markStmtMaybeUsed(S);
1589 PGO->emitMCDCParameters(
Builder);
1593 for (
auto *MCDCCondBitmapAddr : PGO->getMCDCCondBitmapAddrArray(
Builder))
1594 *MCDCCondBitmapAddr =
1599 return PGO->isMCDCDecisionExpr(E);
1602 return PGO->isMCDCBranchExpr(E);
1606 PGO->emitMCDCCondBitmapReset(
Builder, E);
1607 PGO->setCurrentStmt(E);
1612 PGO->emitMCDCTestVectorBitmapUpdate(
Builder, E, *
this);
1613 PGO->setCurrentStmt(E);
1620 PGO->emitMCDCCondBitmapUpdate(
Builder, E, Val, *
this);
1621 PGO->setCurrentStmt(E);
1626 return PGO->getStmtCount(S).value_or(0);
1631 PGO->setCurrentRegionCount(Count);
1637 return PGO->getCurrentRegionCount();
llvm::ImmutableMap< CountKey, unsigned > CountMap
#define DEFINE_NESTABLE_TRAVERSAL(N)
static llvm::cl::opt< bool > EnableValueProfiling("enable-value-profiling", llvm::cl::desc("Enable value profiling"), llvm::cl::Hidden, llvm::cl::init(false))
PGOHashVersion
The version of the PGO hash algorithm.
static uint64_t calculateWeightScale(uint64_t MaxWeight)
Calculate what to divide by to scale weights.
static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale)
Scale an individual branch weight (and add 1).
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
SourceManager & getSourceManager()
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isLogicalOp(Opcode Opc)
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
CXXCatchStmt - This represents a C++ catch block.
Stmt * getHandlerBlock() const
DeclStmt * getBeginStmt()
DeclStmt * getLoopVarStmt()
DeclStmt * getRangeStmt()
const Expr * getSubExpr() const
CXXTryStmt - A C++ try block, including all handlers.
CXXCatchStmt * getHandler(unsigned i)
unsigned getNumHandlers() const
CompoundStmt * getTryBlock()
Represents the body of a CapturedStmt, and serves as its DeclContext.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
bool hasProfileClangInstr() const
Check if Clang profile instrumenation is on.
std::string MainFileName
The user provided name for the "main file", if non-empty.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void setCurrentProfileCount(uint64_t Count)
Set the profiler's current count.
bool isBinaryLogicalOp(const Expr *E) const
CounterForIncrement
Used to specify which counter in a pair shall be incremented.
@ UseSkipPath
Skip (false)
RawAddress CreateIRTemp(QualType T, const Twine &Name="tmp")
CreateIRTemp - Create a temporary IR object of the given type, with appropriate alignment.
void maybeUpdateMCDCTestVectorBitmap(const Expr *E)
Increment the profiler's counter for the given expression by StepV.
static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor)
Checks whether the given constructor is a valid subject for the complete-to-base constructor delegati...
void maybeCreateMCDCCondBitmap()
Allocate a temp value on the stack that MCDC can use to track condition results.
static bool isInstrumentedCondition(const Expr *C)
isInstrumentedCondition - Determine whether the given condition is an instrumentable condition (i....
void maybeResetMCDCCondBitmap(const Expr *E)
Zero-init the MCDC temp value.
bool isMCDCCoverageEnabled() const
void maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val)
Update the MCDC temp value with the condition's evaluated result.
ASTContext & getContext() const
bool isMCDCBranchExpr(const Expr *E) const
static const Expr * stripCond(const Expr *C)
Ignore parentheses and logical-NOT to track conditions consistently.
uint64_t getCurrentProfileCount()
Get the profiler's current count.
void markStmtMaybeUsed(const Stmt *S)
std::pair< bool, bool > getIsCounterPair(const Stmt *S) const
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
void markStmtAsUsed(bool Skipped, const Stmt *S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
bool isMCDCDecisionExpr(const Expr *E) const
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
llvm::IndexedInstrProfReader * getPGOReader() const
InstrProfStats & getPGOStats()
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
std::pair< bool, bool > getIsCounterPair(const Stmt *S) const
uint64_t getRegionCount(const Stmt *S)
Return the region count for the counter at the given index.
void setValueProfilingFlag(llvm::Module &M)
void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, llvm::Instruction *ValueSite, llvm::Value *ValuePtr)
void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, llvm::Value *Val, CodeGenFunction &CGF)
void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S)
std::vector< Address * > getMCDCCondBitmapAddrArray(CGBuilderTy &Builder)
Fill mcdc.addr order by ID.
void setProfileVersion(llvm::Module &M)
void emitEmptyCounterMapping(const Decl *D, StringRef FuncName, llvm::GlobalValue::LinkageTypes Linkage)
Emit a coverage mapping range with a counter zero for an unused declaration.
void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, bool UseFalsePath, bool UseBoth, llvm::Value *StepV)
void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, CodeGenFunction &CGF)
void emitMCDCParameters(CGBuilderTy &Builder)
bool haveRegionCounts() const
Whether or not we have PGO region data for the current function.
Organizes the per-function state that is used while generating code coverage mapping data.
void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS)
Emit the coverage mapping data for an unused function.
void addMissing(bool MainFile)
Record that a function we've visited has no profile data.
void addMismatched(bool MainFile)
Record that a function we've visited has mismatched profile data.
void addVisited(bool MainFile)
Record that we've visited a function and whether or not that function was in the main source file.
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
bool isNegatedConsteval() const
Represents Objective-C's collection statement.
ObjCMethodDecl - Represents an instance or class method declaration.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceLocation getBeginLoc() const LLVM_READONLY
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ Ctor_Base
Base object ctor.
bool isa(CodeGen::Address addr)
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ Result
The result type of a method or function.
@ Dtor_Base
Base object dtor.
@ Type
The name was classified as a type.
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
U cast(CodeGen::Address addr)
@ None
The alignment was not explicit in code.
cl::opt< bool > SystemHeadersCoverage
Diagnostic wrappers for TextAPI types for error reporting.
cl::opt< bool > EnableSingleByteCoverage
Per-Function MC/DC state.
llvm::DenseMap< const Stmt *, Decision > DecisionByStmt