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());
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 {
102 ObjCForCollectionStmt,
112 BinaryConditionalOperator,
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)
155 if (PGOReader->getVersion() <= 12)
161struct MapRegionCounters :
public RecursiveASTVisitor<MapRegionCounters> {
162 using Base = RecursiveASTVisitor<MapRegionCounters>;
165 unsigned NextCounter;
169 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
171 MCDC::State &MCDCState;
173 unsigned MCDCMaxCond;
177 DiagnosticsEngine &
Diag;
179 MapRegionCounters(
PGOHashVersion HashVersion, uint64_t ProfileVersion,
180 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
181 MCDC::State &MCDCState,
unsigned MCDCMaxCond,
182 DiagnosticsEngine &
Diag)
183 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
184 MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
185 ProfileVersion(ProfileVersion),
Diag(
Diag) {}
189 bool TraverseBlockExpr(BlockExpr *BE) {
return true; }
192 for (
auto C : zip(
LE->captures(),
LE->capture_inits()))
193 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
196 bool TraverseCapturedStmt(CapturedStmt *CS) {
return true; }
198 bool VisitDecl(
const Decl *D) {
203 case Decl::CXXMethod:
204 case Decl::CXXConstructor:
205 case Decl::CXXDestructor:
206 case Decl::CXXConversion:
207 case Decl::ObjCMethod:
210 CounterMap[D->
getBody()] = NextCounter++;
218 PGOHash::HashType updateCounterMappings(Stmt *S) {
220 if (
Type != PGOHash::None)
221 CounterMap[S] = NextCounter++;
234 struct DecisionState {
235 llvm::DenseSet<const Stmt *> Leaves;
236 const Expr *DecisionExpr;
239 DecisionState() =
delete;
240 DecisionState(
const Expr *E,
bool Split =
false)
244 SmallVector<DecisionState, 1> DecisionStack;
247 bool dataTraverseStmtPre(Stmt *S) {
249 if (MCDCMaxCond == 0)
253 if (!DecisionStack.empty()) {
254 auto &StackTop = DecisionStack.back();
255 if (!StackTop.Split) {
256 if (StackTop.Leaves.contains(S)) {
257 assert(!StackTop.Split);
258 StackTop.Split =
true;
264 assert(StackTop.Split);
265 assert(!StackTop.Leaves.contains(S));
268 if (
const auto *E = dyn_cast<Expr>(S)) {
269 if (
const auto *BinOp =
271 BinOp && BinOp->isLogicalOp())
272 DecisionStack.emplace_back(E);
281 bool dataTraverseStmtPost(Stmt *S) {
282 if (DecisionStack.empty())
286 assert(MCDCMaxCond > 0);
288 auto &StackTop = DecisionStack.back();
290 if (StackTop.DecisionExpr != S) {
291 if (StackTop.Leaves.contains(S)) {
292 assert(StackTop.Split);
293 StackTop.Split =
false;
300 auto &DecisionEntry =
305 auto NumCond = StackTop.Leaves.size();
306 if (NumCond > MCDCMaxCond) {
308 << NumCond << MCDCMaxCond;
309 DecisionStack.pop_back();
316 DecisionStack.pop_back();
326 bool VisitBinaryOperator(BinaryOperator *S) {
329 if (!DecisionStack.empty())
330 DecisionStack.back().Leaves.insert(S->
getLHS());
334 if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
335 CounterMap[S->
getRHS()] = NextCounter++;
337 if (!DecisionStack.empty())
338 DecisionStack.back().Leaves.insert(S->
getRHS());
341 return Base::VisitBinaryOperator(S);
345 bool VisitStmt(Stmt *S) {
346 auto Type = updateCounterMappings(S);
348 Type = getHashType(Hash.getHashVersion(), S);
349 if (
Type != PGOHash::None)
354 bool TraverseIfStmt(IfStmt *
If) {
357 return Base::TraverseIfStmt(
If);
362 for (Stmt *CS :
If->children()) {
365 if (CS ==
If->getThen())
366 Hash.combine(PGOHash::IfThenBranch);
367 else if (CS ==
If->getElse())
368 Hash.combine(PGOHash::IfElseBranch);
371 Hash.combine(PGOHash::EndOfScope);
378#define DEFINE_NESTABLE_TRAVERSAL(N) \
379 bool Traverse##N(N *S) { \
380 Base::Traverse##N(S); \
381 if (Hash.getHashVersion() != PGO_HASH_V1) \
382 Hash.combine(PGOHash::EndOfScope); \
399 case Stmt::LabelStmtClass:
400 return PGOHash::LabelStmt;
401 case Stmt::WhileStmtClass:
402 return PGOHash::WhileStmt;
403 case Stmt::DoStmtClass:
404 return PGOHash::DoStmt;
405 case Stmt::ForStmtClass:
406 return PGOHash::ForStmt;
407 case Stmt::CXXForRangeStmtClass:
408 return PGOHash::CXXForRangeStmt;
409 case Stmt::ObjCForCollectionStmtClass:
410 return PGOHash::ObjCForCollectionStmt;
411 case Stmt::SwitchStmtClass:
412 return PGOHash::SwitchStmt;
413 case Stmt::CaseStmtClass:
414 return PGOHash::CaseStmt;
415 case Stmt::DefaultStmtClass:
416 return PGOHash::DefaultStmt;
417 case Stmt::IfStmtClass:
418 return PGOHash::IfStmt;
419 case Stmt::CXXTryStmtClass:
420 return PGOHash::CXXTryStmt;
421 case Stmt::CXXCatchStmtClass:
422 return PGOHash::CXXCatchStmt;
423 case Stmt::ConditionalOperatorClass:
424 return PGOHash::ConditionalOperator;
425 case Stmt::BinaryConditionalOperatorClass:
426 return PGOHash::BinaryConditionalOperator;
427 case Stmt::BinaryOperatorClass: {
430 return PGOHash::BinaryOperatorLAnd;
432 return PGOHash::BinaryOperatorLOr;
438 return PGOHash::BinaryOperatorLT;
440 return PGOHash::BinaryOperatorGT;
442 return PGOHash::BinaryOperatorLE;
444 return PGOHash::BinaryOperatorGE;
446 return PGOHash::BinaryOperatorEQ;
448 return PGOHash::BinaryOperatorNE;
459 case Stmt::GotoStmtClass:
460 return PGOHash::GotoStmt;
461 case Stmt::IndirectGotoStmtClass:
462 return PGOHash::IndirectGotoStmt;
463 case Stmt::BreakStmtClass:
464 return PGOHash::BreakStmt;
465 case Stmt::ContinueStmtClass:
466 return PGOHash::ContinueStmt;
467 case Stmt::ReturnStmtClass:
468 return PGOHash::ReturnStmt;
469 case Stmt::CXXThrowExprClass:
470 return PGOHash::ThrowExpr;
471 case Stmt::UnaryOperatorClass: {
474 return PGOHash::UnaryOperatorLNot;
480 return PGOHash::None;
486struct ComputeRegionCounts :
public ConstStmtVisitor<ComputeRegionCounts> {
492 bool RecordNextStmtCount;
498 llvm::DenseMap<const Stmt *, uint64_t> &
CountMap;
501 struct BreakContinue {
504 BreakContinue() =
default;
506 SmallVector<BreakContinue, 8> BreakContinueStack;
508 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &
CountMap,
512 void RecordStmtCount(
const Stmt *S) {
513 if (RecordNextStmtCount) {
515 RecordNextStmtCount =
false;
521 CurrentCount = Count;
525 void VisitStmt(
const Stmt *S) {
527 for (
const Stmt *Child : S->
children())
532 void VisitFunctionDecl(
const FunctionDecl *D) {
544 void VisitCapturedDecl(
const CapturedDecl *D) {
551 void VisitObjCMethodDecl(
const ObjCMethodDecl *D) {
558 void VisitBlockDecl(
const BlockDecl *D) {
565 void VisitReturnStmt(
const ReturnStmt *S) {
570 RecordNextStmtCount =
true;
573 void VisitCXXThrowExpr(
const CXXThrowExpr *E) {
578 RecordNextStmtCount =
true;
581 void VisitGotoStmt(
const GotoStmt *S) {
584 RecordNextStmtCount =
true;
587 void VisitLabelStmt(
const LabelStmt *S) {
588 RecordNextStmtCount =
false;
595 void VisitBreakStmt(
const BreakStmt *S) {
597 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
598 BreakContinueStack.back().BreakCount += CurrentCount;
600 RecordNextStmtCount =
true;
603 void VisitContinueStmt(
const ContinueStmt *S) {
605 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
606 BreakContinueStack.back().ContinueCount += CurrentCount;
608 RecordNextStmtCount =
true;
611 void VisitWhileStmt(
const WhileStmt *S) {
613 uint64_t ParentCount = CurrentCount;
615 BreakContinueStack.push_back(BreakContinue());
621 uint64_t BackedgeCount = CurrentCount;
627 BreakContinue BC = BreakContinueStack.pop_back_val();
629 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
632 setCount(BC.BreakCount + CondCount - BodyCount);
633 RecordNextStmtCount =
true;
636 void VisitDoStmt(
const DoStmt *S) {
640 BreakContinueStack.push_back(BreakContinue());
642 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
645 uint64_t BackedgeCount = CurrentCount;
647 BreakContinue BC = BreakContinueStack.pop_back_val();
650 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
653 setCount(BC.BreakCount + CondCount - LoopCount);
654 RecordNextStmtCount =
true;
657 void VisitForStmt(
const ForStmt *S) {
662 uint64_t ParentCount = CurrentCount;
664 BreakContinueStack.push_back(BreakContinue());
670 uint64_t BackedgeCount = CurrentCount;
671 BreakContinue BC = BreakContinueStack.pop_back_val();
676 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
683 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
688 setCount(BC.BreakCount + CondCount - BodyCount);
689 RecordNextStmtCount =
true;
692 void VisitCXXForRangeStmt(
const CXXForRangeStmt *S) {
701 uint64_t ParentCount = CurrentCount;
702 BreakContinueStack.push_back(BreakContinue());
708 uint64_t BackedgeCount = CurrentCount;
709 BreakContinue BC = BreakContinueStack.pop_back_val();
713 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
719 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
722 setCount(BC.BreakCount + CondCount - BodyCount);
723 RecordNextStmtCount =
true;
726 void VisitObjCForCollectionStmt(
const ObjCForCollectionStmt *S) {
729 uint64_t ParentCount = CurrentCount;
730 BreakContinueStack.push_back(BreakContinue());
735 uint64_t BackedgeCount = CurrentCount;
736 BreakContinue BC = BreakContinueStack.pop_back_val();
738 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
740 RecordNextStmtCount =
true;
743 void VisitSwitchStmt(
const SwitchStmt *S) {
749 BreakContinueStack.push_back(BreakContinue());
752 BreakContinue BC = BreakContinueStack.pop_back_val();
753 if (!BreakContinueStack.empty())
754 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
757 RecordNextStmtCount =
true;
760 void VisitSwitchCase(
const SwitchCase *S) {
761 RecordNextStmtCount =
false;
766 setCount(CurrentCount + CaseCount);
770 RecordNextStmtCount =
true;
774 void VisitIfStmt(
const IfStmt *S) {
784 uint64_t ParentCount = CurrentCount;
796 uint64_t ElseCount = ParentCount - ThenCount;
801 OutCount += CurrentCount;
803 OutCount += ElseCount;
805 RecordNextStmtCount =
true;
808 void VisitCXXTryStmt(
const CXXTryStmt *S) {
815 RecordNextStmtCount =
true;
818 void VisitCXXCatchStmt(
const CXXCatchStmt *S) {
819 RecordNextStmtCount =
false;
826 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *E) {
828 uint64_t ParentCount = CurrentCount;
838 uint64_t FalseCount = setCount(ParentCount - TrueCount);
841 OutCount += CurrentCount;
844 RecordNextStmtCount =
true;
847 void VisitBinLAnd(
const BinaryOperator *E) {
849 uint64_t ParentCount = CurrentCount;
855 setCount(ParentCount + RHSCount - CurrentCount);
856 RecordNextStmtCount =
true;
859 void VisitBinLOr(
const BinaryOperator *E) {
861 uint64_t ParentCount = CurrentCount;
867 setCount(ParentCount + RHSCount - CurrentCount);
868 RecordNextStmtCount =
true;
873void PGOHash::combine(HashType
Type) {
875 assert(
Type &&
"Hash is invalid: unexpected type 0");
876 assert(
unsigned(
Type) < TooBig &&
"Hash is invalid: too many types");
879 if (Count && Count % NumTypesPerWord == 0) {
880 using namespace llvm::support;
882 endian::byte_swap<uint64_t>(Working, llvm::endianness::little);
883 MD5.update(llvm::ArrayRef((
uint8_t *)&Swapped,
sizeof(Swapped)));
889 Working = Working << NumBitsPerType |
Type;
894 if (Count <= NumTypesPerWord)
905 MD5.update({(
uint8_t)Working});
907 using namespace llvm::support;
909 endian::byte_swap<uint64_t>(Working, llvm::endianness::little);
910 MD5.update(llvm::ArrayRef((
uint8_t *)&Swapped,
sizeof(Swapped)));
915 llvm::MD5::MD5Result
Result;
926 if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice &&
930 bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
931 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
932 if (!InstrumentRegions && !PGOReader)
939 if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
940 if (
const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
948 CGM.ClearUnusedCoverageMapping(D);
949 if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
951 if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
961 mapRegionCounters(D);
962 if (CGM.getCodeGenOpts().CoverageMapping)
963 emitCounterRegionMapping(D);
966 computeRegionCounts(D);
967 applyFunctionAttributes(PGOReader, Fn);
971void CodeGenPGO::mapRegionCounters(
const Decl *D) {
975 uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
977 HashVersion = getPGOHashVersion(PGOReader, CGM);
978 ProfileVersion = PGOReader->getVersion();
990 unsigned MCDCMaxConditions =
994 RegionCounterMap.reset(
new llvm::DenseMap<const Stmt *, CounterPair>);
996 MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
997 *RegionMCDCState, MCDCMaxConditions, CGM.
getDiags());
998 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
1000 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
1002 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
1003 Walker.TraverseDecl(
const_cast<BlockDecl *
>(BD));
1004 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
1006 assert(Walker.NextCounter > 0 &&
"no entry counter mapped for decl");
1007 NumRegionCounters = Walker.NextCounter;
1008 FunctionHash = Walker.Hash.finalize();
1010 FunctionHash &= llvm::NamedInstrProfRecord::FUNC_HASH_MASK;
1013bool CodeGenPGO::skipRegionMappingForDecl(
const Decl *D) {
1023 !D->
hasAttr<CUDAGlobalAttr>()) ||
1025 (D->
hasAttr<CUDAGlobalAttr>() ||
1026 (!D->
hasAttr<CUDAHostAttr>() && D->
hasAttr<CUDADeviceAttr>())))))
1035void CodeGenPGO::emitCounterRegionMapping(
const Decl *D) {
1036 if (skipRegionMappingForDecl(D))
1039 std::string CoverageMapping;
1040 llvm::raw_string_ostream
OS(CoverageMapping);
1041 RegionMCDCState->BranchByStmt.clear();
1042 CoverageMappingGen MappingGen(
1043 *CGM.getCoverageMapping(), CGM.getContext().getSourceManager(),
1044 CGM.getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1045 MappingGen.emitCounterMapping(D, OS);
1047 if (CoverageMapping.empty())
1051 unsigned MaxNumCounters = NumRegionCounters;
1052 for (
const auto &[_,
V] : *RegionCounterMap) {
1053 assert((!
V.Executed.hasValue() || MaxNumCounters >
V.Executed) &&
1054 "TrueCnt should not be reassigned");
1055 if (
V.Skipped.hasValue())
1056 MaxNumCounters = std::max(MaxNumCounters,
V.Skipped + 1);
1058 NumRegionCounters = MaxNumCounters;
1060 CGM.getCoverageMapping()->addFunctionMappingRecord(
1061 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1066 llvm::GlobalValue::LinkageTypes
Linkage) {
1067 if (skipRegionMappingForDecl(D))
1070 std::string CoverageMapping;
1071 llvm::raw_string_ostream OS(CoverageMapping);
1073 CGM.getContext().getSourceManager(),
1077 if (CoverageMapping.empty())
1081 CGM.getCoverageMapping()->addFunctionMappingRecord(
1082 FuncNameVar, FuncName, FunctionHash, CoverageMapping,
false);
1085void CodeGenPGO::computeRegionCounts(
const Decl *D) {
1086 StmtCountMap.reset(
new llvm::DenseMap<const Stmt *, uint64_t>);
1087 ComputeRegionCounts Walker(*StmtCountMap, *
this);
1088 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
1089 Walker.VisitFunctionDecl(FD);
1090 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
1091 Walker.VisitObjCMethodDecl(MD);
1092 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
1093 Walker.VisitBlockDecl(BD);
1094 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
1095 Walker.VisitCapturedDecl(
const_cast<CapturedDecl *
>(CD));
1099CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1100 llvm::Function *Fn) {
1105 Fn->setEntryCount(FunctionCount);
1109 if (!RegionCounterMap)
1112 auto I = RegionCounterMap->find(S);
1113 if (I == RegionCounterMap->end())
1116 return I->second.Skipped.hasValue();
1120 bool UseSkipPath,
bool UseBoth,
1121 llvm::Value *StepV) {
1122 if (!RegionCounterMap)
1126 const auto &TheCounterPair = (*RegionCounterMap)[S];
1128 if (!Builder.GetInsertBlock())
1132 (UseSkipPath ? TheCounterPair.Skipped : TheCounterPair.Executed);
1138 auto *NormalizedFuncNameVarPtr =
1139 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1140 FuncNameVar, llvm::PointerType::get(CGM.getLLVMContext(), 0));
1142 llvm::Value *Args[] = {
1143 NormalizedFuncNameVarPtr, Builder.getInt64(FunctionHash),
1144 Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV};
1147 assert(!StepV &&
"StepV is not supported in single byte counter mode");
1148 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover),
1151 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
1155 CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
1158bool CodeGenPGO::canEmitMCDCCoverage(
const CGBuilderTy &Builder) {
1164 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1167 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1172 llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1173 Builder.getInt64(FunctionHash),
1174 Builder.getInt32(RegionMCDCState->BitmapBits)};
1176 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
1180std::vector<Address *>
1182 std::vector<Address *>
Result;
1184 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1188 for (
auto &[_,
V] : RegionMCDCState->DecisionByStmt)
1190 SortedPair.emplace_back(
V.ID, &
V.MCDCCondBitmapAddr);
1192 llvm::sort(SortedPair);
1194 for (
auto &[_, MCDCCondBitmapAddr] : SortedPair)
1195 Result.push_back(MCDCCondBitmapAddr);
1203 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1208 auto DecisionStateIter = RegionMCDCState->DecisionByStmt.find(S);
1209 if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
1212 auto &MCDCCondBitmapAddr = DecisionStateIter->second.MCDCCondBitmapAddr;
1213 if (!MCDCCondBitmapAddr.isValid())
1218 if (DecisionStateIter->second.Indices.size() == 0)
1222 unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
1223 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1230 llvm::Value *Args[4] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1231 Builder.getInt64(FunctionHash),
1232 Builder.getInt32(MCDCTestVectorBitmapOffset),
1233 MCDCCondBitmapAddr.emitRawPointer(CGF)};
1235 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
1239 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1242 auto I = RegionMCDCState->DecisionByStmt.find(S->
IgnoreParens());
1243 if (I == RegionMCDCState->DecisionByStmt.end())
1246 auto &MCDCCondBitmapAddr = I->second.MCDCCondBitmapAddr;
1247 if (!MCDCCondBitmapAddr.isValid())
1251 Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr);
1257 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1269 auto BranchStateIter = RegionMCDCState->BranchByStmt.find(S);
1270 if (BranchStateIter == RegionMCDCState->BranchByStmt.end())
1274 const auto &Branch = BranchStateIter->second;
1275 assert(Branch.ID >= 0 &&
"Condition has no ID!");
1276 assert(Branch.DecisionStmt);
1279 const auto DecisionIter =
1280 RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
1281 if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
1284 auto &MCDCCondBitmapAddr = DecisionIter->second.MCDCCondBitmapAddr;
1285 if (!MCDCCondBitmapAddr.isValid())
1288 const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
1290 auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
1291 "mcdc." + Twine(Branch.ID + 1) +
".cur");
1292 auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
true]));
1293 NewTV = Builder.CreateSelect(
1294 Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
false])));
1295 Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
1299 if (CGM.getCodeGenOpts().hasProfileClangInstr())
1300 M.addModuleFlag(llvm::Module::Warning,
"EnableValueProfiling",
1305 if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
1307 const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1308 llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
1309 uint64_t ProfileVersion =
1310 (INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);
1312 auto IRLevelVersionVariable =
new llvm::GlobalVariable(
1313 M, IntTy64,
true, llvm::GlobalValue::WeakAnyLinkage,
1314 llvm::Constant::getIntegerValue(IntTy64,
1315 llvm::APInt(64, ProfileVersion)),
1318 IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1319 llvm::Triple TT(M.getTargetTriple());
1321 IRLevelVersionVariable->setVisibility(
1322 llvm::GlobalValue::ProtectedVisibility);
1323 if (TT.supportsCOMDAT()) {
1324 IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
1325 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
1327 IRLevelVersionVariable->setDSOLocal(
true);
1334 llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
1339 if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
1345 bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
1346 if (InstrumentValueSites && RegionCounterMap) {
1347 auto BuilderInsertPoint = Builder.saveIP();
1348 Builder.SetInsertPoint(ValueSite);
1349 llvm::Value *Args[5] = {
1351 Builder.getInt64(FunctionHash),
1352 Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1353 Builder.getInt32(ValueKind),
1354 Builder.getInt32(NumValueSites[ValueKind]++)
1357 CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1358 Builder.restoreIP(BuilderInsertPoint);
1362 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1370 if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1373 llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
1374 (llvm::InstrProfValueKind)ValueKind,
1375 NumValueSites[ValueKind]);
1377 NumValueSites[ValueKind]++;
1381void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
1382 bool IsInMainFile) {
1384 RegionCounts.clear();
1385 auto RecordExpected = PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1386 if (
auto E = RecordExpected.takeError()) {
1387 auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(E)));
1388 if (IPE == llvm::instrprof_error::unknown_function)
1390 else if (IPE == llvm::instrprof_error::hash_mismatch)
1392 else if (IPE == llvm::instrprof_error::malformed)
1398 std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1399 RegionCounts = ProfRecord->Counts;
1407 return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
1420 assert(Scale &&
"scale by 0?");
1421 uint64_t Scaled = Weight / Scale + 1;
1422 assert(Scaled <= UINT32_MAX &&
"overflow 32-bits");
1426llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1427 uint64_t FalseCount)
const {
1429 if (!TrueCount && !FalseCount)
1435 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
1441CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights)
const {
1443 if (Weights.size() < 2)
1447 uint64_t MaxWeight = *llvm::max_element(Weights);
1454 SmallVector<uint32_t, 16> ScaledWeights;
1455 ScaledWeights.reserve(Weights.size());
1456 for (uint64_t W : Weights)
1459 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
1460 return MDHelper.createBranchWeights(ScaledWeights);
1464CodeGenFunction::createProfileWeightsForLoop(
const Stmt *Cond,
1465 uint64_t LoopCount)
const {
1466 if (!PGO->haveRegionCounts())
1468 std::optional<uint64_t> CondCount = PGO->getStmtCount(Cond);
1469 if (!CondCount || *CondCount == 0)
1471 return createProfileWeights(LoopCount,
1472 std::max(*CondCount, LoopCount) - LoopCount);
1476 const Stmt *S,
bool UseBoth,
1477 llvm::Value *StepV) {
1478 if (
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1479 !
CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
1480 !
CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) {
1485 PGO->setCurrentStmt(S);
1489 return PGO->hasSkipCounter(S);
1492 PGO->markStmtAsUsed(Skipped, S);
1495 PGO->markStmtMaybeUsed(S);
1500 PGO->emitMCDCParameters(
Builder);
1504 for (
auto *MCDCCondBitmapAddr : PGO->getMCDCCondBitmapAddrArray(
Builder))
1505 *MCDCCondBitmapAddr =
1510 return PGO->isMCDCDecisionExpr(E);
1513 return PGO->isMCDCBranchExpr(E);
1517 PGO->emitMCDCCondBitmapReset(
Builder, E);
1518 PGO->setCurrentStmt(E);
1523 PGO->emitMCDCTestVectorBitmapUpdate(
Builder, E, *
this);
1524 PGO->setCurrentStmt(E);
1531 PGO->emitMCDCCondBitmapUpdate(
Builder, E, Val, *
this);
1532 PGO->setCurrentStmt(E);
1537 return PGO->getStmtCount(S).value_or(0);
1542 PGO->setCurrentRegionCount(Count);
1548 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
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
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)
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...
bool hasSkipCounter(const Stmt *S) const
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....
RawAddress CreateIRTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateIRTempWithoutCast - Create a temporary IR object of the given type, with appropriate alignment.
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)
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.
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)
bool hasSkipCounter(const Stmt *S) const
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.
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
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.
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.
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceLocation getBeginLoc() const LLVM_READONLY
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.
@ 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)
Top level wrappers for InstallAPI frontend operations.
@ 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.
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
int32_t uint32_t uint32_t __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
Per-Function MC/DC state.
llvm::DenseMap< const Stmt *, Decision > DecisionByStmt