20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/MDBuilder.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/Endian.h"
24#include "llvm/Support/MD5.h"
31static llvm::cl::opt<bool>
33 llvm::cl::desc(
"Enable value profiling"),
34 llvm::cl::Hidden, llvm::cl::init(
false));
39void CodeGenPGO::setFuncName(StringRef Name,
40 llvm::GlobalValue::LinkageTypes
Linkage) {
41 llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
42 FuncName = llvm::getPGOFuncName(
44 PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
48 FuncNameVar = llvm::createPGOFuncNameVar(CGM.
getModule(),
Linkage, FuncName);
51void CodeGenPGO::setFuncName(llvm::Function *Fn) {
52 setFuncName(
Fn->getName(),
Fn->getLinkage());
54 llvm::createPGOFuncNameMetadata(*Fn, FuncName);
85 static const int NumBitsPerType = 6;
86 static const unsigned NumTypesPerWord =
sizeof(
uint64_t) * 8 / NumBitsPerType;
87 static const unsigned TooBig = 1u << NumBitsPerType;
97 enum HashType :
unsigned char {
104 ObjCForCollectionStmt,
114 BinaryConditionalOperator,
138 static_assert(LastHashType <= TooBig,
"Too many types in HashType");
141 : Working(0), Count(0), HashVersion(HashVersion) {}
142 void combine(HashType
Type);
146const int PGOHash::NumBitsPerType;
147const unsigned PGOHash::NumTypesPerWord;
148const unsigned PGOHash::TooBig;
151static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
153 if (PGOReader->getVersion() <= 4)
155 if (PGOReader->getVersion() <= 5)
157 if (PGOReader->getVersion() <= 12)
163struct MapRegionCounters :
public RecursiveASTVisitor<MapRegionCounters> {
164 using Base = RecursiveASTVisitor<MapRegionCounters>;
167 unsigned NextCounter;
171 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
173 MCDC::State &MCDCState;
175 unsigned MCDCMaxCond;
179 DiagnosticsEngine &
Diag;
181 MapRegionCounters(
PGOHashVersion HashVersion, uint64_t ProfileVersion,
182 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
183 MCDC::State &MCDCState,
unsigned MCDCMaxCond,
184 DiagnosticsEngine &
Diag)
185 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
186 MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
187 ProfileVersion(ProfileVersion),
Diag(
Diag) {}
191 bool TraverseBlockExpr(BlockExpr *BE) {
return true; }
194 for (
auto C : zip(
LE->captures(),
LE->capture_inits()))
195 TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
198 bool TraverseCapturedStmt(CapturedStmt *CS) {
return true; }
200 bool VisitDecl(
const Decl *D) {
205 case Decl::CXXMethod:
206 case Decl::CXXConstructor:
207 case Decl::CXXDestructor:
208 case Decl::CXXConversion:
209 case Decl::ObjCMethod:
212 CounterMap[D->
getBody()] = NextCounter++;
220 PGOHash::HashType updateCounterMappings(Stmt *S) {
222 if (
Type != PGOHash::None)
223 CounterMap[S] = NextCounter++;
236 struct DecisionState {
237 llvm::DenseSet<const Stmt *> Leaves;
238 const Expr *DecisionExpr;
241 DecisionState() =
delete;
242 DecisionState(
const Expr *E,
bool Split =
false)
246 SmallVector<DecisionState, 1> DecisionStack;
249 bool dataTraverseStmtPre(Stmt *S) {
251 if (MCDCMaxCond == 0)
255 if (!DecisionStack.empty()) {
256 auto &StackTop = DecisionStack.back();
257 if (!StackTop.Split) {
258 if (StackTop.Leaves.contains(S)) {
259 assert(!StackTop.Split);
260 StackTop.Split =
true;
266 assert(StackTop.Split);
267 assert(!StackTop.Leaves.contains(S));
270 if (
const auto *E = dyn_cast<Expr>(S)) {
271 if (
const auto *BinOp =
273 BinOp && BinOp->isLogicalOp())
274 DecisionStack.emplace_back(E);
283 bool dataTraverseStmtPost(Stmt *S) {
284 if (DecisionStack.empty())
288 assert(MCDCMaxCond > 0);
290 auto &StackTop = DecisionStack.back();
292 if (StackTop.DecisionExpr != S) {
293 if (StackTop.Leaves.contains(S)) {
294 assert(StackTop.Split);
295 StackTop.Split =
false;
302 auto &DecisionEntry =
307 auto NumCond = StackTop.Leaves.size();
308 if (NumCond > MCDCMaxCond) {
310 << NumCond << MCDCMaxCond;
311 DecisionStack.pop_back();
318 DecisionStack.pop_back();
328 bool VisitBinaryOperator(BinaryOperator *S) {
331 if (!DecisionStack.empty())
332 DecisionStack.back().Leaves.insert(S->
getLHS());
336 if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
337 CounterMap[S->
getRHS()] = NextCounter++;
339 if (!DecisionStack.empty())
340 DecisionStack.back().Leaves.insert(S->
getRHS());
343 return Base::VisitBinaryOperator(S);
347 bool VisitStmt(Stmt *S) {
348 auto Type = updateCounterMappings(S);
350 Type = getHashType(Hash.getHashVersion(), S);
351 if (
Type != PGOHash::None)
356 bool TraverseIfStmt(IfStmt *
If) {
359 return Base::TraverseIfStmt(
If);
364 for (Stmt *CS :
If->children()) {
367 if (CS ==
If->getThen())
368 Hash.combine(PGOHash::IfThenBranch);
369 else if (CS ==
If->getElse())
370 Hash.combine(PGOHash::IfElseBranch);
373 Hash.combine(PGOHash::EndOfScope);
380#define DEFINE_NESTABLE_TRAVERSAL(N) \
381 bool Traverse##N(N *S) { \
382 Base::Traverse##N(S); \
383 if (Hash.getHashVersion() != PGO_HASH_V1) \
384 Hash.combine(PGOHash::EndOfScope); \
401 case Stmt::LabelStmtClass:
402 return PGOHash::LabelStmt;
403 case Stmt::WhileStmtClass:
404 return PGOHash::WhileStmt;
405 case Stmt::DoStmtClass:
406 return PGOHash::DoStmt;
407 case Stmt::ForStmtClass:
408 return PGOHash::ForStmt;
409 case Stmt::CXXForRangeStmtClass:
410 return PGOHash::CXXForRangeStmt;
411 case Stmt::ObjCForCollectionStmtClass:
412 return PGOHash::ObjCForCollectionStmt;
413 case Stmt::SwitchStmtClass:
414 return PGOHash::SwitchStmt;
415 case Stmt::CaseStmtClass:
416 return PGOHash::CaseStmt;
417 case Stmt::DefaultStmtClass:
418 return PGOHash::DefaultStmt;
419 case Stmt::IfStmtClass:
420 return PGOHash::IfStmt;
421 case Stmt::CXXTryStmtClass:
422 return PGOHash::CXXTryStmt;
423 case Stmt::CXXCatchStmtClass:
424 return PGOHash::CXXCatchStmt;
425 case Stmt::ConditionalOperatorClass:
426 return PGOHash::ConditionalOperator;
427 case Stmt::BinaryConditionalOperatorClass:
428 return PGOHash::BinaryConditionalOperator;
429 case Stmt::BinaryOperatorClass: {
432 return PGOHash::BinaryOperatorLAnd;
434 return PGOHash::BinaryOperatorLOr;
440 return PGOHash::BinaryOperatorLT;
442 return PGOHash::BinaryOperatorGT;
444 return PGOHash::BinaryOperatorLE;
446 return PGOHash::BinaryOperatorGE;
448 return PGOHash::BinaryOperatorEQ;
450 return PGOHash::BinaryOperatorNE;
461 case Stmt::GotoStmtClass:
462 return PGOHash::GotoStmt;
463 case Stmt::IndirectGotoStmtClass:
464 return PGOHash::IndirectGotoStmt;
465 case Stmt::BreakStmtClass:
466 return PGOHash::BreakStmt;
467 case Stmt::ContinueStmtClass:
468 return PGOHash::ContinueStmt;
469 case Stmt::ReturnStmtClass:
470 return PGOHash::ReturnStmt;
471 case Stmt::CXXThrowExprClass:
472 return PGOHash::ThrowExpr;
473 case Stmt::UnaryOperatorClass: {
476 return PGOHash::UnaryOperatorLNot;
482 return PGOHash::None;
488struct ComputeRegionCounts :
public ConstStmtVisitor<ComputeRegionCounts> {
494 bool RecordNextStmtCount;
500 llvm::DenseMap<const Stmt *, uint64_t> &
CountMap;
503 struct BreakContinue {
506 BreakContinue() =
default;
508 SmallVector<BreakContinue, 8> BreakContinueStack;
510 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &
CountMap,
514 void RecordStmtCount(
const Stmt *S) {
515 if (RecordNextStmtCount) {
517 RecordNextStmtCount =
false;
523 CurrentCount = Count;
527 void VisitStmt(
const Stmt *S) {
529 for (
const Stmt *Child : S->
children())
534 void VisitFunctionDecl(
const FunctionDecl *D) {
546 void VisitCapturedDecl(
const CapturedDecl *D) {
553 void VisitObjCMethodDecl(
const ObjCMethodDecl *D) {
560 void VisitBlockDecl(
const BlockDecl *D) {
567 void VisitReturnStmt(
const ReturnStmt *S) {
572 RecordNextStmtCount =
true;
575 void VisitCXXThrowExpr(
const CXXThrowExpr *E) {
580 RecordNextStmtCount =
true;
583 void VisitGotoStmt(
const GotoStmt *S) {
586 RecordNextStmtCount =
true;
589 void VisitLabelStmt(
const LabelStmt *S) {
590 RecordNextStmtCount =
false;
597 void VisitBreakStmt(
const BreakStmt *S) {
599 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
600 BreakContinueStack.back().BreakCount += CurrentCount;
602 RecordNextStmtCount =
true;
605 void VisitContinueStmt(
const ContinueStmt *S) {
607 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
608 BreakContinueStack.back().ContinueCount += CurrentCount;
610 RecordNextStmtCount =
true;
613 void VisitWhileStmt(
const WhileStmt *S) {
615 uint64_t ParentCount = CurrentCount;
617 BreakContinueStack.push_back(BreakContinue());
623 uint64_t BackedgeCount = CurrentCount;
629 BreakContinue BC = BreakContinueStack.pop_back_val();
631 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
634 setCount(BC.BreakCount + CondCount - BodyCount);
635 RecordNextStmtCount =
true;
638 void VisitDoStmt(
const DoStmt *S) {
642 BreakContinueStack.push_back(BreakContinue());
644 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
647 uint64_t BackedgeCount = CurrentCount;
649 BreakContinue BC = BreakContinueStack.pop_back_val();
652 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
655 setCount(BC.BreakCount + CondCount - LoopCount);
656 RecordNextStmtCount =
true;
659 void VisitForStmt(
const ForStmt *S) {
664 uint64_t ParentCount = CurrentCount;
666 BreakContinueStack.push_back(BreakContinue());
672 uint64_t BackedgeCount = CurrentCount;
673 BreakContinue BC = BreakContinueStack.pop_back_val();
678 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
685 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
690 setCount(BC.BreakCount + CondCount - BodyCount);
691 RecordNextStmtCount =
true;
694 void VisitCXXForRangeStmt(
const CXXForRangeStmt *S) {
703 uint64_t ParentCount = CurrentCount;
704 BreakContinueStack.push_back(BreakContinue());
710 uint64_t BackedgeCount = CurrentCount;
711 BreakContinue BC = BreakContinueStack.pop_back_val();
715 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
721 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
724 setCount(BC.BreakCount + CondCount - BodyCount);
725 RecordNextStmtCount =
true;
728 void VisitObjCForCollectionStmt(
const ObjCForCollectionStmt *S) {
731 uint64_t ParentCount = CurrentCount;
732 BreakContinueStack.push_back(BreakContinue());
737 uint64_t BackedgeCount = CurrentCount;
738 BreakContinue BC = BreakContinueStack.pop_back_val();
740 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
742 RecordNextStmtCount =
true;
745 void VisitSwitchStmt(
const SwitchStmt *S) {
751 BreakContinueStack.push_back(BreakContinue());
754 BreakContinue BC = BreakContinueStack.pop_back_val();
755 if (!BreakContinueStack.empty())
756 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
759 RecordNextStmtCount =
true;
762 void VisitSwitchCase(
const SwitchCase *S) {
763 RecordNextStmtCount =
false;
768 setCount(CurrentCount + CaseCount);
772 RecordNextStmtCount =
true;
776 void VisitIfStmt(
const IfStmt *S) {
786 uint64_t ParentCount = CurrentCount;
798 uint64_t ElseCount = ParentCount - ThenCount;
803 OutCount += CurrentCount;
805 OutCount += ElseCount;
807 RecordNextStmtCount =
true;
810 void VisitCXXTryStmt(
const CXXTryStmt *S) {
817 RecordNextStmtCount =
true;
820 void VisitCXXCatchStmt(
const CXXCatchStmt *S) {
821 RecordNextStmtCount =
false;
828 void VisitAbstractConditionalOperator(
const AbstractConditionalOperator *E) {
830 uint64_t ParentCount = CurrentCount;
840 uint64_t FalseCount = setCount(ParentCount - TrueCount);
843 OutCount += CurrentCount;
846 RecordNextStmtCount =
true;
849 void VisitBinLAnd(
const BinaryOperator *E) {
851 uint64_t ParentCount = CurrentCount;
857 setCount(ParentCount + RHSCount - CurrentCount);
858 RecordNextStmtCount =
true;
861 void VisitBinLOr(
const BinaryOperator *E) {
863 uint64_t ParentCount = CurrentCount;
869 setCount(ParentCount + RHSCount - CurrentCount);
870 RecordNextStmtCount =
true;
875void PGOHash::combine(HashType
Type) {
877 assert(
Type &&
"Hash is invalid: unexpected type 0");
878 assert(
unsigned(
Type) < TooBig &&
"Hash is invalid: too many types");
881 if (Count && Count % NumTypesPerWord == 0) {
882 using namespace llvm::support;
884 endian::byte_swap<uint64_t>(Working, llvm::endianness::little);
885 MD5.update(llvm::ArrayRef((
uint8_t *)&Swapped,
sizeof(Swapped)));
891 Working = Working << NumBitsPerType |
Type;
896 if (Count <= NumTypesPerWord)
907 MD5.update({(
uint8_t)Working});
909 using namespace llvm::support;
911 endian::byte_swap<uint64_t>(Working, llvm::endianness::little);
912 MD5.update(llvm::ArrayRef((
uint8_t *)&Swapped,
sizeof(Swapped)));
917 llvm::MD5::MD5Result
Result;
928 if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice &&
932 bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
933 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
934 if (!InstrumentRegions && !PGOReader)
941 if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
942 if (
const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
950 CGM.ClearUnusedCoverageMapping(D);
951 if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
953 if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
963 mapRegionCounters(D);
964 if (CGM.getCodeGenOpts().CoverageMapping)
965 emitCounterRegionMapping(D);
968 computeRegionCounts(D);
969 applyFunctionAttributes(PGOReader, Fn);
973void CodeGenPGO::mapRegionCounters(
const Decl *D) {
977 uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
979 HashVersion = getPGOHashVersion(PGOReader, CGM);
980 ProfileVersion = PGOReader->getVersion();
992 unsigned MCDCMaxConditions =
996 RegionCounterMap.reset(
new llvm::DenseMap<const Stmt *, CounterPair>);
998 MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
999 *RegionMCDCState, MCDCMaxConditions, CGM.
getDiags());
1000 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
1002 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
1004 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
1005 Walker.TraverseDecl(
const_cast<BlockDecl *
>(BD));
1006 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
1008 assert(Walker.NextCounter > 0 &&
"no entry counter mapped for decl");
1009 NumRegionCounters = Walker.NextCounter;
1010 FunctionHash = Walker.Hash.finalize();
1012 FunctionHash &= llvm::NamedInstrProfRecord::FUNC_HASH_MASK;
1015bool CodeGenPGO::skipRegionMappingForDecl(
const Decl *D) {
1025 !D->
hasAttr<CUDAGlobalAttr>()) ||
1027 (D->
hasAttr<CUDAGlobalAttr>() ||
1028 (!D->
hasAttr<CUDAHostAttr>() && D->
hasAttr<CUDADeviceAttr>())))))
1037void CodeGenPGO::emitCounterRegionMapping(
const Decl *D) {
1038 if (skipRegionMappingForDecl(D))
1041 std::string CoverageMapping;
1042 llvm::raw_string_ostream
OS(CoverageMapping);
1043 RegionMCDCState->BranchByStmt.clear();
1044 CoverageMappingGen MappingGen(
1045 *CGM.getCoverageMapping(), CGM.getContext().getSourceManager(),
1046 CGM.getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1047 MappingGen.emitCounterMapping(D, OS);
1049 if (CoverageMapping.empty())
1053 unsigned MaxNumCounters = NumRegionCounters;
1054 for (
const auto &[_,
V] : *RegionCounterMap) {
1055 assert((!
V.Executed.hasValue() || MaxNumCounters >
V.Executed) &&
1056 "TrueCnt should not be reassigned");
1057 if (
V.Skipped.hasValue())
1058 MaxNumCounters = std::max(MaxNumCounters,
V.Skipped + 1);
1060 NumRegionCounters = MaxNumCounters;
1062 CGM.getCoverageMapping()->addFunctionMappingRecord(
1063 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1068 llvm::GlobalValue::LinkageTypes
Linkage) {
1069 if (skipRegionMappingForDecl(D))
1072 std::string CoverageMapping;
1073 llvm::raw_string_ostream OS(CoverageMapping);
1075 CGM.getContext().getSourceManager(),
1079 if (CoverageMapping.empty())
1083 CGM.getCoverageMapping()->addFunctionMappingRecord(
1084 FuncNameVar, FuncName, FunctionHash, CoverageMapping,
false);
1087void CodeGenPGO::computeRegionCounts(
const Decl *D) {
1088 StmtCountMap.reset(
new llvm::DenseMap<const Stmt *, uint64_t>);
1089 ComputeRegionCounts Walker(*StmtCountMap, *
this);
1090 if (
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
1091 Walker.VisitFunctionDecl(FD);
1092 else if (
const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
1093 Walker.VisitObjCMethodDecl(MD);
1094 else if (
const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
1095 Walker.VisitBlockDecl(BD);
1096 else if (
const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
1097 Walker.VisitCapturedDecl(
const_cast<CapturedDecl *
>(CD));
1101CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1102 llvm::Function *Fn) {
1107 Fn->setEntryCount(FunctionCount);
1111 if (!RegionCounterMap)
1114 auto I = RegionCounterMap->find(S);
1115 if (I == RegionCounterMap->end())
1118 return I->second.Skipped.hasValue();
1122 bool UseSkipPath,
bool UseBoth,
1123 llvm::Value *StepV) {
1124 if (!RegionCounterMap)
1128 const auto &TheCounterPair = (*RegionCounterMap)[S];
1130 if (!Builder.GetInsertBlock())
1134 (UseSkipPath ? TheCounterPair.Skipped : TheCounterPair.Executed);
1140 auto *NormalizedFuncNameVarPtr =
1141 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1142 FuncNameVar, llvm::PointerType::get(CGM.getLLVMContext(), 0));
1144 llvm::Value *Args[] = {
1145 NormalizedFuncNameVarPtr, Builder.getInt64(FunctionHash),
1146 Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV};
1149 assert(!StepV &&
"StepV is not supported in single byte counter mode");
1150 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover),
1153 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
1157 CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
1160bool CodeGenPGO::canEmitMCDCCoverage(
const CGBuilderTy &Builder) {
1166 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1169 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1174 llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1175 Builder.getInt64(FunctionHash),
1176 Builder.getInt32(RegionMCDCState->BitmapBits)};
1178 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
1182std::vector<Address *>
1184 std::vector<Address *>
Result;
1186 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1190 for (
auto &[_,
V] : RegionMCDCState->DecisionByStmt)
1192 SortedPair.emplace_back(
V.ID, &
V.MCDCCondBitmapAddr);
1194 llvm::sort(SortedPair);
1196 for (
auto &[_, MCDCCondBitmapAddr] : SortedPair)
1197 Result.push_back(MCDCCondBitmapAddr);
1205 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1210 auto DecisionStateIter = RegionMCDCState->DecisionByStmt.find(S);
1211 if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
1214 auto &MCDCCondBitmapAddr = DecisionStateIter->second.MCDCCondBitmapAddr;
1215 if (!MCDCCondBitmapAddr.isValid())
1220 if (DecisionStateIter->second.Indices.size() == 0)
1224 unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
1225 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1232 llvm::Value *Args[4] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1233 Builder.getInt64(FunctionHash),
1234 Builder.getInt32(MCDCTestVectorBitmapOffset),
1235 MCDCCondBitmapAddr.emitRawPointer(CGF)};
1237 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
1241 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1244 auto I = RegionMCDCState->DecisionByStmt.find(S->
IgnoreParens());
1245 if (I == RegionMCDCState->DecisionByStmt.end())
1248 auto &MCDCCondBitmapAddr = I->second.MCDCCondBitmapAddr;
1249 if (!MCDCCondBitmapAddr.isValid())
1253 Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr);
1259 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1271 auto BranchStateIter = RegionMCDCState->BranchByStmt.find(S);
1272 if (BranchStateIter == RegionMCDCState->BranchByStmt.end())
1276 const auto &Branch = BranchStateIter->second;
1277 assert(Branch.ID >= 0 &&
"Condition has no ID!");
1278 assert(Branch.DecisionStmt);
1281 const auto DecisionIter =
1282 RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
1283 if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
1286 auto &MCDCCondBitmapAddr = DecisionIter->second.MCDCCondBitmapAddr;
1287 if (!MCDCCondBitmapAddr.isValid())
1290 const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
1292 auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
1293 "mcdc." + Twine(Branch.ID + 1) +
".cur");
1294 auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
true]));
1295 NewTV = Builder.CreateSelect(
1296 Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
false])));
1297 Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
1301 if (CGM.getCodeGenOpts().hasProfileClangInstr())
1302 M.addModuleFlag(llvm::Module::Warning,
"EnableValueProfiling",
1307 if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
1309 const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1310 llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
1311 uint64_t ProfileVersion =
1312 (INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);
1314 auto IRLevelVersionVariable =
new llvm::GlobalVariable(
1315 M, IntTy64,
true, llvm::GlobalValue::WeakAnyLinkage,
1316 llvm::Constant::getIntegerValue(IntTy64,
1317 llvm::APInt(64, ProfileVersion)),
1320 IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1321 llvm::Triple TT(M.getTargetTriple());
1323 IRLevelVersionVariable->setVisibility(
1324 llvm::GlobalValue::ProtectedVisibility);
1325 if (TT.supportsCOMDAT()) {
1326 IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
1327 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
1329 IRLevelVersionVariable->setDSOLocal(
true);
1336 llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
1341 if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
1347 bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
1348 if (InstrumentValueSites && RegionCounterMap) {
1349 auto BuilderInsertPoint = Builder.saveIP();
1350 Builder.SetInsertPoint(ValueSite);
1351 llvm::Value *Args[5] = {
1353 Builder.getInt64(FunctionHash),
1354 Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1355 Builder.getInt32(ValueKind),
1356 Builder.getInt32(NumValueSites[ValueKind]++)
1359 CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1360 Builder.restoreIP(BuilderInsertPoint);
1364 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1372 if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1375 llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
1376 (llvm::InstrProfValueKind)ValueKind,
1377 NumValueSites[ValueKind]);
1379 NumValueSites[ValueKind]++;
1383void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
1384 bool IsInMainFile) {
1386 RegionCounts.clear();
1387 auto RecordExpected = PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1388 if (
auto E = RecordExpected.takeError()) {
1389 auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(E)));
1390 if (IPE == llvm::instrprof_error::unknown_function)
1392 else if (IPE == llvm::instrprof_error::hash_mismatch)
1394 else if (IPE == llvm::instrprof_error::malformed)
1400 std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1401 RegionCounts = ProfRecord->Counts;
1409 return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
1422 assert(Scale &&
"scale by 0?");
1423 uint64_t Scaled = Weight / Scale + 1;
1424 assert(Scaled <= UINT32_MAX &&
"overflow 32-bits");
1428llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1429 uint64_t FalseCount)
const {
1431 if (!TrueCount && !FalseCount)
1437 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
1443CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights)
const {
1445 if (Weights.size() < 2)
1449 uint64_t MaxWeight = *llvm::max_element(Weights);
1456 SmallVector<uint32_t, 16> ScaledWeights;
1457 ScaledWeights.reserve(Weights.size());
1458 for (uint64_t W : Weights)
1461 llvm::MDBuilder MDHelper(
CGM.getLLVMContext());
1462 return MDHelper.createBranchWeights(ScaledWeights);
1466CodeGenFunction::createProfileWeightsForLoop(
const Stmt *
Cond,
1467 uint64_t LoopCount)
const {
1468 if (!PGO->haveRegionCounts())
1470 std::optional<uint64_t> CondCount = PGO->getStmtCount(
Cond);
1471 if (!CondCount || *CondCount == 0)
1473 return createProfileWeights(LoopCount,
1474 std::max(*CondCount, LoopCount) - LoopCount);
1478 const Stmt *S,
bool UseBoth,
1479 llvm::Value *StepV) {
1480 if (
CGM.getCodeGenOpts().hasProfileClangInstr() &&
1481 !
CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
1482 !
CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) {
1487 PGO->setCurrentStmt(S);
1491 return PGO->hasSkipCounter(S);
1494 PGO->markStmtAsUsed(Skipped, S);
1497 PGO->markStmtMaybeUsed(S);
1502 PGO->emitMCDCParameters(
Builder);
1506 for (
auto *MCDCCondBitmapAddr : PGO->getMCDCCondBitmapAddrArray(
Builder))
1507 *MCDCCondBitmapAddr =
1512 return PGO->isMCDCDecisionExpr(E);
1515 return PGO->isMCDCBranchExpr(E);
1519 PGO->emitMCDCCondBitmapReset(
Builder, E);
1520 PGO->setCurrentStmt(E);
1525 PGO->emitMCDCTestVectorBitmapUpdate(
Builder, E, *
this);
1526 PGO->setCurrentStmt(E);
1533 PGO->emitMCDCCondBitmapUpdate(
Builder, E, Val, *
this);
1534 PGO->setCurrentStmt(E);
1539 return PGO->getStmtCount(S).value_or(0);
1544 PGO->setCurrentRegionCount(Count);
1550 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)
The JSON file list parser is used to communicate input to InstallAPI.
@ Ctor_Base
Base object ctor.
bool isa(CodeGen::Address addr)
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ Result
The result type of a method or function.
@ Dtor_Base
Base object dtor.
@ Type
The name was classified as a type.
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
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
Per-Function MC/DC state.
llvm::DenseMap< const Stmt *, Decision > DecisionByStmt