llvm::cl::opt<bool>
31llvm::cl::desc(
"Enable value profiling"),
32llvm::cl::Hidden, llvm::cl::init(
false));
34using namespace clang;
35using namespaceCodeGen;
37voidCodeGenPGO::setFuncName(StringRef Name,
38llvm::GlobalValue::LinkageTypes
Linkage) {
39llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
40FuncName = llvm::getPGOFuncName(
42PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
46FuncNameVar = llvm::createPGOFuncNameVar(CGM.
getModule(),
Linkage, FuncName);
49voidCodeGenPGO::setFuncName(llvm::Function *Fn) {
50setFuncName(
Fn->getName(),
Fn->getLinkage());
52llvm::createPGOFuncNameMetadata(*Fn, FuncName);
82 static const intNumBitsPerType = 6;
83 static const unsignedNumTypesPerWord =
sizeof(
uint64_t) * 8 / NumBitsPerType;
84 static const unsignedTooBig = 1u << NumBitsPerType;
94 enumHashType :
unsigned char{
135 static_assert(LastHashType <= TooBig,
"Too many types in HashType");
138: Working(0), Count(0), HashVersion(HashVersion) {}
139 voidcombine(HashType
Type);
143const intPGOHash::NumBitsPerType;
144const unsignedPGOHash::NumTypesPerWord;
145const unsignedPGOHash::TooBig;
148static PGOHashVersiongetPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
150 if(PGOReader->getVersion() <= 4)
152 if(PGOReader->getVersion() <= 5)
162 unsignedNextCounter;
166llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
170 unsignedMCDCMaxCond;
176MapRegionCounters(
PGOHashVersionHashVersion, uint64_t ProfileVersion,
177llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
180: NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
181MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
182ProfileVersion(ProfileVersion),
Diag(
Diag) {}
186 boolTraverseBlockExpr(
BlockExpr*BE) {
return true; }
189 for(
auto C: zip(
LE->captures(),
LE->capture_inits()))
190TraverseLambdaCapture(LE, &std::get<0>(
C), std::get<1>(
C));
193 boolTraverseCapturedStmt(
CapturedStmt*CS) {
return true; }
195 boolVisitDecl(
const Decl*
D) {
200 caseDecl::CXXMethod:
201 caseDecl::CXXConstructor:
202 caseDecl::CXXDestructor:
203 caseDecl::CXXConversion:
204 caseDecl::ObjCMethod:
207CounterMap[
D->
getBody()] = NextCounter++;
215PGOHash::HashType updateCounterMappings(
Stmt*S) {
217 if(
Type!= PGOHash::None)
218CounterMap[S] = NextCounter++;
231 unsignedNumCond = 0;
232 boolSplitNestedLogicalOp =
false;
237 booldataTraverseStmtPre(
Stmt*S) {
239 if(MCDCMaxCond == 0)
244 if(LogOpStack.empty()) {
246SplitNestedLogicalOp =
false;
249 if(
const Expr*
E= dyn_cast<Expr>(S)) {
259SplitNestedLogicalOp = SplitNestedLogicalOp || !NonLogOpStack.empty();
261LogOpStack.push_back(BinOp);
268 if(!LogOpStack.empty())
269NonLogOpStack.push_back(S);
277 booldataTraverseStmtPost(
Stmt*S) {
279 if(MCDCMaxCond == 0)
282 if(
const Expr*
E= dyn_cast<Expr>(S)) {
285assert(LogOpStack.back() == BinOp);
286LogOpStack.pop_back();
289 if(LogOpStack.empty()) {
291 if(SplitNestedLogicalOp) {
292 unsignedDiagID =
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 unsignedDiagID =
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())
320NonLogOpStack.pop_back();
331 if(S->isLogicalOp()) {
332 if(CodeGenFunction::isInstrumentedCondition(S->getLHS()))
335 if(CodeGenFunction::isInstrumentedCondition(S->getRHS())) {
336 if(ProfileVersion >= llvm::IndexedInstrProf::Version7)
337CounterMap[S->getRHS()] = NextCounter++;
342 returnBase::VisitBinaryOperator(S);
347CounterMap[S->getTrueExpr()] = NextCounter++;
349CounterMap[S->getFalseExpr()] = NextCounter++;
350 returnBase::VisitConditionalOperator(S);
354 boolVisitStmt(
Stmt*S) {
355 auto Type= updateCounterMappings(S);
357 Type= getHashType(Hash.getHashVersion(), S);
358 if(
Type!= PGOHash::None)
359Hash.combine(
Type);
363 boolTraverseIfStmt(
IfStmt*
If) {
366 returnBase::TraverseIfStmt(
If);
371 for(
Stmt*CS :
If->children()) {
372 if(!CS || NoSingleByteCoverage)
374 if(CS ==
If->getThen())
375CounterMap[
If->getThen()] = NextCounter++;
376 else if(CS ==
If->getElse())
377CounterMap[
If->getElse()] = NextCounter++;
383 for(
Stmt*CS :
If->children()) {
386 if(CS ==
If->getThen())
387Hash.combine(PGOHash::IfThenBranch);
388 else if(CS ==
If->getElse())
389Hash.combine(PGOHash::IfElseBranch);
392Hash.combine(PGOHash::EndOfScope);
396 boolTraverseWhileStmt(
WhileStmt*While) {
401 if(!CS || NoSingleByteCoverage)
404CounterMap[While->
getCond()] = NextCounter++;
405 else if(CS == While->
getBody())
406CounterMap[While->
getBody()] = NextCounter++;
409Base::TraverseWhileStmt(While);
411Hash.combine(PGOHash::EndOfScope);
415 boolTraverseDoStmt(
DoStmt*Do) {
420 if(!CS || NoSingleByteCoverage)
423CounterMap[Do->
getCond()] = NextCounter++;
424 else if(CS == Do->
getBody())
425CounterMap[Do->
getBody()] = NextCounter++;
428Base::TraverseDoStmt(Do);
430Hash.combine(PGOHash::EndOfScope);
434 boolTraverseForStmt(
ForStmt*For) {
439 if(!CS || NoSingleByteCoverage)
442CounterMap[For->
getCond()] = NextCounter++;
443 else if(CS == For->
getInc())
444CounterMap[For->
getInc()] = NextCounter++;
445 else if(CS == For->
getBody())
446CounterMap[For->
getBody()] = NextCounter++;
449Base::TraverseForStmt(For);
451Hash.combine(PGOHash::EndOfScope);
459 if(!CS || NoSingleByteCoverage)
461 if(CS == ForRange->
getBody())
462CounterMap[ForRange->
getBody()] = NextCounter++;
465Base::TraverseCXXForRangeStmt(ForRange);
467Hash.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 caseStmt::LabelStmtClass:
492 returnPGOHash::LabelStmt;
493 caseStmt::WhileStmtClass:
494 returnPGOHash::WhileStmt;
495 caseStmt::DoStmtClass:
496 returnPGOHash::DoStmt;
497 caseStmt::ForStmtClass:
498 returnPGOHash::ForStmt;
499 caseStmt::CXXForRangeStmtClass:
500 returnPGOHash::CXXForRangeStmt;
501 caseStmt::ObjCForCollectionStmtClass:
502 returnPGOHash::ObjCForCollectionStmt;
503 caseStmt::SwitchStmtClass:
504 returnPGOHash::SwitchStmt;
505 caseStmt::CaseStmtClass:
506 returnPGOHash::CaseStmt;
507 caseStmt::DefaultStmtClass:
508 returnPGOHash::DefaultStmt;
509 caseStmt::IfStmtClass:
510 returnPGOHash::IfStmt;
511 caseStmt::CXXTryStmtClass:
512 returnPGOHash::CXXTryStmt;
513 caseStmt::CXXCatchStmtClass:
514 returnPGOHash::CXXCatchStmt;
515 caseStmt::ConditionalOperatorClass:
516 returnPGOHash::ConditionalOperator;
517 caseStmt::BinaryConditionalOperatorClass:
518 returnPGOHash::BinaryConditionalOperator;
519 caseStmt::BinaryOperatorClass: {
522 returnPGOHash::BinaryOperatorLAnd;
524 returnPGOHash::BinaryOperatorLOr;
530 returnPGOHash::BinaryOperatorLT;
532 returnPGOHash::BinaryOperatorGT;
534 returnPGOHash::BinaryOperatorLE;
536 returnPGOHash::BinaryOperatorGE;
538 returnPGOHash::BinaryOperatorEQ;
540 returnPGOHash::BinaryOperatorNE;
548 switch(S->getStmtClass()) {
551 caseStmt::GotoStmtClass:
552 returnPGOHash::GotoStmt;
553 caseStmt::IndirectGotoStmtClass:
554 returnPGOHash::IndirectGotoStmt;
555 caseStmt::BreakStmtClass:
556 returnPGOHash::BreakStmt;
557 caseStmt::ContinueStmtClass:
558 returnPGOHash::ContinueStmt;
559 caseStmt::ReturnStmtClass:
560 returnPGOHash::ReturnStmt;
561 caseStmt::CXXThrowExprClass:
562 returnPGOHash::ThrowExpr;
563 caseStmt::UnaryOperatorClass: {
566 returnPGOHash::UnaryOperatorLNot;
572 returnPGOHash::None;
584 boolRecordNextStmtCount;
590llvm::DenseMap<const Stmt *, uint64_t> &
CountMap;
593 structBreakContinue {
596BreakContinue() =
default;
600ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &
CountMap,
604 voidRecordStmtCount(
const Stmt*S) {
605 if(RecordNextStmtCount) {
607RecordNextStmtCount =
false;
613CurrentCount = Count;
617 voidVisitStmt(
const Stmt*S) {
619 for(
const Stmt*Child : S->children())
634 voidVisitLambdaExpr(
const LambdaExpr*LE) {}
659 if(S->getRetValue())
660Visit(S->getRetValue());
662RecordNextStmtCount =
true;
666RecordStmtCount(
E);
667 if(
E->getSubExpr())
668Visit(
E->getSubExpr());
670RecordNextStmtCount =
true;
673 voidVisitGotoStmt(
const GotoStmt*S) {
676RecordNextStmtCount =
true;
679 voidVisitLabelStmt(
const LabelStmt*S) {
680RecordNextStmtCount =
false;
684Visit(S->getSubStmt());
687 voidVisitBreakStmt(
const BreakStmt*S) {
689assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
690BreakContinueStack.back().BreakCount += CurrentCount;
692RecordNextStmtCount =
true;
697assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
698BreakContinueStack.back().ContinueCount += CurrentCount;
700RecordNextStmtCount =
true;
703 voidVisitWhileStmt(
const WhileStmt*S) {
705 uint64_tParentCount = CurrentCount;
707BreakContinueStack.push_back(BreakContinue());
711 CountMap[S->getBody()] = CurrentCount;
713 uint64_tBackedgeCount = CurrentCount;
719BreakContinue BC = BreakContinueStack.pop_back_val();
721setCount(ParentCount + BackedgeCount + BC.ContinueCount);
722 CountMap[S->getCond()] = CondCount;
724setCount(BC.BreakCount + CondCount - BodyCount);
725RecordNextStmtCount =
true;
728 voidVisitDoStmt(
const DoStmt*S) {
732BreakContinueStack.push_back(BreakContinue());
734 uint64_tBodyCount = setCount(LoopCount + CurrentCount);
735 CountMap[S->getBody()] = BodyCount;
737 uint64_tBackedgeCount = CurrentCount;
739BreakContinue BC = BreakContinueStack.pop_back_val();
742 uint64_tCondCount = setCount(BackedgeCount + BC.ContinueCount);
743 CountMap[S->getCond()] = CondCount;
745setCount(BC.BreakCount + CondCount - LoopCount);
746RecordNextStmtCount =
true;
749 voidVisitForStmt(
const ForStmt*S) {
754 uint64_tParentCount = CurrentCount;
756BreakContinueStack.push_back(BreakContinue());
760 CountMap[S->getBody()] = BodyCount;
762 uint64_tBackedgeCount = CurrentCount;
763BreakContinue BC = BreakContinueStack.pop_back_val();
768 uint64_tIncCount = setCount(BackedgeCount + BC.ContinueCount);
775setCount(ParentCount + BackedgeCount + BC.ContinueCount);
777 CountMap[S->getCond()] = CondCount;
780setCount(BC.BreakCount + CondCount - BodyCount);
781RecordNextStmtCount =
true;
788Visit(S->getLoopVarStmt());
789Visit(S->getRangeStmt());
790Visit(S->getBeginStmt());
791Visit(S->getEndStmt());
793 uint64_tParentCount = CurrentCount;
794BreakContinueStack.push_back(BreakContinue());
798 CountMap[S->getBody()] = BodyCount;
800 uint64_tBackedgeCount = CurrentCount;
801BreakContinue BC = BreakContinueStack.pop_back_val();
805 uint64_tIncCount = setCount(BackedgeCount + BC.ContinueCount);
811setCount(ParentCount + BackedgeCount + BC.ContinueCount);
812 CountMap[S->getCond()] = CondCount;
814setCount(BC.BreakCount + CondCount - BodyCount);
815RecordNextStmtCount =
true;
820Visit(S->getElement());
821 uint64_tParentCount = CurrentCount;
822BreakContinueStack.push_back(BreakContinue());
825 CountMap[S->getBody()] = BodyCount;
827 uint64_tBackedgeCount = CurrentCount;
828BreakContinue BC = BreakContinueStack.pop_back_val();
830setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
832RecordNextStmtCount =
true;
841BreakContinueStack.push_back(BreakContinue());
844BreakContinue BC = BreakContinueStack.pop_back_val();
845 if(!BreakContinueStack.empty())
846BreakContinueStack.back().ContinueCount += BC.ContinueCount;
849RecordNextStmtCount =
true;
853RecordNextStmtCount =
false;
858setCount(CurrentCount + CaseCount);
862RecordNextStmtCount =
true;
863Visit(S->getSubStmt());
866 voidVisitIfStmt(
const IfStmt*S) {
869 if(S->isConsteval()) {
870 const Stmt*Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse();
876 uint64_tParentCount = CurrentCount;
884 CountMap[S->getThen()] = ThenCount;
888 uint64_tElseCount = ParentCount - ThenCount;
891 CountMap[S->getElse()] = ElseCount;
893OutCount += CurrentCount;
895OutCount += ElseCount;
897RecordNextStmtCount =
true;
902Visit(S->getTryBlock());
903 for(
unsignedI = 0,
E= S->getNumHandlers(); I <
E; ++I)
904Visit(S->getHandler(I));
907RecordNextStmtCount =
true;
911RecordNextStmtCount =
false;
915Visit(S->getHandlerBlock());
919RecordStmtCount(
E);
920 uint64_tParentCount = CurrentCount;
921Visit(
E->getCond());
926 CountMap[
E->getTrueExpr()] = TrueCount;
927Visit(
E->getTrueExpr());
930 uint64_tFalseCount = setCount(ParentCount - TrueCount);
931 CountMap[
E->getFalseExpr()] = FalseCount;
932Visit(
E->getFalseExpr());
933OutCount += CurrentCount;
936RecordNextStmtCount =
true;
940RecordStmtCount(
E);
941 uint64_tParentCount = CurrentCount;
942Visit(
E->getLHS());
946Visit(
E->getRHS());
947setCount(ParentCount + RHSCount - CurrentCount);
948RecordNextStmtCount =
true;
952RecordStmtCount(
E);
953 uint64_tParentCount = CurrentCount;
954Visit(
E->getLHS());
958Visit(
E->getRHS());
959setCount(ParentCount + RHSCount - CurrentCount);
960RecordNextStmtCount =
true;
965voidPGOHash::combine(HashType
Type) {
967assert(
Type&&
"Hash is invalid: unexpected type 0");
968assert(
unsigned(
Type) < TooBig &&
"Hash is invalid: too many types");
971 if(Count && Count % NumTypesPerWord == 0) {
972 using namespacellvm::support;
974endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
975MD5.update(
llvm::ArrayRef((uint8_t *)&Swapped,
sizeof(Swapped)));
981Working = Working << NumBitsPerType |
Type;
986 if(Count <= NumTypesPerWord)
997MD5.update({(uint8_t)Working});
999 using namespacellvm::support;
1001endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
1002MD5.update(
llvm::ArrayRef((uint8_t *)&Swapped,
sizeof(Swapped)));
1007llvm::MD5::MD5Result
Result;
1023llvm::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))
1053mapRegionCounters(
D);
1055emitCounterRegionMapping(
D);
1057loadRegionCounts(PGOReader,
SM.isInMainFile(
D->
getLocation()));
1058computeRegionCounts(
D);
1059applyFunctionAttributes(PGOReader, Fn);
1063voidCodeGenPGO::mapRegionCounters(
const Decl*
D) {
1067uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
1069HashVersion = getPGOHashVersion(PGOReader, CGM);
1070ProfileVersion = PGOReader->getVersion();
1082 unsignedMCDCMaxConditions =
1086RegionCounterMap.reset(
newllvm::DenseMap<const Stmt *, CounterPair>);
1088MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
1089*RegionMCDCState, MCDCMaxConditions, CGM.
getDiags());
1090 if(
const FunctionDecl*FD = dyn_cast_or_null<FunctionDecl>(
D))
1091Walker.TraverseDecl(
const_cast<FunctionDecl*
>(FD));
1092 else if(
const ObjCMethodDecl*MD = dyn_cast_or_null<ObjCMethodDecl>(
D))
1094 else if(
const BlockDecl*BD = dyn_cast_or_null<BlockDecl>(
D))
1095Walker.TraverseDecl(
const_cast<BlockDecl*
>(BD));
1096 else if(
const CapturedDecl*CD = dyn_cast_or_null<CapturedDecl>(
D))
1097Walker.TraverseDecl(
const_cast<CapturedDecl*
>(CD));
1098assert(Walker.NextCounter > 0 &&
"no entry counter mapped for decl");
1099NumRegionCounters = Walker.NextCounter;
1100FunctionHash = Walker.Hash.finalize();
1103boolCodeGenPGO::skipRegionMappingForDecl(
const Decl*
D) {
1113!
D->
hasAttr<CUDAGlobalAttr>()) ||
1115(
D->
hasAttr<CUDAGlobalAttr>() ||
1125voidCodeGenPGO::emitCounterRegionMapping(
const Decl*
D) {
1126 if(skipRegionMappingForDecl(
D))
1129std::string CoverageMapping;
1130llvm::raw_string_ostream OS(CoverageMapping);
1131RegionMCDCState->BranchByStmt.clear();
1134CGM.
getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1135MappingGen.emitCounterMapping(
D, OS);
1137 if(CoverageMapping.empty())
1141FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1146llvm::GlobalValue::LinkageTypes
Linkage) {
1147 if(skipRegionMappingForDecl(
D))
1150std::string CoverageMapping;
1151llvm::raw_string_ostream OS(CoverageMapping);
1157 if(CoverageMapping.empty())
1162FuncNameVar, FuncName, FunctionHash, CoverageMapping,
false);
1165voidCodeGenPGO::computeRegionCounts(
const Decl*
D) {
1166StmtCountMap.reset(
newllvm::DenseMap<const Stmt *, uint64_t>);
1167ComputeRegionCounts Walker(*StmtCountMap, *
this);
1168 if(
const FunctionDecl*FD = dyn_cast_or_null<FunctionDecl>(
D))
1169Walker.VisitFunctionDecl(FD);
1170 else if(
const ObjCMethodDecl*MD = dyn_cast_or_null<ObjCMethodDecl>(
D))
1171Walker.VisitObjCMethodDecl(MD);
1172 else if(
const BlockDecl*BD = dyn_cast_or_null<BlockDecl>(
D))
1173Walker.VisitBlockDecl(BD);
1174 else if(
const CapturedDecl*CD = dyn_cast_or_null<CapturedDecl>(
D))
1175Walker.VisitCapturedDecl(
const_cast<CapturedDecl*
>(CD));
1179CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1180llvm::Function *Fn) {
1185Fn->setEntryCount(FunctionCount);
1189 if(!RegionCounterMap)
1190 return{
false,
false};
1192 autoI = RegionCounterMap->find(S);
1193 if(I == RegionCounterMap->end())
1194 return{
false,
false};
1196 return{I->second.Executed.hasValue(), I->second.Skipped.hasValue()};
1200llvm::Value *StepV) {
1201 if(!RegionCounterMap || !Builder.GetInsertBlock())
1204 unsignedCounter = (*RegionCounterMap)[S].Executed;
1208 auto*NormalizedFuncNameVarPtr =
1209llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1212llvm::Value *Args[] = {
1213NormalizedFuncNameVarPtr, Builder.getInt64(FunctionHash),
1214Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV};
1217Builder.CreateCall(CGM.
getIntrinsic(llvm::Intrinsic::instrprof_cover),
1220Builder.CreateCall(CGM.
getIntrinsic(llvm::Intrinsic::instrprof_increment),
1224CGM.
getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
1227boolCodeGenPGO::canEmitMCDCCoverage(
const CGBuilderTy&Builder) {
1229CGM.
getCodeGenOpts().MCDCCoverage && Builder.GetInsertBlock());
1233 if(!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1236 auto*I8PtrTy = llvm::PointerType::getUnqual(CGM.
getLLVMContext());
1241llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1242Builder.getInt64(FunctionHash),
1243Builder.getInt32(RegionMCDCState->BitmapBits)};
1245CGM.
getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
1252 if(!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1255S = S->IgnoreParens();
1257 autoDecisionStateIter = RegionMCDCState->DecisionByStmt.find(S);
1258 if(DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
1263 if(DecisionStateIter->second.Indices.size() == 0)
1267 unsignedMCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
1268 auto*I8PtrTy = llvm::PointerType::getUnqual(CGM.
getLLVMContext());
1275llvm::Value *Args[4] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1276Builder.getInt64(FunctionHash),
1277Builder.getInt32(MCDCTestVectorBitmapOffset),
1280CGM.
getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
1285 if(!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1288S = S->IgnoreParens();
1290 if(!RegionMCDCState->DecisionByStmt.contains(S))
1294Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr);
1301 if(!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1313 autoBranchStateIter = RegionMCDCState->BranchByStmt.find(S);
1314 if(BranchStateIter == RegionMCDCState->BranchByStmt.end())
1318 const auto&Branch = BranchStateIter->second;
1319assert(Branch.ID >= 0 &&
"Condition has no ID!");
1320assert(Branch.DecisionStmt);
1323 const autoDecisionIter =
1324RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
1325 if(DecisionIter == RegionMCDCState->DecisionByStmt.end())
1328 const auto&TVIdxs = DecisionIter->second.Indices[Branch.ID];
1330 auto*CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
1331 "mcdc."+ Twine(Branch.ID + 1) +
".cur");
1332 auto*NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
true]));
1333NewTV = Builder.CreateSelect(
1334Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[
false])));
1335Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
1340M.addModuleFlag(llvm::Module::Warning,
"EnableValueProfiling",
1347 constStringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1348llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
1349uint64_t ProfileVersion =
1350(INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);
1352 autoIRLevelVersionVariable =
newllvm::GlobalVariable(
1353M, IntTy64,
true, llvm::GlobalValue::WeakAnyLinkage,
1354llvm::Constant::getIntegerValue(IntTy64,
1355llvm::APInt(64, ProfileVersion)),
1358IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1359llvm::Triple TT(M.getTargetTriple());
1360 if(TT.supportsCOMDAT()) {
1361IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
1362IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
1364IRLevelVersionVariable->setDSOLocal(
true);
1371llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
1376 if(!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
1379 if(isa<llvm::Constant>(ValuePtr))
1383 if(InstrumentValueSites && RegionCounterMap) {
1384 autoBuilderInsertPoint = Builder.saveIP();
1385Builder.SetInsertPoint(ValueSite);
1386llvm::Value *Args[5] = {
1388Builder.getInt64(FunctionHash),
1389Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1390Builder.getInt32(ValueKind),
1391Builder.getInt32(NumValueSites[ValueKind]++)
1394CGM.
getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1395Builder.restoreIP(BuilderInsertPoint);
1399llvm::IndexedInstrProfReader *PGOReader = CGM.
getPGOReader();
1407 if(NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1410llvm::annotateValueSite(CGM.
getModule(), *ValueSite, *ProfRecord,
1411(llvm::InstrProfValueKind)ValueKind,
1412NumValueSites[ValueKind]);
1414NumValueSites[ValueKind]++;
1418voidCodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
1419 boolIsInMainFile) {
1421RegionCounts.clear();
1423PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1424 if(
auto E= RecordExpected.takeError()) {
1425 autoIPE = std::get<0>(llvm::InstrProfError::take(std::move(
E)));
1426 if(IPE == llvm::instrprof_error::unknown_function)
1428 else if(IPE == llvm::instrprof_error::hash_mismatch)
1430 else if(IPE == llvm::instrprof_error::malformed)
1436std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1437RegionCounts = ProfRecord->Counts;
1445 returnMaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
1458assert(Scale &&
"scale by 0?");
1459uint64_t Scaled = Weight / Scale + 1;
1460assert(Scaled <= UINT32_MAX &&
"overflow 32-bits");
1464llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1465uint64_t FalseCount)
const{
1467 if(!TrueCount && !FalseCount)
1481 if(Weights.size() < 2)
1485 uint64_tMaxWeight = *std::max_element(Weights.begin(), Weights.end());
1493ScaledWeights.reserve(Weights.size());
1494 for(uint64_t W : Weights)
1498 returnMDHelper.createBranchWeights(ScaledWeights);
1502CodeGenFunction::createProfileWeightsForLoop(
const Stmt*Cond,
1503uint64_t LoopCount)
const{
1506std::optional<uint64_t> CondCount = PGO.
getStmtCount(Cond);
1507 if(!CondCount || *CondCount == 0)
1509 returncreateProfileWeights(LoopCount,
1510std::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::pair< bool, bool > getIsCounterPair(const Stmt *S) const
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
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4