18#include "llvm/IR/Intrinsics.h"
19#include "llvm/IR/MDBuilder.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/Endian.h"
22#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/MD5.h"
30static llvm::cl::opt<bool>
32 llvm::cl::desc(
"Enable value profiling"),
33 llvm::cl::Hidden, llvm::cl::init(
false));
36using namespace CodeGen;
38void CodeGenPGO::setFuncName(StringRef Name,
39 llvm::GlobalValue::LinkageTypes
Linkage) {
40 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
41 FuncName = llvm::getPGOFuncName(
43 PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
47 FuncNameVar = llvm::createPGOFuncNameVar(CGM.
getModule(),
Linkage, FuncName);
50void CodeGenPGO::setFuncName(llvm::Function *Fn) {
51 setFuncName(
Fn->getName(),
Fn->getLinkage());
53 llvm::createPGOFuncNameMetadata(*Fn, FuncName);
83 static const int NumBitsPerType = 6;
84 static const unsigned NumTypesPerWord =
sizeof(
uint64_t) * 8 / NumBitsPerType;
85 static const unsigned TooBig = 1u << NumBitsPerType;
95 enum HashType :
unsigned char {
136 static_assert(LastHashType <= TooBig,
"Too many types in HashType");
139 : Working(0), Count(0), HashVersion(HashVersion) {}
140 void combine(HashType
Type);
144const int PGOHash::NumBitsPerType;
145const unsigned PGOHash::NumTypesPerWord;
146const unsigned PGOHash::TooBig;
149static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
151 if (PGOReader->getVersion() <= 4)
153 if (PGOReader->getVersion() <= 5)
163 unsigned NextCounter;
167 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
171 unsigned MCDCMaxCond;
177 MapRegionCounters(
PGOHashVersion HashVersion, uint64_t ProfileVersion,
178 llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
181 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
182 MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
183 ProfileVersion(ProfileVersion),
Diag(
Diag) {}
187 bool TraverseBlockExpr(
BlockExpr *BE) {
return true; }
190 for (
auto C : zip(
LE->captures(),
LE->capture_inits()))
191 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
194 bool TraverseCapturedStmt(
CapturedStmt *CS) {
return true; }
196 bool VisitDecl(
const Decl *
D) {
201 case Decl::CXXMethod:
202 case Decl::CXXConstructor:
203 case Decl::CXXDestructor:
204 case Decl::CXXConversion:
205 case Decl::ObjCMethod:
208 CounterMap[
D->
getBody()] = NextCounter++;
216 PGOHash::HashType updateCounterMappings(
Stmt *S) {
218 if (
Type != PGOHash::None)
219 CounterMap[S] = NextCounter++;
232 unsigned NumCond = 0;
233 bool SplitNestedLogicalOp =
false;
238 bool dataTraverseStmtPre(
Stmt *S) {
240 if (MCDCMaxCond == 0)
245 if (LogOpStack.empty()) {
247 SplitNestedLogicalOp =
false;
250 if (
const Expr *
E = dyn_cast<Expr>(S)) {
260 SplitNestedLogicalOp = SplitNestedLogicalOp || !NonLogOpStack.empty();
262 LogOpStack.push_back(BinOp);
269 if (!LogOpStack.empty())
270 NonLogOpStack.push_back(S);
278 bool dataTraverseStmtPost(
Stmt *S) {
280 if (MCDCMaxCond == 0)
283 if (
const Expr *
E = dyn_cast<Expr>(S)) {
286 assert(LogOpStack.back() == BinOp);
287 LogOpStack.pop_back();
290 if (LogOpStack.empty()) {
292 if (SplitNestedLogicalOp) {
293 unsigned DiagID =
Diag.getCustomDiagID(
295 "unsupported MC/DC boolean expression; "
296 "contains an operation with a nested boolean expression. "
297 "Expression will not be covered");
298 Diag.Report(S->getBeginLoc(), DiagID);
303 if (NumCond > MCDCMaxCond) {
304 unsigned DiagID =
Diag.getCustomDiagID(
306 "unsupported MC/DC boolean expression; "
307 "number of conditions (%0) exceeds max (%1). "
308 "Expression will not be covered");
309 Diag.Report(S->getBeginLoc(), DiagID) << NumCond << MCDCMaxCond;
320 if (!LogOpStack.empty())
321 NonLogOpStack.pop_back();
332 if (S->isLogicalOp()) {
333 if (CodeGenFunction::isInstrumentedCondition(S->getLHS()))
336 if (CodeGenFunction::isInstrumentedCondition(S->getRHS())) {
337 if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
338 CounterMap[S->getRHS()] = NextCounter++;
343 return Base::VisitBinaryOperator(S);
348 CounterMap[S->getTrueExpr()] = NextCounter++;
350 CounterMap[S->getFalseExpr()] = NextCounter++;
351 return Base::VisitConditionalOperator(S);
355 bool VisitStmt(
Stmt *S) {
356 auto Type = updateCounterMappings(S);
358 Type = getHashType(Hash.getHashVersion(), S);
359 if (
Type != PGOHash::None)
367 return Base::TraverseIfStmt(
If);
372 for (
Stmt *CS :
If->children()) {
373 if (!CS || NoSingleByteCoverage)
375 if (CS ==
If->getThen())
376 CounterMap[
If->getThen()] = NextCounter++;
377 else if (CS ==
If->getElse())
378 CounterMap[
If->getElse()] = NextCounter++;
384 for (
Stmt *CS :
If->children()) {
387 if (CS ==
If->getThen())
388 Hash.combine(PGOHash::IfThenBranch);
389 else if (CS ==
If->getElse())
390 Hash.combine(PGOHash::IfElseBranch);
393 Hash.combine(PGOHash::EndOfScope);
397 bool TraverseWhileStmt(
WhileStmt *While) {
402 if (!CS || NoSingleByteCoverage)
405 CounterMap[While->
getCond()] = NextCounter++;
406 else if (CS == While->
getBody())
407 CounterMap[While->
getBody()] = NextCounter++;
410 Base::TraverseWhileStmt(While);
412 Hash.combine(PGOHash::EndOfScope);
416 bool TraverseDoStmt(
DoStmt *Do) {
421 if (!CS || NoSingleByteCoverage)
424 CounterMap[Do->
getCond()] = NextCounter++;
426 CounterMap[Do->
getBody()] = NextCounter++;
429 Base::TraverseDoStmt(Do);
431 Hash.combine(PGOHash::EndOfScope);
435 bool TraverseForStmt(
ForStmt *For) {
440 if (!CS || NoSingleByteCoverage)
443 CounterMap[For->
getCond()] = NextCounter++;
444 else if (CS == For->
getInc())
445 CounterMap[For->
getInc()] = NextCounter++;
447 CounterMap[For->
getBody()] = NextCounter++;
450 Base::TraverseForStmt(For);
452 Hash.combine(PGOHash::EndOfScope);
460 if (!CS || NoSingleByteCoverage)
463 CounterMap[ForRange->
getBody()] = NextCounter++;
466 Base::TraverseCXXForRangeStmt(ForRange);
468 Hash.combine(PGOHash::EndOfScope);
475#define DEFINE_NESTABLE_TRAVERSAL(N) \
476 bool Traverse##N(N *S) { \
477 Base::Traverse##N(S); \
478 if (Hash.getHashVersion() != PGO_HASH_V1) \
479 Hash.combine(PGOHash::EndOfScope); \
489 switch (S->getStmtClass()) {
492 case Stmt::LabelStmtClass:
493 return PGOHash::LabelStmt;
494 case Stmt::WhileStmtClass:
495 return PGOHash::WhileStmt;
496 case Stmt::DoStmtClass:
497 return PGOHash::DoStmt;
498 case Stmt::ForStmtClass:
499 return PGOHash::ForStmt;
500 case Stmt::CXXForRangeStmtClass:
501 return PGOHash::CXXForRangeStmt;
502 case Stmt::ObjCForCollectionStmtClass:
503 return PGOHash::ObjCForCollectionStmt;
504 case Stmt::SwitchStmtClass:
505 return PGOHash::SwitchStmt;
506 case Stmt::CaseStmtClass:
507 return PGOHash::CaseStmt;
508 case Stmt::DefaultStmtClass:
509 return PGOHash::DefaultStmt;
510 case Stmt::IfStmtClass:
511 return PGOHash::IfStmt;
512 case Stmt::CXXTryStmtClass:
513 return PGOHash::CXXTryStmt;
514 case Stmt::CXXCatchStmtClass:
515 return PGOHash::CXXCatchStmt;
516 case Stmt::ConditionalOperatorClass:
517 return PGOHash::ConditionalOperator;
518 case Stmt::BinaryConditionalOperatorClass:
519 return PGOHash::BinaryConditionalOperator;
520 case Stmt::BinaryOperatorClass: {
523 return PGOHash::BinaryOperatorLAnd;
525 return PGOHash::BinaryOperatorLOr;
531 return PGOHash::BinaryOperatorLT;
533 return PGOHash::BinaryOperatorGT;
535 return PGOHash::BinaryOperatorLE;
537 return PGOHash::BinaryOperatorGE;
539 return PGOHash::BinaryOperatorEQ;
541 return PGOHash::BinaryOperatorNE;
549 switch (S->getStmtClass()) {
552 case Stmt::GotoStmtClass:
553 return PGOHash::GotoStmt;
554 case Stmt::IndirectGotoStmtClass:
555 return PGOHash::IndirectGotoStmt;
556 case Stmt::BreakStmtClass:
557 return PGOHash::BreakStmt;
558 case Stmt::ContinueStmtClass:
559 return PGOHash::ContinueStmt;
560 case Stmt::ReturnStmtClass:
561 return PGOHash::ReturnStmt;
562 case Stmt::CXXThrowExprClass:
563 return PGOHash::ThrowExpr;
564 case Stmt::UnaryOperatorClass: {
567 return PGOHash::UnaryOperatorLNot;
573 return PGOHash::None;
585 bool RecordNextStmtCount;
591 llvm::DenseMap<const Stmt *, uint64_t> &
CountMap;
594 struct BreakContinue {
597 BreakContinue() =
default;
601 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &
CountMap,
605 void RecordStmtCount(
const Stmt *S) {
606 if (RecordNextStmtCount) {
608 RecordNextStmtCount =
false;
614 CurrentCount = Count;
618 void VisitStmt(
const Stmt *S) {
620 for (
const Stmt *Child : S->children())
660 if (S->getRetValue())
661 Visit(S->getRetValue());
663 RecordNextStmtCount =
true;
669 Visit(
E->getSubExpr());
671 RecordNextStmtCount =
true;
674 void VisitGotoStmt(
const GotoStmt *S) {
677 RecordNextStmtCount =
true;
680 void VisitLabelStmt(
const LabelStmt *S) {
681 RecordNextStmtCount =
false;
685 Visit(S->getSubStmt());
688 void VisitBreakStmt(
const BreakStmt *S) {
690 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
691 BreakContinueStack.back().BreakCount += CurrentCount;
693 RecordNextStmtCount =
true;
698 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
699 BreakContinueStack.back().ContinueCount += CurrentCount;
701 RecordNextStmtCount =
true;
704 void VisitWhileStmt(
const WhileStmt *S) {
706 uint64_t ParentCount = CurrentCount;
708 BreakContinueStack.push_back(BreakContinue());
712 CountMap[S->getBody()] = CurrentCount;
714 uint64_t BackedgeCount = CurrentCount;
720 BreakContinue BC = BreakContinueStack.pop_back_val();
722 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
725 setCount(BC.BreakCount + CondCount - BodyCount);
726 RecordNextStmtCount =
true;
729 void VisitDoStmt(
const DoStmt *S) {
733 BreakContinueStack.push_back(BreakContinue());
735 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
738 uint64_t BackedgeCount = CurrentCount;
740 BreakContinue BC = BreakContinueStack.pop_back_val();
743 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
746 setCount(BC.BreakCount + CondCount - LoopCount);
747 RecordNextStmtCount =
true;
750 void VisitForStmt(
const ForStmt *S) {
755 uint64_t ParentCount = CurrentCount;
757 BreakContinueStack.push_back(BreakContinue());
763 uint64_t BackedgeCount = CurrentCount;
764 BreakContinue BC = BreakContinueStack.pop_back_val();
769 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
776 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
781 setCount(BC.BreakCount + CondCount - BodyCount);
782 RecordNextStmtCount =
true;
789 Visit(S->getLoopVarStmt());
790 Visit(S->getRangeStmt());
791 Visit(S->getBeginStmt());
792 Visit(S->getEndStmt());
794 uint64_t ParentCount = CurrentCount;
795 BreakContinueStack.push_back(BreakContinue());
801 uint64_t BackedgeCount = CurrentCount;
802 BreakContinue BC = BreakContinueStack.pop_back_val();
806 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
812 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
815 setCount(BC.BreakCount + CondCount - BodyCount);
816 RecordNextStmtCount =
true;
821 Visit(S->getElement());
822 uint64_t ParentCount = CurrentCount;
823 BreakContinueStack.push_back(BreakContinue());
828 uint64_t BackedgeCount = CurrentCount;
829 BreakContinue BC = BreakContinueStack.pop_back_val();
831 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
833 RecordNextStmtCount =
true;
842 BreakContinueStack.push_back(BreakContinue());
845 BreakContinue BC = BreakContinueStack.pop_back_val();
846 if (!BreakContinueStack.empty())
847 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
850 RecordNextStmtCount =
true;
854 RecordNextStmtCount =
false;
859 setCount(CurrentCount + CaseCount);
863 RecordNextStmtCount =
true;
864 Visit(S->getSubStmt());
867 void VisitIfStmt(
const IfStmt *S) {
870 if (S->isConsteval()) {
871 const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse();
877 uint64_t ParentCount = CurrentCount;
889 uint64_t ElseCount = ParentCount - ThenCount;
894 OutCount += CurrentCount;
896 OutCount += ElseCount;
898 RecordNextStmtCount =
true;
903 Visit(S->getTryBlock());
904 for (
unsigned I = 0,
E = S->getNumHandlers(); I <
E; ++I)
905 Visit(S->getHandler(I));
908 RecordNextStmtCount =
true;
912 RecordNextStmtCount =
false;
916 Visit(S->getHandlerBlock());
921 uint64_t ParentCount = CurrentCount;
928 Visit(
E->getTrueExpr());
931 uint64_t FalseCount = setCount(ParentCount - TrueCount);
932 CountMap[
E->getFalseExpr()] = FalseCount;
933 Visit(
E->getFalseExpr());
934 OutCount += CurrentCount;
937 RecordNextStmtCount =
true;
942 uint64_t ParentCount = CurrentCount;
948 setCount(ParentCount + RHSCount - CurrentCount);
949 RecordNextStmtCount =
true;
954 uint64_t ParentCount = CurrentCount;
960 setCount(ParentCount + RHSCount - CurrentCount);
961 RecordNextStmtCount =
true;
966void PGOHash::combine(HashType
Type) {
968 assert(
Type &&
"Hash is invalid: unexpected type 0");
969 assert(
unsigned(
Type) < TooBig &&
"Hash is invalid: too many types");
972 if (Count && Count % NumTypesPerWord == 0) {
973 using namespace llvm::support;
975 endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
982 Working = Working << NumBitsPerType |
Type;
987 if (Count <= NumTypesPerWord)
998 MD5.update({(uint8_t)Working});
1000 using namespace llvm::support;
1002 endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
1003 MD5.update(
llvm::ArrayRef((uint8_t *)&Swapped,
sizeof(Swapped)));
1008 llvm::MD5::MD5Result
Result;
1024 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
1025 if (!InstrumentRegions && !PGOReader)
1033 if (
const auto *CCD = dyn_cast<CXXConstructorDecl>(
D))
1042 if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
1044 if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
1054 mapRegionCounters(
D);
1056 emitCounterRegionMapping(
D);
1059 computeRegionCounts(
D);
1060 applyFunctionAttributes(PGOReader, Fn);
1064void CodeGenPGO::mapRegionCounters(
const Decl *
D) {
1068 uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
1070 HashVersion = getPGOHashVersion(PGOReader, CGM);
1071 ProfileVersion = PGOReader->getVersion();
1083 unsigned MCDCMaxConditions =
1087 RegionCounterMap.reset(
new llvm::DenseMap<const Stmt *, unsigned>);
1089 MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
1090 *RegionMCDCState, MCDCMaxConditions, CGM.
getDiags());
1091 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(
D))
1093 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(
D))
1095 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(
D))
1096 Walker.TraverseDecl(
const_cast<BlockDecl *
>(BD));
1097 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(
D))
1099 assert(Walker.NextCounter > 0 &&
"no entry counter mapped for decl");
1100 NumRegionCounters = Walker.NextCounter;
1101 FunctionHash = Walker.Hash.finalize();
1104bool CodeGenPGO::skipRegionMappingForDecl(
const Decl *
D) {
1126void CodeGenPGO::emitCounterRegionMapping(
const Decl *
D) {
1127 if (skipRegionMappingForDecl(
D))
1130 std::string CoverageMapping;
1131 llvm::raw_string_ostream OS(CoverageMapping);
1132 RegionMCDCState->BranchByStmt.clear();
1135 CGM.
getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1136 MappingGen.emitCounterMapping(
D, OS);
1139 if (CoverageMapping.empty())
1143 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1148 llvm::GlobalValue::LinkageTypes
Linkage) {
1149 if (skipRegionMappingForDecl(
D))
1152 std::string CoverageMapping;
1153 llvm::raw_string_ostream OS(CoverageMapping);
1160 if (CoverageMapping.empty())
1165 FuncNameVar, FuncName, FunctionHash, CoverageMapping,
false);
1168void CodeGenPGO::computeRegionCounts(
const Decl *
D) {
1169 StmtCountMap.reset(
new llvm::DenseMap<const Stmt *, uint64_t>);
1170 ComputeRegionCounts Walker(*StmtCountMap, *
this);
1171 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(
D))
1172 Walker.VisitFunctionDecl(FD);
1173 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(
D))
1174 Walker.VisitObjCMethodDecl(MD);
1175 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(
D))
1176 Walker.VisitBlockDecl(BD);
1177 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(
D))
1178 Walker.VisitCapturedDecl(
const_cast<CapturedDecl *
>(CD));
1182CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1183 llvm::Function *Fn) {
1188 Fn->setEntryCount(FunctionCount);
1192 llvm::Value *StepV) {
1193 if (!RegionCounterMap || !Builder.GetInsertBlock())
1196 unsigned Counter = (*RegionCounterMap)[S];
1198 llvm::Value *Args[] = {FuncNameVar,
1199 Builder.getInt64(FunctionHash),
1200 Builder.getInt32(NumRegionCounters),
1201 Builder.getInt32(Counter), StepV};
1204 Builder.CreateCall(CGM.
getIntrinsic(llvm::Intrinsic::instrprof_cover),
1208 Builder.CreateCall(CGM.
getIntrinsic(llvm::Intrinsic::instrprof_increment),
1212 CGM.
getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
1216bool CodeGenPGO::canEmitMCDCCoverage(
const CGBuilderTy &Builder) {
1222 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1225 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.
getLLVMContext());
1230 llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1231 Builder.getInt64(FunctionHash),
1232 Builder.getInt32(RegionMCDCState->BitmapBits)};
1234 CGM.
getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
1241 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1244 S = S->IgnoreParens();
1246 auto DecisionStateIter = RegionMCDCState->DecisionByStmt.find(S);
1247 if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
1252 if (DecisionStateIter->second.Indices.size() == 0)
1256 unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
1257 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.
getLLVMContext());
1264 llvm::Value *Args[4] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1265 Builder.getInt64(FunctionHash),
1266 Builder.getInt32(MCDCTestVectorBitmapOffset),
1269 CGM.
getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
1274 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1277 S = S->IgnoreParens();
1279 if (!RegionMCDCState->DecisionByStmt.contains(S))
1283 Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr);
1290 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1302 auto BranchStateIter = RegionMCDCState->BranchByStmt.find(S);
1303 if (BranchStateIter == RegionMCDCState->BranchByStmt.end())
1307 const auto &Branch = BranchStateIter->second;
1308 assert(Branch.ID >= 0 &&
"Condition has no ID!");
1309 assert(Branch.DecisionStmt);
1312 const auto DecisionIter =
1313 RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
1314 if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
1317 const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
1319 auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
1320 "mcdc." + Twine(Branch.ID + 1) +
".cur");
1321 auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
true]));
1322 NewTV = Builder.CreateSelect(
1323 Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
false])));
1324 Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
1329 M.addModuleFlag(llvm::Module::Warning,
"EnableValueProfiling",
1336 const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1337 llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
1338 uint64_t ProfileVersion =
1339 (INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);
1341 auto IRLevelVersionVariable =
new llvm::GlobalVariable(
1342 M, IntTy64,
true, llvm::GlobalValue::WeakAnyLinkage,
1343 llvm::Constant::getIntegerValue(IntTy64,
1344 llvm::APInt(64, ProfileVersion)),
1347 IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1348 llvm::Triple TT(M.getTargetTriple());
1349 if (TT.supportsCOMDAT()) {
1350 IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
1351 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
1353 IRLevelVersionVariable->setDSOLocal(
true);
1360 llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
1365 if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
1368 if (isa<llvm::Constant>(ValuePtr))
1372 if (InstrumentValueSites && RegionCounterMap) {
1373 auto BuilderInsertPoint = Builder.saveIP();
1374 Builder.SetInsertPoint(ValueSite);
1375 llvm::Value *Args[5] = {
1377 Builder.getInt64(FunctionHash),
1378 Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1379 Builder.getInt32(ValueKind),
1380 Builder.getInt32(NumValueSites[ValueKind]++)
1383 CGM.
getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1384 Builder.restoreIP(BuilderInsertPoint);
1388 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
1396 if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1399 llvm::annotateValueSite(CGM.
getModule(), *ValueSite, *ProfRecord,
1400 (llvm::InstrProfValueKind)ValueKind,
1401 NumValueSites[ValueKind]);
1403 NumValueSites[ValueKind]++;
1407void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
1408 bool IsInMainFile) {
1410 RegionCounts.clear();
1412 PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1413 if (
auto E = RecordExpected.takeError()) {
1414 auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(
E)));
1415 if (IPE == llvm::instrprof_error::unknown_function)
1417 else if (IPE == llvm::instrprof_error::hash_mismatch)
1419 else if (IPE == llvm::instrprof_error::malformed)
1425 std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1426 RegionCounts = ProfRecord->Counts;
1434 return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
1447 assert(Scale &&
"scale by 0?");
1448 uint64_t Scaled = Weight / Scale + 1;
1449 assert(Scaled <= UINT32_MAX &&
"overflow 32-bits");
1453llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1454 uint64_t FalseCount)
const {
1456 if (!TrueCount && !FalseCount)
1470 if (Weights.size() < 2)
1474 uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
1482 ScaledWeights.reserve(Weights.size());
1483 for (uint64_t W : Weights)
1487 return MDHelper.createBranchWeights(ScaledWeights);
1491CodeGenFunction::createProfileWeightsForLoop(
const Stmt *Cond,
1492 uint64_t LoopCount)
const {
1495 std::optional<uint64_t> CondCount = PGO.
getStmtCount(Cond);
1496 if (!CondCount || *CondCount == 0)
1498 return createProfileWeights(LoopCount,
1499 std::max(*CondCount, LoopCount) - LoopCount);
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()
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
BinaryConditionalOperator - The GNU extension to the conditional operator which allows the middle ope...
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.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
BreakStmt - This represents a break.
CXXCatchStmt - This represents a C++ catch block.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
A C++ throw-expression (C++ [except.throw]).
CXXTryStmt - A C++ try block, including all handlers.
Represents the body of a CapturedStmt, and serves as its DeclContext.
This captures a statement into a function.
CaseStmt - Represent a case statement.
bool hasProfileClangInstr() const
Check if Clang profile instrumenation is on.
std::string MainFileName
The user provided name for the "main file", if non-empty.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
static const Expr * stripCond(const Expr *C)
Ignore parentheses and logical-NOT to track conditions consistently.
static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor)
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
const TargetInfo & getTarget() const
llvm::IndexedInstrProfReader * getPGOReader() const
CoverageMappingModuleGen * getCoverageMapping() const
InstrProfStats & getPGOStats()
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys=std::nullopt)
void ClearUnusedCoverageMapping(const Decl *D)
Remove the deferred empty coverage mapping as this declaration is actually instrumented.
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
std::optional< uint64_t > getStmtCount(const Stmt *S) const
Check if an execution count is known for a given statement.
void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, CodeGenFunction &CGF)
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, Address MCDCCondBitmapAddr, llvm::Value *Val, CodeGenFunction &CGF)
void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr)
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 emitMCDCParameters(CGBuilderTy &Builder)
bool haveRegionCounts() const
Whether or not we have PGO region data for the current function.
void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, llvm::Value *StepV)
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 addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue, uint64_t FunctionHash, const std::string &CoverageMapping, bool IsUsed=true)
Add a function's coverage mapping record to the collection of the function mapping records.
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.
ConditionalOperator - The ?: ternary operator.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
ContinueStmt - This represents a continue.
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
Concrete class used by the front-end to report problems and issues.
DoStmt - This represents a 'do/while' stmt.
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
GotoStmt - This represents a direct goto.
IfStmt - This represents an if/then/else.
IndirectGotoStmt - This represents an indirect goto.
LabelStmt - Represents a label, which has a substatement.
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Represents Objective-C's collection statement.
ObjCMethodDecl - Represents an instance or class method declaration.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
SourceLocation getBeginLoc() const LLVM_READONLY
SwitchStmt - This represents a 'switch' stmt.
bool hasConstructorVariants() const
Does this ABI have different entrypoints for complete-object and base-subobject constructors?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
The base class of the type hierarchy.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
WhileStmt - This represents a 'while' stmt.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Ctor_Base
Base object ctor.
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.
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
@ 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