clang: lib/CodeGen/CodeGenPGO.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
18#include "llvm/IR/Intrinsics.h"
19#include "llvm/IR/MDBuilder.h"
20#include "llvm/Support/CommandLine.h"
21#include "llvm/Support/Endian.h"
22#include "llvm/Support/MD5.h"
23#include
24
25namespace llvm {
27}
28
29static llvm:🆑:opt
31 llvm:🆑:desc("Enable value profiling"),
32 llvm:🆑:Hidden, llvm:🆑:init(false));
33
34using namespace clang;
35using namespace CodeGen;
36
37void CodeGenPGO::setFuncName(StringRef Name,
38 llvm::GlobalValue::LinkageTypes Linkage) {
39 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
40 FuncName = llvm::getPGOFuncName(
42 PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
43
44
46 FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
47}
48
49void CodeGenPGO::setFuncName(llvm::Function *Fn) {
50 setFuncName(Fn->getName(), Fn->getLinkage());
51
52 llvm::createPGOFuncNameMetadata(*Fn, FuncName);
53}
54
55
60
61
64
65namespace {
66
67
68
69
70
71
72
73
74
75
76class PGOHash {
78 unsigned Count;
80 llvm::MD5 MD5;
81
82 static const int NumBitsPerType = 6;
83 static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
84 static const unsigned TooBig = 1u << NumBitsPerType;
85
86public:
87
88
89
90
91
92
93
94 enum HashType : unsigned char {
109 BinaryOperatorLAnd,
110 BinaryOperatorLOr,
112
113
114 EndOfScope,
115 IfThenBranch,
116 IfElseBranch,
122 ThrowExpr,
123 UnaryOperatorLNot,
124 BinaryOperatorLT,
125 BinaryOperatorGT,
126 BinaryOperatorLE,
127 BinaryOperatorGE,
128 BinaryOperatorEQ,
129 BinaryOperatorNE,
130
131
132
133 LastHashType
134 };
135 static_assert(LastHashType <= TooBig, "Too many types in HashType");
136
138 : Working(0), Count(0), HashVersion(HashVersion) {}
139 void combine(HashType Type);
141 PGOHashVersion getHashVersion() const { return HashVersion; }
142};
143const int PGOHash::NumBitsPerType;
144const unsigned PGOHash::NumTypesPerWord;
145const unsigned PGOHash::TooBig;
146
147
148static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
150 if (PGOReader->getVersion() <= 4)
152 if (PGOReader->getVersion() <= 5)
155}
156
157
158struct MapRegionCounters : public RecursiveASTVisitor {
160
161
162 unsigned NextCounter;
163
164 PGOHash Hash;
165
166 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
167
169
170 unsigned MCDCMaxCond;
171
173
175
176 MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
177 llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
178 MCDC::State &MCDCState, unsigned MCDCMaxCond,
180 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
181 MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
182 ProfileVersion(ProfileVersion), Diag(Diag) {}
183
184
185
186 bool TraverseBlockExpr(BlockExpr *BE) { return true; }
187 bool TraverseLambdaExpr(LambdaExpr *LE) {
188
189 for (auto C : zip(LE->captures(), LE->capture_inits()))
190 TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
191 return true;
192 }
193 bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
194
195 bool VisitDecl(const Decl *D) {
197 default:
198 break;
199 case Decl::Function:
200 case Decl::CXXMethod:
201 case Decl::CXXConstructor:
202 case Decl::CXXDestructor:
203 case Decl::CXXConversion:
204 case Decl::ObjCMethod:
205 case Decl::Block:
206 case Decl::Captured:
207 CounterMap[D->getBody()] = NextCounter++;
208 break;
209 }
210 return true;
211 }
212
213
214
215 PGOHash::HashType updateCounterMappings(Stmt *S) {
217 if (Type != PGOHash::None)
218 CounterMap[S] = NextCounter++;
220 }
221
222
223
224
225
226
227
228
229
230
231 unsigned NumCond = 0;
232 bool SplitNestedLogicalOp = false;
235
236
237 bool dataTraverseStmtPre(Stmt *S) {
238
239 if (MCDCMaxCond == 0)
240 return true;
241
242
243
244 if (LogOpStack.empty()) {
245 NumCond = 0;
246 SplitNestedLogicalOp = false;
247 }
248
249 if (const Expr *E = dyn_cast(S)) {
252
253
254
255
256
257
258
259 SplitNestedLogicalOp = SplitNestedLogicalOp || !NonLogOpStack.empty();
260
261 LogOpStack.push_back(BinOp);
262 return true;
263 }
264 }
265
266
267
268 if (!LogOpStack.empty())
269 NonLogOpStack.push_back(S);
270
271 return true;
272 }
273
274
275
276
277 bool dataTraverseStmtPost(Stmt *S) {
278
279 if (MCDCMaxCond == 0)
280 return true;
281
282 if (const Expr *E = dyn_cast(S)) {
285 assert(LogOpStack.back() == BinOp);
286 LogOpStack.pop_back();
287
288
289 if (LogOpStack.empty()) {
290
291 if (SplitNestedLogicalOp) {
292 unsigned DiagID = Diag.getCustomDiagID(
294 "unsupported MC/DC boolean expression; "
295 "contains an operation with a nested boolean expression. "
296 "Expression will not be covered");
297 Diag.Report(S->getBeginLoc(), DiagID);
298 return true;
299 }
300
301
302 if (NumCond > MCDCMaxCond) {
303 unsigned DiagID = Diag.getCustomDiagID(
305 "unsupported MC/DC boolean expression; "
306 "number of conditions (%0) exceeds max (%1). "
307 "Expression will not be covered");
308 Diag.Report(S->getBeginLoc(), DiagID) << NumCond << MCDCMaxCond;
309 return true;
310 }
311
312
314 }
315 return true;
316 }
317 }
318
319 if (!LogOpStack.empty())
320 NonLogOpStack.pop_back();
321
322 return true;
323 }
324
325
326
327
328
329
331 if (S->isLogicalOp()) {
332 if (CodeGenFunction::isInstrumentedCondition(S->getLHS()))
333 NumCond++;
334
335 if (CodeGenFunction::isInstrumentedCondition(S->getRHS())) {
336 if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
337 CounterMap[S->getRHS()] = NextCounter++;
338
339 NumCond++;
340 }
341 }
342 return Base::VisitBinaryOperator(S);
343 }
344
347 CounterMap[S->getTrueExpr()] = NextCounter++;
349 CounterMap[S->getFalseExpr()] = NextCounter++;
350 return Base::VisitConditionalOperator(S);
351 }
352
353
354 bool VisitStmt(Stmt *S) {
355 auto Type = updateCounterMappings(S);
356 if (Hash.getHashVersion() != PGO_HASH_V1)
357 Type = getHashType(Hash.getHashVersion(), S);
358 if (Type != PGOHash::None)
359 Hash.combine(Type);
360 return true;
361 }
362
363 bool TraverseIfStmt(IfStmt *If) {
364
365 if (Hash.getHashVersion() == PGO_HASH_V1)
366 return Base::TraverseIfStmt(If);
367
368
369
371 for (Stmt *CS : If->children()) {
372 if (!CS || NoSingleByteCoverage)
373 continue;
374 if (CS == If->getThen())
375 CounterMap[If->getThen()] = NextCounter++;
376 else if (CS == If->getElse())
377 CounterMap[If->getElse()] = NextCounter++;
378 }
379
380
381 VisitStmt(If);
382
383 for (Stmt *CS : If->children()) {
384 if (!CS)
385 continue;
386 if (CS == If->getThen())
387 Hash.combine(PGOHash::IfThenBranch);
388 else if (CS == If->getElse())
389 Hash.combine(PGOHash::IfElseBranch);
390 TraverseStmt(CS);
391 }
392 Hash.combine(PGOHash::EndOfScope);
393 return true;
394 }
395
396 bool TraverseWhileStmt(WhileStmt *While) {
397
398
401 if (!CS || NoSingleByteCoverage)
402 continue;
403 if (CS == While->getCond())
404 CounterMap[While->getCond()] = NextCounter++;
405 else if (CS == While->getBody())
406 CounterMap[While->getBody()] = NextCounter++;
407 }
408
409 Base::TraverseWhileStmt(While);
410 if (Hash.getHashVersion() != PGO_HASH_V1)
411 Hash.combine(PGOHash::EndOfScope);
412 return true;
413 }
414
415 bool TraverseDoStmt(DoStmt *Do) {
416
417
420 if (!CS || NoSingleByteCoverage)
421 continue;
423 CounterMap[Do->getCond()] = NextCounter++;
424 else if (CS == Do->getBody())
425 CounterMap[Do->getBody()] = NextCounter++;
426 }
427
428 Base::TraverseDoStmt(Do);
429 if (Hash.getHashVersion() != PGO_HASH_V1)
430 Hash.combine(PGOHash::EndOfScope);
431 return true;
432 }
433
434 bool TraverseForStmt(ForStmt *For) {
435
436
439 if (!CS || NoSingleByteCoverage)
440 continue;
441 if (CS == For->getCond())
442 CounterMap[For->getCond()] = NextCounter++;
443 else if (CS == For->getInc())
444 CounterMap[For->getInc()] = NextCounter++;
445 else if (CS == For->getBody())
446 CounterMap[For->getBody()] = NextCounter++;
447 }
448
449 Base::TraverseForStmt(For);
450 if (Hash.getHashVersion() != PGO_HASH_V1)
451 Hash.combine(PGOHash::EndOfScope);
452 return true;
453 }
454
455 bool TraverseCXXForRangeStmt(CXXForRangeStmt *ForRange) {
456
459 if (!CS || NoSingleByteCoverage)
460 continue;
461 if (CS == ForRange->getBody())
462 CounterMap[ForRange->getBody()] = NextCounter++;
463 }
464
465 Base::TraverseCXXForRangeStmt(ForRange);
466 if (Hash.getHashVersion() != PGO_HASH_V1)
467 Hash.combine(PGOHash::EndOfScope);
468 return true;
469 }
470
471
472
473
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); \
479 return true; \
480 }
481
485
486
487 PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) {
488 switch (S->getStmtClass()) {
489 default:
490 break;
491 case Stmt::LabelStmtClass:
492 return PGOHash::LabelStmt;
493 case Stmt::WhileStmtClass:
494 return PGOHash::WhileStmt;
495 case Stmt::DoStmtClass:
496 return PGOHash::DoStmt;
497 case Stmt::ForStmtClass:
498 return PGOHash::ForStmt;
499 case Stmt::CXXForRangeStmtClass:
500 return PGOHash::CXXForRangeStmt;
501 case Stmt::ObjCForCollectionStmtClass:
502 return PGOHash::ObjCForCollectionStmt;
503 case Stmt::SwitchStmtClass:
504 return PGOHash::SwitchStmt;
505 case Stmt::CaseStmtClass:
506 return PGOHash::CaseStmt;
507 case Stmt::DefaultStmtClass:
508 return PGOHash::DefaultStmt;
509 case Stmt::IfStmtClass:
510 return PGOHash::IfStmt;
511 case Stmt::CXXTryStmtClass:
512 return PGOHash::CXXTryStmt;
513 case Stmt::CXXCatchStmtClass:
514 return PGOHash::CXXCatchStmt;
515 case Stmt::ConditionalOperatorClass:
516 return PGOHash::ConditionalOperator;
517 case Stmt::BinaryConditionalOperatorClass:
518 return PGOHash::BinaryConditionalOperator;
519 case Stmt::BinaryOperatorClass: {
522 return PGOHash::BinaryOperatorLAnd;
524 return PGOHash::BinaryOperatorLOr;
527 default:
528 break;
529 case BO_LT:
530 return PGOHash::BinaryOperatorLT;
531 case BO_GT:
532 return PGOHash::BinaryOperatorGT;
533 case BO_LE:
534 return PGOHash::BinaryOperatorLE;
535 case BO_GE:
536 return PGOHash::BinaryOperatorGE;
537 case BO_EQ:
538 return PGOHash::BinaryOperatorEQ;
539 case BO_NE:
540 return PGOHash::BinaryOperatorNE;
541 }
542 }
543 break;
544 }
545 }
546
548 switch (S->getStmtClass()) {
549 default:
550 break;
551 case Stmt::GotoStmtClass:
552 return PGOHash::GotoStmt;
553 case Stmt::IndirectGotoStmtClass:
554 return PGOHash::IndirectGotoStmt;
555 case Stmt::BreakStmtClass:
556 return PGOHash::BreakStmt;
557 case Stmt::ContinueStmtClass:
558 return PGOHash::ContinueStmt;
559 case Stmt::ReturnStmtClass:
560 return PGOHash::ReturnStmt;
561 case Stmt::CXXThrowExprClass:
562 return PGOHash::ThrowExpr;
563 case Stmt::UnaryOperatorClass: {
564 const UnaryOperator *UO = cast(S);
566 return PGOHash::UnaryOperatorLNot;
567 break;
568 }
569 }
570 }
571
572 return PGOHash::None;
573 }
574};
575
576
577
578struct ComputeRegionCounts : public ConstStmtVisitor {
579
581
582
583
584 bool RecordNextStmtCount;
585
586
588
589
590 llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
591
592
593 struct BreakContinue {
596 BreakContinue() = default;
597 };
599
600 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
603
604 void RecordStmtCount(const Stmt *S) {
605 if (RecordNextStmtCount) {
607 RecordNextStmtCount = false;
608 }
609 }
610
611
612 uint64_t setCount(uint64_t Count) {
613 CurrentCount = Count;
614 return Count;
615 }
616
617 void VisitStmt(const Stmt *S) {
618 RecordStmtCount(S);
619 for (const Stmt *Child : S->children())
620 if (Child)
621 this->Visit(Child);
622 }
623
625
629 }
630
631
632
633
634 void VisitLambdaExpr(const LambdaExpr *LE) {}
635
637
641 }
642
644
648 }
649
650 void VisitBlockDecl(const BlockDecl *D) {
651
655 }
656
657 void VisitReturnStmt(const ReturnStmt *S) {
658 RecordStmtCount(S);
659 if (S->getRetValue())
660 Visit(S->getRetValue());
661 CurrentCount = 0;
662 RecordNextStmtCount = true;
663 }
664
666 RecordStmtCount(E);
667 if (E->getSubExpr())
668 Visit(E->getSubExpr());
669 CurrentCount = 0;
670 RecordNextStmtCount = true;
671 }
672
673 void VisitGotoStmt(const GotoStmt *S) {
674 RecordStmtCount(S);
675 CurrentCount = 0;
676 RecordNextStmtCount = true;
677 }
678
679 void VisitLabelStmt(const LabelStmt *S) {
680 RecordNextStmtCount = false;
681
684 Visit(S->getSubStmt());
685 }
686
687 void VisitBreakStmt(const BreakStmt *S) {
688 RecordStmtCount(S);
689 assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
690 BreakContinueStack.back().BreakCount += CurrentCount;
691 CurrentCount = 0;
692 RecordNextStmtCount = true;
693 }
694
695 void VisitContinueStmt(const ContinueStmt *S) {
696 RecordStmtCount(S);
697 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
698 BreakContinueStack.back().ContinueCount += CurrentCount;
699 CurrentCount = 0;
700 RecordNextStmtCount = true;
701 }
702
703 void VisitWhileStmt(const WhileStmt *S) {
704 RecordStmtCount(S);
705 uint64_t ParentCount = CurrentCount;
706
707 BreakContinueStack.push_back(BreakContinue());
708
709
711 CountMap[S->getBody()] = CurrentCount;
712 Visit(S->getBody());
713 uint64_t BackedgeCount = CurrentCount;
714
715
716
717
718
719 BreakContinue BC = BreakContinueStack.pop_back_val();
721 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
722 CountMap[S->getCond()] = CondCount;
723 Visit(S->getCond());
724 setCount(BC.BreakCount + CondCount - BodyCount);
725 RecordNextStmtCount = true;
726 }
727
728 void VisitDoStmt(const DoStmt *S) {
729 RecordStmtCount(S);
731
732 BreakContinueStack.push_back(BreakContinue());
733
734 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
735 CountMap[S->getBody()] = BodyCount;
736 Visit(S->getBody());
737 uint64_t BackedgeCount = CurrentCount;
738
739 BreakContinue BC = BreakContinueStack.pop_back_val();
740
741
742 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
743 CountMap[S->getCond()] = CondCount;
744 Visit(S->getCond());
745 setCount(BC.BreakCount + CondCount - LoopCount);
746 RecordNextStmtCount = true;
747 }
748
749 void VisitForStmt(const ForStmt *S) {
750 RecordStmtCount(S);
751 if (S->getInit())
752 Visit(S->getInit());
753
754 uint64_t ParentCount = CurrentCount;
755
756 BreakContinueStack.push_back(BreakContinue());
757
758
760 CountMap[S->getBody()] = BodyCount;
761 Visit(S->getBody());
762 uint64_t BackedgeCount = CurrentCount;
763 BreakContinue BC = BreakContinueStack.pop_back_val();
764
765
766
767 if (S->getInc()) {
768 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
769 CountMap[S->getInc()] = IncCount;
770 Visit(S->getInc());
771 }
772
773
775 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
776 if (S->getCond()) {
777 CountMap[S->getCond()] = CondCount;
778 Visit(S->getCond());
779 }
780 setCount(BC.BreakCount + CondCount - BodyCount);
781 RecordNextStmtCount = true;
782 }
783
785 RecordStmtCount(S);
786 if (S->getInit())
787 Visit(S->getInit());
788 Visit(S->getLoopVarStmt());
789 Visit(S->getRangeStmt());
790 Visit(S->getBeginStmt());
791 Visit(S->getEndStmt());
792
793 uint64_t ParentCount = CurrentCount;
794 BreakContinueStack.push_back(BreakContinue());
795
796
798 CountMap[S->getBody()] = BodyCount;
799 Visit(S->getBody());
800 uint64_t BackedgeCount = CurrentCount;
801 BreakContinue BC = BreakContinueStack.pop_back_val();
802
803
804
805 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
806 CountMap[S->getInc()] = IncCount;
807 Visit(S->getInc());
808
809
811 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
812 CountMap[S->getCond()] = CondCount;
813 Visit(S->getCond());
814 setCount(BC.BreakCount + CondCount - BodyCount);
815 RecordNextStmtCount = true;
816 }
817
819 RecordStmtCount(S);
820 Visit(S->getElement());
821 uint64_t ParentCount = CurrentCount;
822 BreakContinueStack.push_back(BreakContinue());
823
825 CountMap[S->getBody()] = BodyCount;
826 Visit(S->getBody());
827 uint64_t BackedgeCount = CurrentCount;
828 BreakContinue BC = BreakContinueStack.pop_back_val();
829
830 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
831 BodyCount);
832 RecordNextStmtCount = true;
833 }
834
835 void VisitSwitchStmt(const SwitchStmt *S) {
836 RecordStmtCount(S);
837 if (S->getInit())
838 Visit(S->getInit());
839 Visit(S->getCond());
840 CurrentCount = 0;
841 BreakContinueStack.push_back(BreakContinue());
842 Visit(S->getBody());
843
844 BreakContinue BC = BreakContinueStack.pop_back_val();
845 if (!BreakContinueStack.empty())
846 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
847
849 RecordNextStmtCount = true;
850 }
851
852 void VisitSwitchCase(const SwitchCase *S) {
853 RecordNextStmtCount = false;
854
855
856
858 setCount(CurrentCount + CaseCount);
859
860
862 RecordNextStmtCount = true;
863 Visit(S->getSubStmt());
864 }
865
866 void VisitIfStmt(const IfStmt *S) {
867 RecordStmtCount(S);
868
869 if (S->isConsteval()) {
870 const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse();
871 if (Stm)
872 Visit(Stm);
873 return;
874 }
875
876 uint64_t ParentCount = CurrentCount;
877 if (S->getInit())
878 Visit(S->getInit());
879 Visit(S->getCond());
880
881
882
884 CountMap[S->getThen()] = ThenCount;
885 Visit(S->getThen());
886 uint64_t OutCount = CurrentCount;
887
888 uint64_t ElseCount = ParentCount - ThenCount;
889 if (S->getElse()) {
890 setCount(ElseCount);
891 CountMap[S->getElse()] = ElseCount;
892 Visit(S->getElse());
893 OutCount += CurrentCount;
894 } else
895 OutCount += ElseCount;
896 setCount(OutCount);
897 RecordNextStmtCount = true;
898 }
899
900 void VisitCXXTryStmt(const CXXTryStmt *S) {
901 RecordStmtCount(S);
902 Visit(S->getTryBlock());
903 for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
904 Visit(S->getHandler(I));
905
907 RecordNextStmtCount = true;
908 }
909
910 void VisitCXXCatchStmt(const CXXCatchStmt *S) {
911 RecordNextStmtCount = false;
912
915 Visit(S->getHandlerBlock());
916 }
917
919 RecordStmtCount(E);
920 uint64_t ParentCount = CurrentCount;
921 Visit(E->getCond());
922
923
924
926 CountMap[E->getTrueExpr()] = TrueCount;
927 Visit(E->getTrueExpr());
928 uint64_t OutCount = CurrentCount;
929
930 uint64_t FalseCount = setCount(ParentCount - TrueCount);
931 CountMap[E->getFalseExpr()] = FalseCount;
932 Visit(E->getFalseExpr());
933 OutCount += CurrentCount;
934
935 setCount(OutCount);
936 RecordNextStmtCount = true;
937 }
938
940 RecordStmtCount(E);
941 uint64_t ParentCount = CurrentCount;
942 Visit(E->getLHS());
943
945 CountMap[E->getRHS()] = RHSCount;
946 Visit(E->getRHS());
947 setCount(ParentCount + RHSCount - CurrentCount);
948 RecordNextStmtCount = true;
949 }
950
952 RecordStmtCount(E);
953 uint64_t ParentCount = CurrentCount;
954 Visit(E->getLHS());
955
957 CountMap[E->getRHS()] = RHSCount;
958 Visit(E->getRHS());
959 setCount(ParentCount + RHSCount - CurrentCount);
960 RecordNextStmtCount = true;
961 }
962};
963}
964
965void PGOHash::combine(HashType Type) {
966
967 assert(Type && "Hash is invalid: unexpected type 0");
968 assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
969
970
971 if (Count && Count % NumTypesPerWord == 0) {
972 using namespace llvm::support;
974 endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
975 MD5.update(llvm::ArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
976 Working = 0;
977 }
978
979
980 ++Count;
981 Working = Working << NumBitsPerType | Type;
982}
983
984uint64_t PGOHash::finalize() {
985
986 if (Count <= NumTypesPerWord)
987
988
989
990 return Working;
991
992
993 if (Working) {
994
995
997 MD5.update({(uint8_t)Working});
998 } else {
999 using namespace llvm::support;
1001 endian::byte_swap<uint64_t, llvm::endianness::little>(Working);
1002 MD5.update(llvm::ArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
1003 }
1004 }
1005
1006
1007 llvm::MD5::MD5Result Result;
1009 return Result.low();
1010}
1011
1015 return;
1016
1017
1020 return;
1021
1023 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1024 if (!InstrumentRegions && !PGOReader)
1025 return;
1027 return;
1028
1029
1030
1032 if (const auto *CCD = dyn_cast(D))
1035 return;
1036 }
1038 return;
1039
1041 if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
1042 return;
1043 if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile))
1044 return;
1045
1049 return;
1050
1051 setFuncName(Fn);
1052
1053 mapRegionCounters(D);
1055 emitCounterRegionMapping(D);
1056 if (PGOReader) {
1057 loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
1058 computeRegionCounts(D);
1059 applyFunctionAttributes(PGOReader, Fn);
1060 }
1061}
1062
1063void CodeGenPGO::mapRegionCounters(const Decl *D) {
1064
1065
1067 uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
1069 HashVersion = getPGOHashVersion(PGOReader, CGM);
1070 ProfileVersion = PGOReader->getVersion();
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 unsigned MCDCMaxConditions =
1084 : 0);
1085
1086 RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, CounterPair>);
1088 MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
1089 *RegionMCDCState, MCDCMaxConditions, CGM.getDiags());
1090 if (const FunctionDecl *FD = dyn_cast_or_null(D))
1091 Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
1092 else if (const ObjCMethodDecl *MD = dyn_cast_or_null(D))
1093 Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
1094 else if (const BlockDecl *BD = dyn_cast_or_null(D))
1095 Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
1096 else if (const CapturedDecl *CD = dyn_cast_or_null(D))
1097 Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
1098 assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
1099 NumRegionCounters = Walker.NextCounter;
1100 FunctionHash = Walker.Hash.finalize();
1101}
1102
1103bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
1105 return true;
1106
1107
1108
1109
1110
1113 ->hasAttr()) ||
1116 (->hasAttr() && D->hasAttr())))))
1117 return true;
1118
1119
1123}
1124
1125void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
1126 if (skipRegionMappingForDecl(D))
1127 return;
1128
1129 std::string CoverageMapping;
1130 llvm::raw_string_ostream OS(CoverageMapping);
1131 RegionMCDCState->BranchByStmt.clear();
1134 CGM.getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
1135 MappingGen.emitCounterMapping(D, OS);
1136
1137 if (CoverageMapping.empty())
1138 return;
1139
1141 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
1142}
1143
1144void
1146 llvm::GlobalValue::LinkageTypes Linkage) {
1147 if (skipRegionMappingForDecl(D))
1148 return;
1149
1150 std::string CoverageMapping;
1151 llvm::raw_string_ostream OS(CoverageMapping);
1156
1157 if (CoverageMapping.empty())
1158 return;
1159
1160 setFuncName(Name, Linkage);
1162 FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
1163}
1164
1165void CodeGenPGO::computeRegionCounts(const Decl *D) {
1166 StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
1167 ComputeRegionCounts Walker(*StmtCountMap, *this);
1168 if (const FunctionDecl *FD = dyn_cast_or_null(D))
1169 Walker.VisitFunctionDecl(FD);
1170 else if (const ObjCMethodDecl *MD = dyn_cast_or_null(D))
1171 Walker.VisitObjCMethodDecl(MD);
1172 else if (const BlockDecl *BD = dyn_cast_or_null(D))
1173 Walker.VisitBlockDecl(BD);
1174 else if (const CapturedDecl *CD = dyn_cast_or_null(D))
1175 Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
1176}
1177
1178void
1179CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
1180 llvm::Function *Fn) {
1182 return;
1183
1185 Fn->setEntryCount(FunctionCount);
1186}
1187
1189 if (!RegionCounterMap)
1190 return {false, false};
1191
1192 auto I = RegionCounterMap->find(S);
1193 if (I == RegionCounterMap->end())
1194 return {false, false};
1195
1196 return {I->second.Executed.hasValue(), I->second.Skipped.hasValue()};
1197}
1198
1200 llvm::Value *StepV) {
1201 if (!RegionCounterMap || !Builder.GetInsertBlock())
1202 return;
1203
1204 unsigned Counter = (*RegionCounterMap)[S].Executed;
1205
1206
1207
1208 auto *NormalizedFuncNameVarPtr =
1209 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
1210 FuncNameVar, llvm::PointerType::get(CGM.getLLVMContext(), 0));
1211
1212 llvm::Value *Args[] = {
1213 NormalizedFuncNameVarPtr, Builder.getInt64(FunctionHash),
1214 Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV};
1215
1217 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover),
1219 else if (!StepV)
1220 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
1222 else
1223 Builder.CreateCall(
1224 CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
1225}
1226
1227bool CodeGenPGO::canEmitMCDCCoverage(const CGBuilderTy &Builder) {
1229 CGM.getCodeGenOpts().MCDCCoverage && Builder.GetInsertBlock());
1230}
1231
1233 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1234 return;
1235
1236 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1237
1238
1239
1240
1241 llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1242 Builder.getInt64(FunctionHash),
1243 Builder.getInt32(RegionMCDCState->BitmapBits)};
1244 Builder.CreateCall(
1245 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
1246}
1247
1249 const Expr *S,
1250 Address MCDCCondBitmapAddr,
1252 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1253 return;
1254
1255 S = S->IgnoreParens();
1256
1257 auto DecisionStateIter = RegionMCDCState->DecisionByStmt.find(S);
1258 if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
1259 return;
1260
1261
1262
1263 if (DecisionStateIter->second.Indices.size() == 0)
1264 return;
1265
1266
1267 unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
1268 auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
1269
1270
1271
1272
1273
1274
1275 llvm::Value *Args[4] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
1276 Builder.getInt64(FunctionHash),
1277 Builder.getInt32(MCDCTestVectorBitmapOffset),
1279 Builder.CreateCall(
1280 CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
1281}
1282
1284 Address MCDCCondBitmapAddr) {
1285 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1286 return;
1287
1288 S = S->IgnoreParens();
1289
1290 if (!RegionMCDCState->DecisionByStmt.contains(S))
1291 return;
1292
1293
1294 Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr);
1295}
1296
1298 Address MCDCCondBitmapAddr,
1299 llvm::Value *Val,
1301 if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState)
1302 return;
1303
1304
1305
1306
1307
1308
1309
1310
1312
1313 auto BranchStateIter = RegionMCDCState->BranchByStmt.find(S);
1314 if (BranchStateIter == RegionMCDCState->BranchByStmt.end())
1315 return;
1316
1317
1318 const auto &Branch = BranchStateIter->second;
1319 assert(Branch.ID >= 0 && "Condition has no ID!");
1320 assert(Branch.DecisionStmt);
1321
1322
1323 const auto DecisionIter =
1324 RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
1325 if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
1326 return;
1327
1328 const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
1329
1330 auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
1331 "mcdc." + Twine(Branch.ID + 1) + ".cur");
1332 auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[true]));
1333 NewTV = Builder.CreateSelect(
1334 Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[false])));
1335 Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
1336}
1337
1340 M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling",
1342}
1343
1347 const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR));
1348 llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext());
1349 uint64_t ProfileVersion =
1350 (INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE);
1351
1352 auto IRLevelVersionVariable = new llvm::GlobalVariable(
1353 M, IntTy64, true, llvm::GlobalValue::WeakAnyLinkage,
1354 llvm::Constant::getIntegerValue(IntTy64,
1355 llvm::APInt(64, ProfileVersion)),
1356 VarName);
1357
1358 IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
1359 llvm::Triple TT(M.getTargetTriple());
1360 if (TT.supportsCOMDAT()) {
1361 IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
1362 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
1363 }
1364 IRLevelVersionVariable->setDSOLocal(true);
1365 }
1366}
1367
1368
1369
1371 llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
1372
1374 return;
1375
1376 if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
1377 return;
1378
1379 if (isallvm::Constant(ValuePtr))
1380 return;
1381
1383 if (InstrumentValueSites && RegionCounterMap) {
1384 auto BuilderInsertPoint = Builder.saveIP();
1385 Builder.SetInsertPoint(ValueSite);
1386 llvm::Value *Args[5] = {
1387 FuncNameVar,
1388 Builder.getInt64(FunctionHash),
1389 Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1390 Builder.getInt32(ValueKind),
1391 Builder.getInt32(NumValueSites[ValueKind]++)
1392 };
1393 Builder.CreateCall(
1394 CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1395 Builder.restoreIP(BuilderInsertPoint);
1396 return;
1397 }
1398
1399 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1401
1402
1403
1404
1405
1406
1407 if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1408 return;
1409
1410 llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
1411 (llvm::InstrProfValueKind)ValueKind,
1412 NumValueSites[ValueKind]);
1413
1414 NumValueSites[ValueKind]++;
1415 }
1416}
1417
1418void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
1419 bool IsInMainFile) {
1421 RegionCounts.clear();
1423 PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1424 if (auto E = RecordExpected.takeError()) {
1425 auto IPE = 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)
1431
1433 return;
1434 }
1435 ProfRecord =
1436 std::make_uniquellvm::InstrProfRecord(std::move(RecordExpected.get()));
1437 RegionCounts = ProfRecord->Counts;
1438}
1439
1440
1441
1442
1443
1445 return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
1446}
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1458 assert(Scale && "scale by 0?");
1459 uint64_t Scaled = Weight / Scale + 1;
1460 assert(Scaled <= UINT32_MAX && "overflow 32-bits");
1461 return Scaled;
1462}
1463
1464llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1465 uint64_t FalseCount) const {
1466
1467 if (!TrueCount && !FalseCount)
1468 return nullptr;
1469
1470
1472
1474 return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
1476}
1477
1478llvm::MDNode *
1479CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) const {
1480
1481 if (Weights.size() < 2)
1482 return nullptr;
1483
1484
1485 uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
1486 if (MaxWeight == 0)
1487 return nullptr;
1488
1489
1491
1493 ScaledWeights.reserve(Weights.size());
1494 for (uint64_t W : Weights)
1496
1498 return MDHelper.createBranchWeights(ScaledWeights);
1499}
1500
1501llvm::MDNode *
1502CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond,
1503 uint64_t LoopCount) const {
1505 return nullptr;
1506 std::optional<uint64_t> CondCount = PGO.getStmtCount(Cond);
1507 if (!CondCount || *CondCount == 0)
1508 return nullptr;
1509 return createProfileWeights(LoopCount,
1510 std::max(*CondCount, LoopCount) - LoopCount);
1511}
llvm::ImmutableMap< CountKey, unsigned > CountMap
#define DEFINE_NESTABLE_TRAVERSAL(N)
static llvm:🆑:opt< bool > EnableValueProfiling("enable-value-profiling", llvm:🆑:desc("Enable value profiling"), llvm:🆑:Hidden, llvm:🆑: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