1414#include " llvm/ProfileData/Coverage/CoverageMapping.h"
1515#include " llvm/ADT/ArrayRef.h"
1616#include " llvm/ADT/DenseMap.h"
17+ #include " llvm/ADT/STLExtras.h"
1718#include " llvm/ADT/SmallBitVector.h"
1819#include " llvm/ADT/SmallVector.h"
1920#include " llvm/ADT/StringExtras.h"
@@ -582,6 +583,72 @@ static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
582583 return MaxBitmapID + (SizeInBits / CHAR_BIT);
583584}
584585
586+ struct DecisionRow {
587+ const CounterMappingRegion *DecisionRegion;
588+ LineColPair DecisionStartLoc;
589+ LineColPair DecisionEndLoc;
590+
591+ SmallVector<const CounterMappingRegion *, 6 > Branches;
592+ DenseSet<CounterMappingRegion::MCDCConditionID> IDs;
593+ SmallVector<const CounterMappingRegion *> Expansions;
594+
595+ DecisionRow (const CounterMappingRegion &Decision)
596+ : DecisionRegion(&Decision), DecisionStartLoc(Decision.startLoc()),
597+ DecisionEndLoc (Decision.endLoc()) {}
598+
599+ bool insert (const CounterMappingRegion &Branch) {
600+ auto ID = Branch.MCDCParams .ID ;
601+ if (ID == 1 )
602+ Branches.insert (Branches.begin (), &Branch);
603+ else
604+ Branches.push_back (&Branch);
605+ IDs.insert (ID);
606+ return (Branches.size () == DecisionRegion->MCDCParams .NumConditions );
607+ }
608+
609+ enum class UpdateResult {
610+ NotFound = 0 ,
611+ Updated,
612+ Committed,
613+ };
614+
615+ UpdateResult updateBranch (const CounterMappingRegion &Branch) {
616+ if (IDs.contains (Branch.MCDCParams .ID ))
617+ return UpdateResult::NotFound;
618+
619+ if (Branch.FileID == DecisionRegion->FileID &&
620+ Branch.startLoc () >= DecisionStartLoc &&
621+ Branch.endLoc () <= DecisionEndLoc)
622+ return (insert (Branch) ? UpdateResult::Committed : UpdateResult::Updated);
623+
624+ for (const auto *R : Expansions) {
625+ if (Branch.FileID == R->ExpandedFileID )
626+ return (insert (Branch) ? UpdateResult::Committed
627+ : UpdateResult::Updated);
628+ }
629+
630+ return UpdateResult::NotFound;
631+ }
632+
633+ bool updateExpansion (const CounterMappingRegion &Expansion) {
634+ if (Expansion.FileID == DecisionRegion->FileID &&
635+ Expansion.startLoc () >= DecisionStartLoc &&
636+ Expansion.endLoc () <= DecisionEndLoc) {
637+ Expansions.push_back (&Expansion);
638+ return true ;
639+ }
640+
641+ for (const auto *R : Expansions) {
642+ if (Expansion.FileID == R->ExpandedFileID ) {
643+ Expansions.push_back (&Expansion);
644+ return true ;
645+ }
646+ }
647+
648+ return false ;
649+ }
650+ };
651+
585652Error CoverageMapping::loadFunctionRecord (
586653 const CoverageMappingRecord &Record,
587654 IndexedInstrProfReader &ProfileReader) {
@@ -638,18 +705,11 @@ Error CoverageMapping::loadFunctionRecord(
638705 Record.MappingRegions [0 ].Count .isZero () && Counts[0 ] > 0 )
639706 return Error::success ();
640707
641- unsigned NumConds = 0 ;
642- const CounterMappingRegion *MCDCDecision;
643- std::vector<const CounterMappingRegion *> MCDCBranches;
644-
708+ SmallVector<DecisionRow> Decisions;
645709 FunctionRecord Function (OrigFuncName, Record.Filenames );
646710 for (const auto &Region : Record.MappingRegions ) {
647- // If an MCDCDecisionRegion is seen, track the BranchRegions that follow
648- // it according to Region.NumConditions.
649711 if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
650- assert (NumConds == 0 );
651- MCDCDecision = &Region;
652- NumConds = Region.MCDCParams .NumConditions ;
712+ Decisions.emplace_back (Region);
653713 continue ;
654714 }
655715 Expected<int64_t > ExecutionCount = Ctx.evaluate (Region.Count );
@@ -664,23 +724,39 @@ Error CoverageMapping::loadFunctionRecord(
664724 }
665725 Function.pushRegion (Region, *ExecutionCount, *AltExecutionCount);
666726
727+ if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
728+ for (auto &Decision : reverse (Decisions)) {
729+ if (Decision.updateExpansion (Region))
730+ break ;
731+ }
732+ continue ;
733+ }
734+
735+ if (Region.Kind != CounterMappingRegion::MCDCBranchRegion)
736+ continue ;
737+
667738 // If a MCDCDecisionRegion was seen, store the BranchRegions that
668739 // correspond to it in a vector, according to the number of conditions
669740 // recorded for the region (tracked by NumConds).
670- if (NumConds > 0 && Region. Kind == CounterMappingRegion::MCDCBranchRegion ) {
671- MCDCBranches. push_back (&Region) ;
741+ for ( int I = Decisions. size () - 1 ; I >= 0 ; --I ) {
742+ auto &Decision = Decisions[I] ;
672743
673744 // As we move through all of the MCDCBranchRegions that follow the
674745 // MCDCDecisionRegion, decrement NumConds to make sure we account for
675746 // them all before we calculate the bitmap of executed test vectors.
676- if (--NumConds == 0 ) {
747+ switch (Decision.updateBranch (Region)) {
748+ case DecisionRow::UpdateResult::NotFound:
749+ continue ;
750+ case DecisionRow::UpdateResult::Updated:
751+ goto branch_found;
752+ case DecisionRow::UpdateResult::Committed:
677753 // Evaluating the test vector bitmap for the decision region entails
678754 // calculating precisely what bits are pertinent to this region alone.
679755 // This is calculated based on the recorded offset into the global
680756 // profile bitmap; the length is calculated based on the recorded
681757 // number of conditions.
682758 Expected<BitVector> ExecutedTestVectorBitmap =
683- Ctx.evaluateBitmap (MCDCDecision );
759+ Ctx.evaluateBitmap (Decision. DecisionRegion );
684760 if (auto E = ExecutedTestVectorBitmap.takeError ()) {
685761 consumeError (std::move (E));
686762 return Error::success ();
@@ -690,17 +766,23 @@ Error CoverageMapping::loadFunctionRecord(
690766 // DecisionRegion, all of the information is now available to process.
691767 // This is where the bulk of the MC/DC progressing takes place.
692768 Expected<MCDCRecord> Record = Ctx.evaluateMCDCRegion (
693- *MCDCDecision, *ExecutedTestVectorBitmap, MCDCBranches);
769+ *Decision.DecisionRegion , *ExecutedTestVectorBitmap,
770+ Decision.Branches );
694771 if (auto E = Record.takeError ()) {
695772 consumeError (std::move (E));
696773 return Error::success ();
697774 }
698775
699776 // Save the MC/DC Record so that it can be visualized later.
700777 Function.pushMCDCRecord (*Record);
701- MCDCBranches.clear ();
778+
779+ Decisions.erase (Decisions.begin () + I);
780+ goto branch_found;
702781 }
703782 }
783+ llvm_unreachable (" Branch not found in Decisions" );
784+
785+ branch_found:;
704786 }
705787
706788 // Don't create records for (filenames, function) pairs we've already seen.
0 commit comments