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/MD5.h"
29static llvm::cl::opt<bool>
31 llvm::cl::desc(
"Enable value profiling"),
32 llvm::cl::Hidden, llvm::cl::init(
false));
35using namespace CodeGen;
37void CodeGenPGO::setFuncName(StringRef Name,
38 llvm::GlobalValue::LinkageTypes
Linkage) {
39 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
40 FuncName = llvm::getPGOFuncName(
42 PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
46 FuncNameVar = llvm::createPGOFuncNameVar(CGM.
getModule(),
Linkage, FuncName);
49void CodeGenPGO::setFuncName(llvm::Function *Fn) {
50 setFuncName(
Fn->getName(),
Fn->getLinkage());
52 llvm::createPGOFuncNameMetadata(*Fn, FuncName);
82 static const int NumBitsPerType = 6;
83 static const unsigned NumTypesPerWord =
sizeof(
uint64_t) * 8 / NumBitsPerType;
84 static const unsigned TooBig = 1u << NumBitsPerType;
94 enum HashType :
unsigned char {
135 static_assert(LastHashType <= TooBig,
"Too many types in HashType");
138 : Working(0), Count(0), HashVersion(HashVersion) {}
139 void combine(HashType
Type);
143const int PGOHash::NumBitsPerType;
144const unsigned PGOHash::NumTypesPerWord;
145const unsigned PGOHash::TooBig;
148static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
150 if (PGOReader->getVersion() <= 4)
152 if (PGOReader->getVersion() <= 5)
162 unsigned NextCounter;
166 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
170 unsigned MCDCMaxCond;
176 MapRegionCounters(
PGOHashVersion HashVersion, uint64_t ProfileVersion,
177 llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
180 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
181 MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
182 ProfileVersion(ProfileVersion),
Diag(
Diag) {}
186 bool TraverseBlockExpr(
BlockExpr *BE) {
return true; }
189 for (
auto C : zip(
LE->captures(),
LE->capture_inits()))
190 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
193 bool TraverseCapturedStmt(
CapturedStmt *CS) {
return true; }
195 bool VisitDecl(
const Decl *
D) {
200 case Decl::CXXMethod:
201 case Decl::CXXConstructor:
202 case Decl::CXXDestructor:
203 case Decl::CXXConversion:
204 case Decl::ObjCMethod:
207 CounterMap[
D->
getBody()] = NextCounter++;
215 PGOHash::HashType updateCounterMappings(
Stmt *S) {
217 if (
Type != PGOHash::None)
218 CounterMap[S] = NextCounter++;
231 unsigned NumCond = 0;
232 bool SplitNestedLogicalOp =
false;
237 bool dataTraverseStmtPre(
Stmt *S) {
239 if (MCDCMaxCond == 0)
244 if (LogOpStack.empty()) {
246 SplitNestedLogicalOp =
false;
249 if (
const Expr *
E = dyn_cast<Expr>(S)) {
259 SplitNestedLogicalOp = SplitNestedLogicalOp || !NonLogOpStack.empty();
261 LogOpStack.push_back(BinOp);
268 if (!LogOpStack.empty())
269 NonLogOpStack.push_back(S);
277 bool dataTraverseStmtPost(
Stmt *S) {
279 if (MCDCMaxCond == 0)
282 if (
const Expr *
E = dyn_cast<Expr>(S)) {
285 assert(LogOpStack.back() == BinOp);
286 LogOpStack.pop_back();
289 if (LogOpStack.empty()) {
291 if (SplitNestedLogicalOp) {
292 unsigned DiagID =
Diag.getCustomDiagID(
294 "unsupported MC/DC boolean expression; "
295 "contains an operation with a nested boolean expression. "
296 "Expression will not be covered");
297 Diag.Report(S->getBeginLoc(), DiagID);
302 if (NumCond > MCDCMaxCond) {
303 unsigned DiagID =
Diag.getCustomDiagID(
305 "unsupported MC/DC boolean expression; "
306 "number of conditions (%0) exceeds max (%1). "
307 "Expression will not be covered");
308 Diag.Report(S->getBeginLoc(), DiagID) << NumCond << MCDCMaxCond;
319 if (!LogOpStack.empty())
320 NonLogOpStack.pop_back();
331 if (S->isLogicalOp()) {
332 if (CodeGenFunction::isInstrumentedCondition(S->getLHS()))
335 if (CodeGenFunction::isInstrumentedCondition(S->getRHS())) {
336 if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
337 CounterMap[S->getRHS()] = NextCounter++;
342 return Base::VisitBinaryOperator(S);
347 CounterMap[S->getTrueExpr()] = NextCounter++;
349 CounterMap[S->getFalseExpr()] = NextCounter++;
350 return Base::VisitConditionalOperator(S);
354 bool VisitStmt(
Stmt *S) {
355 auto Type = updateCounterMappings(S);
357 Type = getHashType(Hash.getHashVersion(), S);
358 if (
Type != PGOHash::None)
366 return Base::TraverseIfStmt(
If);
371 for (
Stmt *CS :
If->children()) {
372 if (!CS || NoSingleByteCoverage)
374 if (CS ==
If->getThen())
375 CounterMap[
If->getThen()] = NextCounter++;
376 else if (CS ==
If->getElse())
377 CounterMap[
If->getElse()] = NextCounter++;
383 for (
Stmt *CS :
If->children()) {
386 if (CS ==
If->getThen())
387 Hash.combine(PGOHash::IfThenBranch);
388 else if (CS ==
If->getElse())
389 Hash.combine(PGOHash::IfElseBranch);
392 Hash.combine(PGOHash::EndOfScope);
396 bool TraverseWhileStmt(
WhileStmt *While) {
401 if (!CS || NoSingleByteCoverage)
404 CounterMap[While->
getCond()] = NextCounter++;
405 else if (CS == While->
getBody())
406 CounterMap[While->
getBody()] = NextCounter++;
409 Base::TraverseWhileStmt(While);
411 Hash.combine(PGOHash::EndOfScope);
415 bool TraverseDoStmt(
DoStmt *Do) {
420 if (!CS || NoSingleByteCoverage)
423 CounterMap[Do->
getCond()] = NextCounter++;
425 CounterMap[Do->
getBody()] = NextCounter++;
428 Base::TraverseDoStmt(Do);
430 Hash.combine(PGOHash::EndOfScope);
434 bool TraverseForStmt(
ForStmt *For) {
439 if (!CS || NoSingleByteCoverage)
442 CounterMap[For->
getCond()] = NextCounter++;
443 else if (CS == For->
getInc())
444 CounterMap[For->
getInc()] = NextCounter++;
446 CounterMap[For->
getBody()] = NextCounter++;
449 Base::TraverseForStmt(For);
451 Hash.combine(PGOHash::EndOfScope);
459 if (!CS || NoSingleByteCoverage)
462 CounterMap[ForRange->
getBody()] = NextCounter++;
465 Base::TraverseCXXForRangeStmt(ForRange);
467 Hash.combine(PGOHash::EndOfScope);
474#define DEFINE_NESTABLE_TRAVERSAL(N) \
475 bool Traverse##N(N *S) { \
476 Base::Traverse##N(S); \
477 if (Hash.getHashVersion() != PGO_HASH_V1) \
478 Hash.combine(PGOHash::EndOfScope); \
488 switch (S->getStmtClass()) {
491 case Stmt::LabelStmtClass:
492 return PGOHash::LabelStmt;
493 case Stmt::WhileStmtClass:
494 return PGOHash::WhileStmt;
495 case Stmt::DoStmtClass:
496 return PGOHash::DoStmt;
497 case Stmt::ForStmtClass:
498 return PGOHash::ForStmt;
499 case Stmt::CXXForRangeStmtClass:
500 return PGOHash::CXXForRangeStmt;
501 case Stmt::ObjCForCollectionStmtClass:
502 return PGOHash::ObjCForCollectionStmt;
503 case Stmt::SwitchStmtClass:
504 return PGOHash::SwitchStmt;
505 case Stmt::CaseStmtClass:
506 return PGOHash::CaseStmt;
507 case Stmt::DefaultStmtClass:
508 return PGOHash::DefaultStmt;
509 case Stmt::IfStmtClass:
510 return PGOHash::IfStmt;
511 case Stmt::CXXTryStmtClass:
512 return PGOHash::CXXTryStmt;
513 case Stmt::CXXCatchStmtClass:
514 return PGOHash::CXXCatchStmt;
515 case Stmt::ConditionalOperatorClass:
516 return PGOHash::ConditionalOperator;
517 case Stmt::BinaryConditionalOperatorClass:
518 return PGOHash::BinaryConditionalOperator;
519 case Stmt::BinaryOperatorClass: {
522 return PGOHash::BinaryOperatorLAnd;
524 return PGOHash::BinaryOperatorLOr;
530 return PGOHash::BinaryOperatorLT;
532 return PGOHash::BinaryOperatorGT;
534 return PGOHash::BinaryOperatorLE;
536 return PGOHash::BinaryOperatorGE;
538 return PGOHash::BinaryOperatorEQ;
540 return PGOHash::BinaryOperatorNE;
548 switch (S->getStmtClass()) {
551 case Stmt::GotoStmtClass:
552 return PGOHash::GotoStmt;
553 case Stmt::IndirectGotoStmtClass:
554 return PGOHash::IndirectGotoStmt;
555 case Stmt::BreakStmtClass:
556 return PGOHash::BreakStmt;
557 case Stmt::ContinueStmtClass:
558 return PGOHash::ContinueStmt;
559 case Stmt::ReturnStmtClass:
560 return PGOHash::ReturnStmt;
561 case Stmt::CXXThrowExprClass:
562 return PGOHash::ThrowExpr;
563 case Stmt::UnaryOperatorClass: {
566 return PGOHash::UnaryOperatorLNot;
572 return PGOHash::None;
584 bool RecordNextStmtCount;
590 llvm::DenseMap<const Stmt *, uint64_t> &
CountMap;
593 struct BreakContinue {
596 BreakContinue() =
default;
600 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &
CountMap,
604 void RecordStmtCount(
const Stmt *S) {
605 if (RecordNextStmtCount) {
607 RecordNextStmtCount =
false;
613 CurrentCount = Count;
617 void VisitStmt(
const Stmt *S) {
619 for (
const Stmt *Child : S->children())
659 if (S->getRetValue())
660 Visit(S->getRetValue());
662 RecordNextStmtCount =
true;
668 Visit(
E->getSubExpr());
670 RecordNextStmtCount =
true;
673 void VisitGotoStmt(
const GotoStmt *S) {
676 RecordNextStmtCount =
true;
679 void VisitLabelStmt(
const LabelStmt *S) {
680 RecordNextStmtCount =
false;
684 Visit(S->getSubStmt());
687 void VisitBreakStmt(
const BreakStmt *S) {
689 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
690 BreakContinueStack.back().BreakCount += CurrentCount;
692 RecordNextStmtCount =
true;
697 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
698 BreakContinueStack.back().ContinueCount += CurrentCount;
700 RecordNextStmtCount =
true;
703 void VisitWhileStmt(
const WhileStmt *S) {
705 uint64_t ParentCount = CurrentCount;
707 BreakContinueStack.push_back(BreakContinue());
711 CountMap[S->getBody()] = CurrentCount;
713 uint64_t BackedgeCount = CurrentCount;
719 BreakContinue BC = BreakContinueStack.pop_back_val();
721 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
724 setCount(BC.BreakCount + CondCount - BodyCount);
725 RecordNextStmtCount =
true;
728 void VisitDoStmt(
const DoStmt *S) {
732 BreakContinueStack.push_back(BreakContinue());
734 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
737 uint64_t BackedgeCount = CurrentCount;
739 BreakContinue BC = BreakContinueStack.pop_back_val();
742 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
745 setCount(BC.BreakCount + CondCount - LoopCount);
746 RecordNextStmtCount =
true;
749 void VisitForStmt(
const ForStmt *S) {
754 uint64_t ParentCount = CurrentCount;
756 BreakContinueStack.push_back(BreakContinue());
762 uint64_t BackedgeCount = CurrentCount;
763 BreakContinue BC = BreakContinueStack.pop_back_val();
768 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
775 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
780 setCount(BC.BreakCount + CondCount - BodyCount);
781 RecordNextStmtCount =
true;
788 Visit(S->getLoopVarStmt());
789 Visit(S->getRangeStmt());
790 Visit(S->getBeginStmt());
791 Visit(S->getEndStmt());
793 uint64_t ParentCount = CurrentCount;
794 BreakContinueStack.push_back(BreakContinue());
800 uint64_t BackedgeCount = CurrentCount;
801 BreakContinue BC = BreakContinueStack.pop_back_val();
805 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
811 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
814 setCount(BC.BreakCount + CondCount - BodyCount);
815 RecordNextStmtCount =
true;
820 Visit(S->getElement());
821 uint64_t ParentCount = CurrentCount;
822 BreakContinueStack.push_back(BreakContinue());
827 uint64_t BackedgeCount = CurrentCount;
828 BreakContinue BC = BreakContinueStack.pop_back_val();
830 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
832 RecordNextStmtCount =
true;
841 BreakContinueStack.push_back(BreakContinue());
844 BreakContinue BC = BreakContinueStack.pop_back_val();
845 if (!BreakContinueStack.empty())
846 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
849 RecordNextStmtCount =
true;
853 RecordNextStmtCount =
false;
858 setCount(CurrentCount + CaseCount);
862 RecordNextStmtCount =
true;
863 Visit(S->getSubStmt());
866 void VisitIfStmt(
const IfStmt *S) {
869 if (S->isConsteval()) {
870 const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse();
876 uint64_t ParentCount = CurrentCount;
888 uint64_t ElseCount = ParentCount - ThenCount;
893 OutCount += CurrentCount;
895 OutCount += ElseCount;
897 RecordNextStmtCount =
true;
902 Visit(S->getTryBlock());
903 for (
unsigned I = 0,
E = S->getNumHandlers(); I <
E; ++I)
904 Visit(S->getHandler(I));
907 RecordNextStmtCount =
true;
911 RecordNextStmtCount =
false;
915 Visit(S->getHandlerBlock());
920 uint64_t ParentCount = CurrentCount;
927 Visit(
E->getTrueExpr());
930 uint64_t FalseCount = setCount(ParentCount - TrueCount);
931 CountMap[
E->getFalseExpr()] = FalseCount;
932 Visit(
E->getFalseExpr());
933 OutCount += CurrentCount;
936 RecordNextStmtCount =
true;
941 uint64_t ParentCount = CurrentCount;
947 setCount(ParentCount + RHSCount - CurrentCount);
948 RecordNextStmtCount =
true;
953 uint64_t ParentCount = CurrentCount;
959 setCount(ParentCount + RHSCount - CurrentCount);
960 RecordNextStmtCount =
true;
965void PGOHash::combine(HashType
Type) {
967 assert(
Type &&
"Hash is invalid: unexpected type 0");
968 assert(
unsigned(
Type) < TooBig &&
"Hash is invalid: too many types");
971 if (Count && Count % NumTypesPerWord == 0) {
972 using namespace llvm::support;
974 endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
981 Working = Working << NumBitsPerType |
Type;
986 if (Count <= NumTypesPerWord)
997 MD5.update({(uint8_t)Working});
999 using namespace llvm::support;
1001 endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
1002 MD5.update(
llvm::ArrayRef((uint8_t *)&Swapped,
sizeof(Swapped)));
1007 llvm::MD5::MD5Result
Result;
1023 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
1024 if (!InstrumentRegions && !PGOReader)
1032 if (
const auto *CCD = dyn_cast<CXXConstructorDecl>(
D))
1041 if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
1043 if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
1053 mapRegionCounters(
D);
1055 emitCounterRegionMapping(
D);
1058 computeRegionCounts(
D);
1059 applyFunctionAttributes(PGOReader, Fn);
1063void CodeGenPGO::mapRegionCounters(
const Decl *
D) {
1067 uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
1069 HashVersion = getPGOHashVersion(PGOReader, CGM);
1070 ProfileVersion = PGOReader->getVersion();
1082 unsigned MCDCMaxConditions =
1086 RegionCounterMap.reset(
new llvm::DenseMap<const Stmt *, unsigned>);
1088 MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
1089 *RegionMCDCState, MCDCMaxConditions, CGM.
getDiags());
1090 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(
D))
1092 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(
D))
1094 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(
D))
1095 Walker.TraverseDecl(
const_cast<BlockDecl *
>(BD));
1096 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(
D))
1098 assert(Walker.NextCounter > 0 &&
"no entry counter mapped for decl");
1099 NumRegionCounters = Walker.NextCounter;
1100 FunctionHash = Walker.Hash.finalize();
1103bool CodeGenPGO::skipRegionMappingForDecl(
const Decl *
D) {
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();
1134 CGM.
getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1135 MappingGen.emitCounterMapping(
D, OS);
1137 if (CoverageMapping.empty())
1141 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1146 llvm::GlobalValue::LinkageTypes
Linkage) {
1147 if (skipRegionMappingForDecl(
D))
1150 std::string CoverageMapping;
1151 llvm::raw_string_ostream OS(CoverageMapping);
1157 if (CoverageMapping.empty())
1162 FuncNameVar, FuncName, FunctionHash, CoverageMapping,
false);
1165void CodeGenPGO::computeRegionCounts(
const Decl *
D) {
1166 StmtCountMap.reset(
new llvm::DenseMap<const Stmt *, uint64_t>);
1167 ComputeRegionCounts Walker(*StmtCountMap, *
this);
1168 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(
D))
1169 Walker.VisitFunctionDecl(FD);
1170 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(
D))
1171 Walker.VisitObjCMethodDecl(MD);
1172 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(
D))
1173 Walker.VisitBlockDecl(BD);
1174 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(
D))
1175 Walker.VisitCapturedDecl(
const_cast<CapturedDecl *
>(CD));
1179CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1180 llvm::Function *Fn) {
1185 Fn->setEntryCount(FunctionCount);
1189 llvm::Value *StepV) {
1190 if (!RegionCounterMap || !Builder.GetInsertBlock())
1193 unsigned Counter = (*RegionCounterMap)[S];
1197 auto *NormalizedFuncNameVarPtr =
1198 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1201 llvm::Value *Args[] = {
1202 NormalizedFuncNameVarPtr, Builder.getInt64(FunctionHash),
1203 Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV};
1206 Builder.CreateCall(CGM.
getIntrinsic(llvm::Intrinsic::instrprof_cover),
1209 Builder.CreateCall(CGM.
getIntrinsic(llvm::Intrinsic::instrprof_increment),
1213 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={})
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.
@ Ctor_Base
Base object ctor.
@ 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.
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