https://github.com/chapuni updated https://github.com/llvm/llvm-project/pull/122589
>From e5fbf846113591b0abff151d91b01a5dd40abef1 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4ci...@gmail.com> Date: Sat, 11 Jan 2025 18:42:10 +0900 Subject: [PATCH 1/6] [Coverage] Improve performance of propagating Counter of Expansions This improves `-dump-coverage-mapping` (939,498 lines) for `RISCVInstructionSelector.cpp` from 30m to 1m18s and also improves `llvm-cov` for `check-llvm` from 33m to 24s. The current implementation behaved O(N^2) order with hundreds thousands of Expansions. This assumes: - Records are partitioned by FileID. - ExpandedFileID doesn't point FileID==0, since it is the root. - The Count in Expansion is propagated from 1st Record in ExpandedFileID. Therefore another fact below can be assumed. - Propagation chain consists of Expansions at each 1st Record. This scans the Record at most a few times. O(N) is expected. Fixes #113173 --- .../Coverage/CoverageMappingReader.cpp | 100 +++++++++++++++--- 1 file changed, 84 insertions(+), 16 deletions(-) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index cdf4412c6477a..15c7004c45e7d 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -440,26 +440,94 @@ Error RawCoverageMappingReader::read() { // Set the counters for the expansion regions. // i.e. Counter of expansion region = counter of the first region // from the expanded file. - // Perform multiple passes to correctly propagate the counters through - // all the nested expansion regions. - SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; - FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); - for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { - for (auto &R : MappingRegions) { - if (R.Kind != CounterMappingRegion::ExpansionRegion) - continue; - assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); - FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; + // This assumes: + // - Records are partitioned by FileID. + // - ExpandedFileID doesn't point FileID==0, since it is the root. + // - The Count in Expansion is propagated from 1st Record in + // ExpandedFileID. + // Therefore another fact below can be assumed. + // - Propagation chain consists of Expansions at each 1st Record. + + /// Node per File. + struct FileNode { + /// 1st Record in the File. + CounterMappingRegion *FirstR = nullptr; + /// The Expansion Record out of this File. + CounterMappingRegion *ExpanderR = nullptr; + /// Count hasn't been propagated yet (for Expansion) + bool ExpansionPending = false; + }; + SmallVector<FileNode> FileIDExpansionRegionMapping(VirtualFileMapping.size()); + assert(VirtualFileMapping.size() == FileIDExpansionRegionMapping.size()); + + // Construct the tree. + unsigned PrevFileID = 0; + for (auto &R : MappingRegions) { + if (R.Kind == CounterMappingRegion::ExpansionRegion) { + // The File that contains Expansion may be a node. + assert(R.ExpandedFileID != 0 && + "ExpandedFileID shouldn't point the root"); + assert(!FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR); + FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR = &R; + + // It will be the node if (isExpansion and ExpansionPending). + FileIDExpansionRegionMapping[R.ExpandedFileID].ExpansionPending = true; } - for (auto &R : MappingRegions) { - if (FileIDExpansionRegionMapping[R.FileID]) { - FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; - FileIDExpansionRegionMapping[R.FileID] = nullptr; - } + + // FileID==0 is not handled here but don't care since it's the root. + if (PrevFileID != R.FileID) { + // Record 1st Record for each File. + assert(!FileIDExpansionRegionMapping[R.FileID].FirstR); + FileIDExpansionRegionMapping[R.FileID].FirstR = &R; + PrevFileID = R.FileID; } } - return Error::success(); + // Make sure the root [0] doesn't point others. + assert((FileIDExpansionRegionMapping.empty() || + (!FileIDExpansionRegionMapping[0].ExpanderR && + !FileIDExpansionRegionMapping[0].FirstR)) && + "The root shouldn't point other nodes"); + + auto Propagate = [&](FileNode &X) { + // Skip already processed node. + if (!X.ExpanderR) + return false; + // Skip Pending Expansion node. + // Process non-Expansion Record and non-Pending Expansion. + if (X.ExpansionPending && + X.FirstR->Kind == CounterMappingRegion::ExpansionRegion) + return false; + + // Propagate. + X.ExpanderR->Count = X.FirstR->Count; + // Mark the destination ready. + FileIDExpansionRegionMapping[X.ExpanderR->FileID].ExpansionPending = false; + // Mark this processed. + X.ExpanderR = nullptr; + return true; + }; + + // This won't iterate in most cases but iterates finitely for + // unusual cases. + for (unsigned I = 0, E = FileIDExpansionRegionMapping.size(); I != E; ++I) { + // Propagate Descending. All Files will be processed if each + // ExpandedFileID is greater than FileID. + for (auto &X : reverse(FileIDExpansionRegionMapping)) + Propagate(X); + + // Check whether all Files are processed (or propagate Ascending, + // not possible in the usual assumptions). + bool Changed = false; + for (auto &X : FileIDExpansionRegionMapping) + Changed = (Propagate(X) || Changed); + + if (!Changed) + return Error::success(); + } + + return make_error<CoverageMapError>(coveragemap_error::malformed, + "unexpected Expansions"); } Expected<bool> RawCoverageMappingDummyChecker::isDummy() { >From 2aa0859cafca4eb8576cf5b8b23998038bf71ebf Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4ci...@gmail.com> Date: Sat, 11 Jan 2025 22:51:29 +0900 Subject: [PATCH 2/6] Get rid of the assumption "[0] is the root" --- .../ProfileData/Coverage/CoverageMappingReader.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 15c7004c45e7d..19733adeef9ba 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" +#include <limits> #include <vector> using namespace llvm; @@ -442,7 +443,6 @@ Error RawCoverageMappingReader::read() { // from the expanded file. // This assumes: // - Records are partitioned by FileID. - // - ExpandedFileID doesn't point FileID==0, since it is the root. // - The Count in Expansion is propagated from 1st Record in // ExpandedFileID. // Therefore another fact below can be assumed. @@ -458,15 +458,12 @@ Error RawCoverageMappingReader::read() { bool ExpansionPending = false; }; SmallVector<FileNode> FileIDExpansionRegionMapping(VirtualFileMapping.size()); - assert(VirtualFileMapping.size() == FileIDExpansionRegionMapping.size()); // Construct the tree. - unsigned PrevFileID = 0; + auto PrevFileID = std::numeric_limits<unsigned>::max(); // Invalid value for (auto &R : MappingRegions) { if (R.Kind == CounterMappingRegion::ExpansionRegion) { // The File that contains Expansion may be a node. - assert(R.ExpandedFileID != 0 && - "ExpandedFileID shouldn't point the root"); assert(!FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR); FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR = &R; @@ -474,7 +471,6 @@ Error RawCoverageMappingReader::read() { FileIDExpansionRegionMapping[R.ExpandedFileID].ExpansionPending = true; } - // FileID==0 is not handled here but don't care since it's the root. if (PrevFileID != R.FileID) { // Record 1st Record for each File. assert(!FileIDExpansionRegionMapping[R.FileID].FirstR); @@ -483,12 +479,6 @@ Error RawCoverageMappingReader::read() { } } - // Make sure the root [0] doesn't point others. - assert((FileIDExpansionRegionMapping.empty() || - (!FileIDExpansionRegionMapping[0].ExpanderR && - !FileIDExpansionRegionMapping[0].FirstR)) && - "The root shouldn't point other nodes"); - auto Propagate = [&](FileNode &X) { // Skip already processed node. if (!X.ExpanderR) >From 06d0d51dce35916ebabcbb219c2d868df375e601 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4ci...@gmail.com> Date: Sun, 2 Feb 2025 21:58:41 +0900 Subject: [PATCH 3/6] [MC/DC] Make covmap tolerant of nested Decisions CoverageMappingWriter reorders `Region`s by `endLoc DESC` to prioritize wider `Decision` with the same `startLoc`. In `llvm-cov`, tweak seeking Decisions by reversal order to find smaller Decision first. --- clang/test/CoverageMapping/ctor.cpp | 4 ++-- clang/test/CoverageMapping/includehell.cpp | 18 +++++++++--------- clang/test/CoverageMapping/macros.c | 6 +++--- .../ProfileData/Coverage/CoverageMapping.cpp | 4 ++-- .../Coverage/CoverageMappingWriter.cpp | 9 ++++++++- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/clang/test/CoverageMapping/ctor.cpp b/clang/test/CoverageMapping/ctor.cpp index 1cf12cd738c2c..191f73f5693e1 100644 --- a/clang/test/CoverageMapping/ctor.cpp +++ b/clang/test/CoverageMapping/ctor.cpp @@ -11,8 +11,8 @@ class B: public A { int c; B(int x, int y) : A(x), // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:11 = #0 - // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:13 = #0 - b(x == 0? 1: 2), // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:19 = #0 + // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:19 = #0 + b(x == 0? 1: 2), // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:13 = #1, (#0 - #1) // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:14 -> [[@LINE-2]]:15 = #1 // CHECK-NEXT: File 0, [[@LINE-3]]:15 -> [[@LINE-3]]:16 = #1 diff --git a/clang/test/CoverageMapping/includehell.cpp b/clang/test/CoverageMapping/includehell.cpp index 09e03e77799d5..3c67672fabc0f 100644 --- a/clang/test/CoverageMapping/includehell.cpp +++ b/clang/test/CoverageMapping/includehell.cpp @@ -28,14 +28,14 @@ int main() { // CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 6:12 -> 6:35 = #0 // CHECK-MAIN-NEXT: File [[MAIN]], 6:35 -> 10:33 = #1 // CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 8:14 -> 8:29 = #1 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 10:12 -> 10:33 = #1 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 10:12 -> 10:33 = #0 // CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 12:12 -> 12:35 = #0 // CHECK-MAIN-NEXT: File [[MAIN]], 12:35 -> 14:33 = #5 // CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 13:14 -> 13:29 = #5 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 14:12 -> 14:33 = #5 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 14:12 -> 14:33 = #0 // CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 16:12 -> 16:35 = #0 // CHECK-MAIN-NEXT: File [[MAIN]], 16:35 -> 17:33 = #9 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 17:12 -> 17:33 = #9 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 17:12 -> 17:33 = #0 // CHECK-START: File [[START1:[0-9]]], 1:1 -> 5:1 = #0 // CHECK-START: File [[START1]], 4:17 -> 4:22 = (#0 + #1) @@ -65,15 +65,15 @@ int main() { // CHECK-CODE: File [[CODE2]], 9:11 -> 11:2 = #7 // CHECK-CODE: File [[CODE2]], 11:8 -> 13:2 = (#5 - #7) -// CHECK-END: File [[END1:[0-9]]], 1:1 -> 3:2 = #1 -// CHECK-END: File [[END1]], 1:1 -> 6:1 = #0 +// CHECK-END: File [[END1:[0-9]]], 1:1 -> 6:1 = #0 +// CHECK-END: File [[END1]], 1:1 -> 3:2 = #1 // CHECK-END: File [[END1]], 5:5 -> 5:9 = #0 // CHECK-END: File [[END1]], 5:11 -> 5:16 = #4 -// CHECK-END: File [[END2:[0-9]]], 1:1 -> 3:2 = #5 -// CHECK-END: File [[END2]], 1:1 -> 6:1 = #0 +// CHECK-END: File [[END2:[0-9]]], 1:1 -> 6:1 = #0 +// CHECK-END: File [[END2]], 1:1 -> 3:2 = #5 // CHECK-END: File [[END2]], 5:5 -> 5:9 = #0 // CHECK-END: File [[END2]], 5:11 -> 5:16 = #8 -// CHECK-END: File [[END3:[0-9]]], 1:1 -> 3:2 = #9 -// CHECK-END: File [[END3]], 1:1 -> 6:1 = #0 +// CHECK-END: File [[END3:[0-9]]], 1:1 -> 6:1 = #0 +// CHECK-END: File [[END3]], 1:1 -> 3:2 = #9 // CHECK-END: File [[END3]], 5:5 -> 5:9 = #0 // CHECK-END: File [[END3]], 5:11 -> 5:16 = #10 diff --git a/clang/test/CoverageMapping/macros.c b/clang/test/CoverageMapping/macros.c index fcf21170ef135..00139f33229d5 100644 --- a/clang/test/CoverageMapping/macros.c +++ b/clang/test/CoverageMapping/macros.c @@ -80,12 +80,12 @@ void func7(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+6]]:2 = #0 int kk,ll; // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:8 = #0 if (k) // CHECK-NEXT: Branch,File 0, [[@LINE]]:7 -> [[@LINE]]:8 = #1 m(k); // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE]]:5 = #1 - else // CHECK-NEXT: Expansion,File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:6 = #1 + else // CHECK-NEXT: Expansion,File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:6 = #0 l = m(l); // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:7 -> [[@LINE]]:5 = (#0 - #1) } // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = (#0 - #1) // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:10 = (#0 - #1) - // CHECK-NEXT: File 1, [[@LINE-9]]:14 -> [[@LINE-9]]:17 = #1 - // CHECK-NEXT: File 1, [[@LINE-10]]:14 -> [[@LINE-10]]:18 = #0 + // CHECK-NEXT: File 1, [[@LINE-9]]:14 -> [[@LINE-9]]:18 = #0 + // CHECK-NEXT: File 1, [[@LINE-10]]:14 -> [[@LINE-10]]:17 = #1 // CHECK-NEXT: File 2, [[@LINE-11]]:14 -> [[@LINE-11]]:17 = (#0 - #1) // CHECK-NEXT: File 2, [[@LINE-12]]:14 -> [[@LINE-12]]:15 = (#0 - #1) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index c39585681911a..3205863331c91 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -800,7 +800,7 @@ class MCDCDecisionRecorder { std::optional<DecisionAndBranches> processBranch(const CounterMappingRegion &Branch) { // Seek each Decision and apply Region to it. - for (auto DecisionIter = Decisions.begin(), DecisionEnd = Decisions.end(); + for (auto DecisionIter = Decisions.rbegin(), DecisionEnd = Decisions.rend(); DecisionIter != DecisionEnd; ++DecisionIter) switch (DecisionIter->addBranch(Branch)) { case DecisionRecord::NotProcessed: @@ -811,7 +811,7 @@ class MCDCDecisionRecorder { DecisionAndBranches Result = std::make_pair(DecisionIter->DecisionRegion, std::move(DecisionIter->MCDCBranches)); - Decisions.erase(DecisionIter); // No longer used. + Decisions.erase(std::next(DecisionIter).base()); // No longer used. return Result; } diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp index 12b1687af69db..e0a1aae2a8cc1 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp @@ -174,7 +174,14 @@ void CoverageMappingWriter::write(raw_ostream &OS) { : 2 * Kind); }; - return getKindKey(LHS.Kind) < getKindKey(RHS.Kind); + auto LHSKindKey = getKindKey(LHS.Kind); + auto RHSKindKey = getKindKey(RHS.Kind); + if (LHSKindKey != RHSKindKey) + return LHSKindKey < RHSKindKey; + + // Compares endLoc in descending order, + // to prioritize wider Regions with the same startLoc. + return LHS.endLoc() > RHS.endLoc(); }); // Write out the fileid -> filename mapping. >From 489b1df5917bb27c56998f16ab535f2a4429c754 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4ci...@gmail.com> Date: Sat, 15 Mar 2025 11:09:53 +0900 Subject: [PATCH 4/6] Dissolve one condition to invert the loop --- .../Coverage/CoverageMappingReader.cpp | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 19733adeef9ba..91cf8048f2b5e 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -460,23 +460,19 @@ Error RawCoverageMappingReader::read() { SmallVector<FileNode> FileIDExpansionRegionMapping(VirtualFileMapping.size()); // Construct the tree. - auto PrevFileID = std::numeric_limits<unsigned>::max(); // Invalid value - for (auto &R : MappingRegions) { - if (R.Kind == CounterMappingRegion::ExpansionRegion) { - // The File that contains Expansion may be a node. - assert(!FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR); - FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR = &R; - - // It will be the node if (isExpansion and ExpansionPending). - FileIDExpansionRegionMapping[R.ExpandedFileID].ExpansionPending = true; - } - - if (PrevFileID != R.FileID) { - // Record 1st Record for each File. - assert(!FileIDExpansionRegionMapping[R.FileID].FirstR); - FileIDExpansionRegionMapping[R.FileID].FirstR = &R; - PrevFileID = R.FileID; - } + // Reverse loop finally sets FirstR as the top for each FileID. + for (auto &R : reverse(MappingRegions)) { + FileIDExpansionRegionMapping[R.FileID].FirstR = &R; + + if (R.Kind != CounterMappingRegion::ExpansionRegion) + continue; + + // The File that contains Expansion may be a node. + auto &ExpandedRegion = FileIDExpansionRegionMapping[R.ExpandedFileID]; + assert(!ExpandedRegion.ExpanderR); + ExpandedRegion.ExpanderR = &R; + // It will be the node if (isExpansion and ExpansionPending). + ExpandedRegion.ExpansionPending = true; } auto Propagate = [&](FileNode &X) { >From 3f04e8ca5deec5e2829e7ce112a088925a5fb16b Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4ci...@gmail.com> Date: Wed, 2 Apr 2025 20:18:49 +0900 Subject: [PATCH 5/6] Refactor with expansion walking --- .../ProfileData/Coverage/CoverageMapping.cpp | 303 ++++++++---------- llvm/test/tools/llvm-cov/mcdc-macro.test | 14 +- 2 files changed, 142 insertions(+), 175 deletions(-) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 3205863331c91..8c5eae9015abe 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -668,154 +668,166 @@ static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record, namespace { -/// Collect Decisions, Branchs, and Expansions and associate them. -class MCDCDecisionRecorder { -private: - /// This holds the DecisionRegion and MCDCBranches under it. - /// Also traverses Expansion(s). - /// The Decision has the number of MCDCBranches and will complete - /// when it is filled with unique ConditionID of MCDCBranches. +/// Walk MappingRegions along Expansions and emit CountedRegions. +struct CountedRegionEmitter { + /// A nestable Decision. struct DecisionRecord { const CounterMappingRegion *DecisionRegion; - - /// They are reflected from DecisionRegion for convenience. - mcdc::DecisionParameters DecisionParams; - LineColPair DecisionStartLoc; - LineColPair DecisionEndLoc; - - /// This is passed to `MCDCRecordProcessor`, so this should be compatible - /// to`ArrayRef<const CounterMappingRegion *>`. + unsigned NumConditions; ///< Copy of DecisionRegion.NumConditions + /// Pushed by traversal order. SmallVector<const CounterMappingRegion *> MCDCBranches; - - /// IDs that are stored in MCDCBranches - /// Complete when all IDs (1 to NumConditions) are met. +#ifndef NDEBUG DenseSet<mcdc::ConditionID> ConditionIDs; - - /// Set of IDs of Expansion(s) that are relevant to DecisionRegion - /// and its children (via expansions). - /// FileID pointed by ExpandedFileID is dedicated to the expansion, so - /// the location in the expansion doesn't matter. - DenseSet<unsigned> ExpandedFileIDs; +#endif DecisionRecord(const CounterMappingRegion &Decision) : DecisionRegion(&Decision), - DecisionParams(Decision.getDecisionParams()), - DecisionStartLoc(Decision.startLoc()), - DecisionEndLoc(Decision.endLoc()) { + NumConditions(Decision.getDecisionParams().NumConditions) { assert(Decision.Kind == CounterMappingRegion::MCDCDecisionRegion); } - /// Determine whether DecisionRecord dominates `R`. - bool dominates(const CounterMappingRegion &R) const { - // Determine whether `R` is included in `DecisionRegion`. - if (R.FileID == DecisionRegion->FileID && - R.startLoc() >= DecisionStartLoc && R.endLoc() <= DecisionEndLoc) - return true; - - // Determine whether `R` is pointed by any of Expansions. - return ExpandedFileIDs.contains(R.FileID); + bool pushBranch(const CounterMappingRegion &B) { + assert(B.Kind == CounterMappingRegion::MCDCBranchRegion); + assert(ConditionIDs.insert(B.getBranchParams().ID).second && + "Duplicate CondID"); + MCDCBranches.push_back(&B); + assert(MCDCBranches.size() <= NumConditions && + "MCDCBranch exceeds NumConds"); + return (MCDCBranches.size() == NumConditions); } + }; - enum Result { - NotProcessed = 0, /// Irrelevant to this Decision - Processed, /// Added to this Decision - Completed, /// Added and filled this Decision - }; + const CoverageMappingRecord &Record; + CounterMappingContext &Ctx; + FunctionRecord &Function; + bool IsVersion11; - /// Add Branch into the Decision - /// \param Branch expects MCDCBranchRegion - /// \returns NotProcessed/Processed/Completed - Result addBranch(const CounterMappingRegion &Branch) { - assert(Branch.Kind == CounterMappingRegion::MCDCBranchRegion); + /// Evaluated Counters. + std::map<Counter, uint64_t> CounterValues; - auto ConditionID = Branch.getBranchParams().ID; + /// Decisions are nestable. + SmallVector<DecisionRecord, 1> DecisionStack; - if (ConditionIDs.contains(ConditionID) || - ConditionID >= DecisionParams.NumConditions) - return NotProcessed; + /// A File pointed by Expansion + struct FileInfo { + /// The last index(+1) for each FileID in MappingRegions. + unsigned LastIndex = 0; + /// Mark Files pointed by Expansions. + /// Non-marked Files are root Files. + bool IsExpanded = false; + }; - if (!this->dominates(Branch)) - return NotProcessed; + /// The last element is a sentinel with Index=NumRegions. + std::vector<FileInfo> Files; +#ifndef NDEBUG + DenseSet<unsigned> Visited; +#endif - assert(MCDCBranches.size() < DecisionParams.NumConditions); + CountedRegionEmitter(const CoverageMappingRecord &Record, + CounterMappingContext &Ctx, FunctionRecord &Function, + bool IsVersion11) + : Record(Record), Ctx(Ctx), Function(Function), IsVersion11(IsVersion11), + Files(Record.Filenames.size()) { + // Scan MappingRegions and mark each last index by FileID. + for (auto [I, Region] : enumerate(Record.MappingRegions)) { + if (Region.FileID >= Files.size()) { + // Extend (only possible in CoverageMappingTests) + Files.resize(Region.FileID + 1); + } + Files[Region.FileID].LastIndex = I + 1; + if (Region.Kind == CounterMappingRegion::ExpansionRegion) { + if (Region.ExpandedFileID >= Files.size()) { + // Extend (only possible in CoverageMappingTests) + Files.resize(Region.ExpandedFileID + 1); + } + Files[Region.ExpandedFileID].IsExpanded = true; + } + } + } - // Put `ID=0` in front of `MCDCBranches` for convenience - // even if `MCDCBranches` is not topological. - if (ConditionID == 0) - MCDCBranches.insert(MCDCBranches.begin(), &Branch); - else - MCDCBranches.push_back(&Branch); + /// Evaluate C and store its evaluated Value into CounterValues. + Error evaluateAndCacheCounter(Counter C) { + if (CounterValues.count(C) > 0) + return Error::success(); - // Mark `ID` as `assigned`. - ConditionIDs.insert(ConditionID); + auto ValueOrErr = Ctx.evaluate(C); + if (!ValueOrErr) + return ValueOrErr.takeError(); + CounterValues[C] = *ValueOrErr; + return Error::success(); + } - // `Completed` when `MCDCBranches` is full - return (MCDCBranches.size() == DecisionParams.NumConditions ? Completed - : Processed); - } + Error walk(unsigned Idx) { + assert(Idx < Files.size()); + unsigned B = (Idx == 0 ? 0 : Files[Idx - 1].LastIndex); + unsigned E = Files[Idx].LastIndex; + assert(B != E && "Empty FileID"); + assert(Visited.insert(Idx).second && "Duplicate Expansions"); + for (unsigned I = B; I != E; ++I) { + const auto &Region = Record.MappingRegions[I]; + if (Region.FileID != Idx) + break; - /// Record Expansion if it is relevant to this Decision. - /// Each `Expansion` may nest. - /// \returns true if recorded. - bool recordExpansion(const CounterMappingRegion &Expansion) { - if (!this->dominates(Expansion)) - return false; + if (Region.Kind == CounterMappingRegion::ExpansionRegion) + if (auto E = walk(Region.ExpandedFileID)) + return E; - ExpandedFileIDs.insert(Expansion.ExpandedFileID); - return true; - } - }; + if (auto E = evaluateAndCacheCounter(Region.Count)) + return E; -private: - /// Decisions in progress - /// DecisionRecord is added for each MCDCDecisionRegion. - /// DecisionRecord is removed when Decision is completed. - SmallVector<DecisionRecord> Decisions; + if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) { + // Start the new Decision on the stack. + DecisionStack.emplace_back(Region); + } else if (Region.Kind == CounterMappingRegion::MCDCBranchRegion) { + assert(!DecisionStack.empty() && "Orphan MCDCBranch"); + auto &D = DecisionStack.back(); + + if (D.pushBranch(Region)) { + // All Branches have been found in the Decision. + auto RecordOrErr = Ctx.evaluateMCDCRegion( + *D.DecisionRegion, D.MCDCBranches, IsVersion11); + if (!RecordOrErr) + return RecordOrErr.takeError(); + + // Finish the stack. + Function.pushMCDCRecord(std::move(*RecordOrErr)); + DecisionStack.pop_back(); + } + } -public: - ~MCDCDecisionRecorder() { - assert(Decisions.empty() && "All Decisions have not been resolved"); - } + // Evaluate FalseCount + // It may have the Counter in Branches, or Zero. + if (auto E = evaluateAndCacheCounter(Region.FalseCount)) + return E; + } - /// Register Region and start recording. - void registerDecision(const CounterMappingRegion &Decision) { - Decisions.emplace_back(Decision); - } + assert((Idx != 0 || DecisionStack.empty()) && "Decision wasn't closed"); - void recordExpansion(const CounterMappingRegion &Expansion) { - any_of(Decisions, [&Expansion](auto &Decision) { - return Decision.recordExpansion(Expansion); - }); + return Error::success(); } - using DecisionAndBranches = - std::pair<const CounterMappingRegion *, /// Decision - SmallVector<const CounterMappingRegion *> /// Branches - >; - - /// Add MCDCBranchRegion to DecisionRecord. - /// \param Branch to be processed - /// \returns DecisionsAndBranches if DecisionRecord completed. - /// Or returns nullopt. - std::optional<DecisionAndBranches> - processBranch(const CounterMappingRegion &Branch) { - // Seek each Decision and apply Region to it. - for (auto DecisionIter = Decisions.rbegin(), DecisionEnd = Decisions.rend(); - DecisionIter != DecisionEnd; ++DecisionIter) - switch (DecisionIter->addBranch(Branch)) { - case DecisionRecord::NotProcessed: - continue; - case DecisionRecord::Processed: - return std::nullopt; - case DecisionRecord::Completed: - DecisionAndBranches Result = - std::make_pair(DecisionIter->DecisionRegion, - std::move(DecisionIter->MCDCBranches)); - Decisions.erase(std::next(DecisionIter).base()); // No longer used. - return Result; - } + Error emitCountedRegions() { + // Walk MappingRegions along Expansions. + // - Evaluate Counters + // - Emit MCDCRecords + for (auto [I, F] : enumerate(Files)) { + if (!F.IsExpanded) + if (auto E = walk(I)) + return E; + } + assert(Visited.size() == Files.size() && "Dangling FileID"); + + // Emit CountedRegions in the same order as MappingRegions. + for (const auto &Region : Record.MappingRegions) { + if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) + continue; // Don't emit. + // Adopt values from the CounterValues. + // FalseCount may be Zero unless Branches. + Function.pushRegion(Region, CounterValues[Region.Count], + CounterValues[Region.FalseCount]); + } - llvm_unreachable("Branch not found in Decisions"); + return Error::success(); } }; @@ -880,57 +892,12 @@ Error CoverageMapping::loadFunctionRecord( Record.MappingRegions[0].Count.isZero() && Counts[0] > 0) return Error::success(); - MCDCDecisionRecorder MCDCDecisions; FunctionRecord Function(OrigFuncName, Record.Filenames); - for (const auto &Region : Record.MappingRegions) { - // MCDCDecisionRegion should be handled first since it overlaps with - // others inside. - if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) { - MCDCDecisions.registerDecision(Region); - continue; - } - Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); - if (auto E = ExecutionCount.takeError()) { - consumeError(std::move(E)); - return Error::success(); - } - Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount); - if (auto E = AltExecutionCount.takeError()) { - consumeError(std::move(E)); - return Error::success(); - } - Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount); - - // Record ExpansionRegion. - if (Region.Kind == CounterMappingRegion::ExpansionRegion) { - MCDCDecisions.recordExpansion(Region); - continue; - } - - // Do nothing unless MCDCBranchRegion. - if (Region.Kind != CounterMappingRegion::MCDCBranchRegion) - continue; - auto Result = MCDCDecisions.processBranch(Region); - if (!Result) // Any Decision doesn't complete. - continue; - - auto MCDCDecision = Result->first; - auto &MCDCBranches = Result->second; - - // Since the bitmap identifies the executed test vectors for an MC/DC - // DecisionRegion, all of the information is now available to process. - // This is where the bulk of the MC/DC progressing takes place. - Expected<MCDCRecord> Record = - Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11); - if (auto E = Record.takeError()) { - consumeError(std::move(E)); - return Error::success(); - } - - // Save the MC/DC Record so that it can be visualized later. - Function.pushMCDCRecord(std::move(*Record)); - } + // Emit CountedRegions into FunctionRecord. + if (auto E = CountedRegionEmitter(Record, Ctx, Function, IsVersion11) + .emitCountedRegions()) + return E; // Don't create records for (filenames, function) pairs we've already seen. auto FilenamesHash = hash_combine_range(Record.Filenames.begin(), diff --git a/llvm/test/tools/llvm-cov/mcdc-macro.test b/llvm/test/tools/llvm-cov/mcdc-macro.test index 14dd5ebd68eb1..d68f4aeb67bcb 100644 --- a/llvm/test/tools/llvm-cov/mcdc-macro.test +++ b/llvm/test/tools/llvm-cov/mcdc-macro.test @@ -13,19 +13,19 @@ // CHECK-NEXT: | // CHECK-NEXT: | Number of Conditions: 5 // CHECK-NEXT: | Condition C1 --> (9:7) -// CHECK-NEXT: | Condition C2 --> (9:22) -// CHECK-NEXT: | Condition C3 --> (2:11) -// CHECK-NEXT: | Condition C4 --> (3:11) -// CHECK-NEXT: | Condition C5 --> (3:23) +// CHECK-NEXT: | Condition C2 --> (2:11) +// CHECK-NEXT: | Condition C3 --> (3:11) +// CHECK-NEXT: | Condition C4 --> (3:23) +// CHECK-NEXT: | Condition C5 --> (9:22) // CHECK-NEXT: | // CHECK-NEXT: | Executed MC/DC Test Vectors: // CHECK-NEXT: | // CHECK-NEXT: | C1, C2, C3, C4, C5 Result -// CHECK-NEXT: | 1 { T, -, C, T, T = T } +// CHECK-NEXT: | 1 { T, C, T, T, - = T } // CHECK-NEXT: | // CHECK-NEXT: | C1-Pair: not covered -// CHECK-NEXT: | C2-Pair: not covered -// CHECK-NEXT: | C3-Pair: constant folded +// CHECK-NEXT: | C2-Pair: constant folded +// CHECK-NEXT: | C3-Pair: not covered // CHECK-NEXT: | C4-Pair: not covered // CHECK-NEXT: | C5-Pair: not covered // CHECK-NEXT: | MC/DC Coverage for Decision: 0.00% >From 4d1ae4b1c0f5bc038a75e083a29afcc8c84bde6f Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi <geek4ci...@gmail.com> Date: Wed, 2 Apr 2025 20:21:14 +0900 Subject: [PATCH 6/6] Revise w/ expansion walker --- clang/test/CoverageMapping/comment-in-macro.c | 4 +- clang/test/CoverageMapping/comment.cpp | 2 +- .../test/CoverageMapping/control-flow-macro.c | 2 +- clang/test/CoverageMapping/if.cpp | 4 +- clang/test/CoverageMapping/include-macros.c | 8 +-- clang/test/CoverageMapping/includehell.cpp | 16 +++--- clang/test/CoverageMapping/label.cpp | 4 +- clang/test/CoverageMapping/loopmacro.c | 16 +++--- clang/test/CoverageMapping/macro-expansion.c | 2 +- .../CoverageMapping/macro-expressions.cpp | 34 +++++------ clang/test/CoverageMapping/macroception.c | 24 ++++---- clang/test/CoverageMapping/macroparams.c | 4 +- clang/test/CoverageMapping/macroparams2.c | 2 +- clang/test/CoverageMapping/macros.c | 20 +++---- clang/test/CoverageMapping/macroscopes.cpp | 30 +++++----- .../test/CoverageMapping/mcdc-scratch-space.c | 10 ++-- .../CoverageMapping/mcdc-system-headers.cpp | 8 +-- clang/test/CoverageMapping/moremacros.c | 8 +-- clang/test/CoverageMapping/switchmacro.c | 4 +- clang/test/CoverageMapping/trymacro.cpp | 6 +- .../ProfileData/Coverage/CoverageMapping.cpp | 57 ++++++++++++++----- .../Coverage/CoverageMappingReader.cpp | 22 ------- .../ProfileData/CoverageMappingTest.cpp | 15 +++-- 23 files changed, 155 insertions(+), 147 deletions(-) diff --git a/clang/test/CoverageMapping/comment-in-macro.c b/clang/test/CoverageMapping/comment-in-macro.c index 1afde46f1e4a5..90f6d373f7f37 100644 --- a/clang/test/CoverageMapping/comment-in-macro.c +++ b/clang/test/CoverageMapping/comment-in-macro.c @@ -4,8 +4,8 @@ #define x2 return 0 // CHECK: main int main(void) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> [[@LINE+3]]:2 = #0 - x1; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:5 = #0 - x2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:5 = #0 + x1; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:5 = 0 + x2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:5 = 0 } // CHECK-NEXT: File 1, 3:12 -> 3:14 = #0 // CHECK-NEXT: File 2, 4:12 -> 4:20 = #0 diff --git a/clang/test/CoverageMapping/comment.cpp b/clang/test/CoverageMapping/comment.cpp index f8e4b4912e182..90da003f01079 100644 --- a/clang/test/CoverageMapping/comment.cpp +++ b/clang/test/CoverageMapping/comment.cpp @@ -8,6 +8,6 @@ int f() { } // CHECK: File 0, 3:9 -> 8:2 = #0 -// CHECK-NEXT: Expansion,File 0, 5:10 -> 5:28 = #0 +// CHECK-NEXT: Expansion,File 0, 5:10 -> 5:28 = 0 // CHECK-NEXT: Skipped,File 0, 6:1 -> 6:7 = 0 // CHECK-NEXT: File 1, 1:1 -> 7:1 = #0 diff --git a/clang/test/CoverageMapping/control-flow-macro.c b/clang/test/CoverageMapping/control-flow-macro.c index b73ac989057db..1a4e106fca6e2 100644 --- a/clang/test/CoverageMapping/control-flow-macro.c +++ b/clang/test/CoverageMapping/control-flow-macro.c @@ -5,7 +5,7 @@ // CHECK: main // CHECK-NEXT: File 0, {{[0-9]+}}:40 -> [[END:[0-9]+]]:2 = #0 int main(int argc, const char *argv[]) { - // CHECK: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:6 = #0 + // CHECK: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:6 = 0 ifc(1) return 0; // Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = (#0 - #1) // File 0, [[@LINE+1]]:6 -> [[END]]:2 = (#0 - #1) diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp index b6fd525e930f9..8166a374c1b53 100644 --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -121,7 +121,7 @@ int check_constexpr_init_with_if_def(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9] // CHECK-LABEL: _Z32check_macro_constexpr_if_skippedi: int check_macro_constexpr_if_skipped(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 -#define IF_CONSTEXPR if constexpr // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = #0 (Expanded file = 1) +#define IF_CONSTEXPR if constexpr // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = 0 (Expanded file = 1) IF_CONSTEXPR(false) { // CHECK-NEXT: Skipped,File 0, [[@LINE]]:3 -> [[@LINE+2]]:4 = 0 i *= 2; // CHECK-NEXT: File 1, [[@LINE-2]]:22 -> [[@LINE-2]]:34 = #0 } @@ -227,7 +227,7 @@ constexpr int check_notconsteval_branch_kept(int i) { // CHECK-NEXT: [[@LINE]]:{ // CHECK-LABEL: _Z32check_macro_consteval_if_skippedi: constexpr int check_macro_consteval_if_skipped(int i) { // CHECK-NEXT: [[@LINE]]:{{[0-9]+}} -> {{[0-9]+}}:2 = #0 -#define IF_RUNTIME if !consteval // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:13 = #0 (Expanded file = 1) +#define IF_RUNTIME if !consteval // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:13 = 0 (Expanded file = 1) IF_RUNTIME { // CHECK-NEXT: Skipped,File 0, [[@LINE]]:3 -> [[@LINE]]:14 = 0 i *= 2; // CHECK-NEXT: File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:4 = #0 } // CHECK-NEXT: File 1, [[@LINE-3]]:20 -> [[@LINE-3]]:33 = #0 diff --git a/clang/test/CoverageMapping/include-macros.c b/clang/test/CoverageMapping/include-macros.c index 8adb34bd22876..6f0ad4c7e2de1 100644 --- a/clang/test/CoverageMapping/include-macros.c +++ b/clang/test/CoverageMapping/include-macros.c @@ -8,11 +8,11 @@ void f1(void) { // CHECK-LABEL: f1: // CHECK-NEXT: File 0, 5:15 -> 7:2 = #0 -// CHECK-NEXT: Expansion,File 0, 6:3 -> 6:5 = #0 (Expanded file = 1) +// CHECK-NEXT: Expansion,File 0, 6:3 -> 6:5 = 0 (Expanded file = 1) // CHECK-NEXT: File 1, 13:20 -> 13:50 = #0 -// CHECK-NEXT: Expansion,File 1, 13:20 -> 13:22 = #0 (Expanded file = 2) +// CHECK-NEXT: Expansion,File 1, 13:20 -> 13:22 = 0 (Expanded file = 2) // CHECK-NEXT: File 2, 7:20 -> 7:46 = #0 -// CHECK-NEXT: Expansion,File 2, 7:33 -> 7:44 = #0 (Expanded file = 3) +// CHECK-NEXT: Expansion,File 2, 7:33 -> 7:44 = 0 (Expanded file = 3) // CHECK-NEXT: File 3, 13:26 -> 13:34 = #0 -// CHECK-NEXT: Expansion,File 3, 13:26 -> 13:33 = #0 (Expanded file = 4) +// CHECK-NEXT: Expansion,File 3, 13:26 -> 13:33 = 0 (Expanded file = 4) // CHECK-NEXT: File 4, 3:17 -> 3:18 = #0 diff --git a/clang/test/CoverageMapping/includehell.cpp b/clang/test/CoverageMapping/includehell.cpp index 3c67672fabc0f..bfa4e74a1e9c1 100644 --- a/clang/test/CoverageMapping/includehell.cpp +++ b/clang/test/CoverageMapping/includehell.cpp @@ -25,17 +25,17 @@ int main() { // RUN: FileCheck -input-file %tmapping %s --check-prefix=CHECK-END // CHECK-MAIN: File [[MAIN:[0-9]]], 3:12 -> 20:2 = #0 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 6:12 -> 6:35 = #0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 6:12 -> 6:35 = 0 // CHECK-MAIN-NEXT: File [[MAIN]], 6:35 -> 10:33 = #1 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 8:14 -> 8:29 = #1 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 10:12 -> 10:33 = #0 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 12:12 -> 12:35 = #0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 8:14 -> 8:29 = 0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 10:12 -> 10:33 = 0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 12:12 -> 12:35 = 0 // CHECK-MAIN-NEXT: File [[MAIN]], 12:35 -> 14:33 = #5 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 13:14 -> 13:29 = #5 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 14:12 -> 14:33 = #0 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 16:12 -> 16:35 = #0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 13:14 -> 13:29 = 0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 14:12 -> 14:33 = 0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 16:12 -> 16:35 = 0 // CHECK-MAIN-NEXT: File [[MAIN]], 16:35 -> 17:33 = #9 -// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 17:12 -> 17:33 = #0 +// CHECK-MAIN-NEXT: Expansion,File [[MAIN]], 17:12 -> 17:33 = 0 // CHECK-START: File [[START1:[0-9]]], 1:1 -> 5:1 = #0 // CHECK-START: File [[START1]], 4:17 -> 4:22 = (#0 + #1) diff --git a/clang/test/CoverageMapping/label.cpp b/clang/test/CoverageMapping/label.cpp index cf7cbe5d00f43..18786e7e08fe8 100644 --- a/clang/test/CoverageMapping/label.cpp +++ b/clang/test/CoverageMapping/label.cpp @@ -54,8 +54,8 @@ void test2(int x) { // CHECK-NEXT: File 0, [[@LINE]]:19 -> {{[0-9]+}}:2 void test3() { if (0) goto b; // CHECK: Gap,File 0, [[@LINE]]:12 -> [[@LINE+1]]:1 = (#0 - #1) -a: // CHECK-NEXT: Expansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = [[retnCount:#[0-9]+]] (Expanded file = 1) - return; // CHECK-NEXT: File 0, [[@LINE-1]]:2 -> [[@LINE]]:9 = [[retnCount]] +a: // CHECK-NEXT: Expansion,File 0, [[@LINE]]:1 -> [[@LINE]]:2 = 0 (Expanded file = 1) + return; // CHECK-NEXT: File 0, [[@LINE-1]]:2 -> [[@LINE]]:9 = [[retnCount:#[0-9]+]] } #undef a diff --git a/clang/test/CoverageMapping/loopmacro.c b/clang/test/CoverageMapping/loopmacro.c index 1fbb1139abf04..1ad633fbbf761 100644 --- a/clang/test/CoverageMapping/loopmacro.c +++ b/clang/test/CoverageMapping/loopmacro.c @@ -3,27 +3,27 @@ // CHECK: main // CHECK-NEXT: File 0, {{[0-9]+}}:16 -> {{[0-9]+}}:2 = #0 // CHECK-NEXT: File 0, {{[0-9]+}}:6 -> {{[0-9]+}}:4 = (#0 + #1) -// CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:7 -> {{[0-9]+}}:20 = (#0 + #1) +// CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:7 -> {{[0-9]+}}:20 = 0 // CHECK-NEXT: File 0, {{[0-9]+}}:12 -> {{[0-9]+}}:30 = (#0 + #1) // CHECK-NEXT: Branch,File 0, {{[0-9]+}}:12 -> {{[0-9]+}}:30 = #1, #0 // CHECK-NEXT: File 1, [[@LINE+4]]:4 -> [[@LINE+6]]:23 = (#0 + #1) -// CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = (#0 + #1) -// CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:16 -> [[@LINE+3]]:21 = (#0 + #1) +// CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = 0 +// CHECK-NEXT: Expansion,File 1, [[@LINE+3]]:16 -> [[@LINE+3]]:21 = 0 #define INSERT_STRING(s, match_head) \ (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \ prev[(s) & WMASK] = match_head = head[ins_h], \ head[ins_h] = (s)) // CHECK-NEXT: File 2, [[@LINE+3]]:26 -> [[@LINE+3]]:66 = (#0 + #1) -// CHECK-NEXT: Expansion,File 2, [[@LINE+2]]:38 -> [[@LINE+2]]:45 = (#0 + #1) -// CHECK-NEXT: Expansion,File 2, [[@LINE+1]]:56 -> [[@LINE+1]]:65 = (#0 + #1) +// CHECK-NEXT: Expansion,File 2, [[@LINE+2]]:38 -> [[@LINE+2]]:45 = 0 +// CHECK-NEXT: Expansion,File 2, [[@LINE+1]]:56 -> [[@LINE+1]]:65 = 0 #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) // CHECK-NEXT: File 3, [[@LINE+1]]:15 -> [[@LINE+1]]:21 = (#0 + #1) #define WMASK 0xFFFF // CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:53 = (#0 + #1) -// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:29 = (#0 + #1) -// CHECK-NEXT: Expansion,File 4, [[@LINE+2]]:30 -> [[@LINE+2]]:39 = (#0 + #1) -// CHECK-NEXT: Expansion,File 4, [[@LINE+1]]:43 -> [[@LINE+1]]:52 = (#0 + #1) +// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:29 = 0 +// CHECK-NEXT: Expansion,File 4, [[@LINE+2]]:30 -> [[@LINE+2]]:39 = 0 +// CHECK-NEXT: Expansion,File 4, [[@LINE+1]]:43 -> [[@LINE+1]]:52 = 0 #define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH) // CHECK-NEXT: File 5, [[@LINE+1]]:19 -> [[@LINE+1]]:25 = (#0 + #1) #define HASH_MASK 0xFFFF diff --git a/clang/test/CoverageMapping/macro-expansion.c b/clang/test/CoverageMapping/macro-expansion.c index 4cd2c93437193..b6fe1c7d2cf7e 100644 --- a/clang/test/CoverageMapping/macro-expansion.c +++ b/clang/test/CoverageMapping/macro-expansion.c @@ -24,7 +24,7 @@ #define M2(x) do { if (x) {} } while (0) // CHECK-NEXT: File 4, [[@LINE+5]]:15 -> [[@LINE+5]]:38 = #0 // CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:28 = (#0 + #8) -// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = (#0 + #8) +// CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = 0 // CHECK-NEXT: File 4, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #8) // CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, #0 #define M3(x) do { M2(x); } while (0) diff --git a/clang/test/CoverageMapping/macro-expressions.cpp b/clang/test/CoverageMapping/macro-expressions.cpp index 2b6a1b64c2594..57e5d1218f0fb 100644 --- a/clang/test/CoverageMapping/macro-expressions.cpp +++ b/clang/test/CoverageMapping/macro-expressions.cpp @@ -58,33 +58,33 @@ void foo(int i) { // CHECK-NEXT: File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:12 = #1 if (0) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:11 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:11 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:16 = #2 // CHECK-NEXT: File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:18 = #2 if (EXPR(i)) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:9 -> [[@LINE+3]]:14 = (#0 + #3) + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:9 -> [[@LINE+3]]:14 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:19 -> [[@LINE+2]]:20 = #3 // CHECK-NEXT: File 0, [[@LINE+1]]:20 -> [[@LINE+1]]:22 = #3 for (;NEXPR(i);) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:14 = #0 - // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:33 -> [[@LINE+4]]:35 = (#0 + #4) - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:43 -> [[@LINE+3]]:46 = #4 + // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:14 = 0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:33 -> [[@LINE+4]]:35 = 0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:43 -> [[@LINE+3]]:46 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:50 -> [[@LINE+2]]:51 = #4 // CHECK: File 0, [[@LINE+1]]:51 -> [[@LINE+1]]:53 = #4 for (ASSIGN(DECL(int, j), 0); LT(j, i); INC(j)) {} - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:9 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:9 = 0 ASSIGN(DECL(int, k), 0); - // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:12 = (#0 + #5) + // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:12 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:19 -> [[@LINE+3]]:20 = #5 // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:31 = #5 - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:22 -> [[@LINE+1]]:25 = #5 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:22 -> [[@LINE+1]]:25 = 0 while (LT(k, i)) { INC(k); } // CHECK-NEXT: File 0, [[@LINE+2]]:6 -> [[@LINE+2]]:8 = (#0 + #6) - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = (#0 + #6) + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:16 -> [[@LINE+1]]:21 = 0 do {} while (NEXPR(i)); - // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:12 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:8 -> [[@LINE+5]]:12 = 0 // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = #7, #0 - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:23 -> [[@LINE+3]]:26 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:23 -> [[@LINE+3]]:26 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:41 -> [[@LINE+2]]:42 = #7 // CHECK: File 0, [[@LINE+1]]:42 -> [[@LINE+1]]:44 = #7 for (DECL(int, j) : ARR(int, 1, 2, 3)) {} @@ -92,21 +92,21 @@ void foo(int i) { // CHECK-NEXT: File 0, [[@LINE+5]]:10 -> [[@LINE+5]]:11 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #8, (#0 - #8) // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #8 - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #0 - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:23 -> [[@LINE+1]]:29 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = 0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:23 -> [[@LINE+1]]:29 = 0 (void)(i ? PRIo64 : PRIu64); // CHECK-NEXT: File 0, [[@LINE+6]]:10 -> [[@LINE+6]]:11 = #0 // CHECK: File 0, [[@LINE+5]]:14 -> [[@LINE+5]]:15 = #9 // CHECK-NEXT: File 0, [[@LINE+4]]:18 -> [[@LINE+4]]:33 = (#0 - #9) - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:22 = (#0 - #9) + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:22 = 0 // CHECK: File 0, [[@LINE+2]]:28 -> [[@LINE+2]]:29 = #10 // CHECK-NEXT: File 0, [[@LINE+1]]:32 -> [[@LINE+1]]:33 = ((#0 - #9) - #10) (void)(i ? i : EXPR(i) ? i : 0); // CHECK-NEXT: File 0, [[@LINE+5]]:10 -> [[@LINE+5]]:11 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #11, (#0 - #11) // CHECK-NEXT: File 0, [[@LINE+3]]:15 -> [[@LINE+3]]:27 = (#0 - #11) - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = (#0 - #11) + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = 0 // CHECK-NEXT: File 0, [[@LINE+1]]:26 -> [[@LINE+1]]:27 = ((#0 - #11) - #12) (void)(i ?: EXPR(i) ?: 0); } @@ -128,10 +128,10 @@ void foo(int i) { // CHECK-NEXT: File {{[0-9]+}}, 5:20 -> 5:23 = #0 // CHECK-NEXT: File {{[0-9]+}}, 9:25 -> 9:40 = #0 // CHECK-NEXT: File {{[0-9]+}}, 12:16 -> 12:42 = #0 -// CHECK-NEXT: Expansion,File {{[0-9]+}}, 12:16 -> 12:38 = #8 +// CHECK-NEXT: Expansion,File {{[0-9]+}}, 12:16 -> 12:38 = 0 // CHECK-NEXT: File {{[0-9]+}}, 12:38 -> 12:42 = #8 // CHECK-NEXT: File {{[0-9]+}}, 13:16 -> 13:42 = #0 -// CHECK-NEXT: Expansion,File {{[0-9]+}}, 13:16 -> 13:38 = (#0 - #8) +// CHECK-NEXT: Expansion,File {{[0-9]+}}, 13:16 -> 13:38 = 0 // CHECK-NEXT: File {{[0-9]+}}, 13:38 -> 13:42 = (#0 - #8) // CHECK-NEXT: File {{[0-9]+}}, 3:17 -> 3:20 = (#0 - #9) // CHECK-NEXT: Branch,File {{[0-9]+}}, 3:17 -> 3:20 = #10, ((#0 - #9) - #10) diff --git a/clang/test/CoverageMapping/macroception.c b/clang/test/CoverageMapping/macroception.c index 6d4b3ed427f7f..ddcee3e398abc 100644 --- a/clang/test/CoverageMapping/macroception.c +++ b/clang/test/CoverageMapping/macroception.c @@ -6,41 +6,41 @@ #define M11 M22 // CHECK-LABEL: main: -// CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:18 = #0 +// CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:18 = 0 // CHECK-NEXT: File 0, [[@LINE+1]]:18 -> [[@LINE+3]]:2 = #0 int main(void) M1 return 0; } -// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 +// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = 0 // CHECK-NEXT: File 2, 3:12 -> 3:13 = #0 // CHECK-LABEL: func2: // CHECK-NEXT: File 0, [[@LINE+2]]:18 -> [[@LINE+4]]:4 = #0 -// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0 +// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = 0 void func2(void) { int x = 0; M11 -// CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = #0 +// CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = 0 // CHECK-NEXT: File 2, 5:13 -> 5:14 = #0 // CHECK-LABEL: func3: -// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = #0 +// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = 0 // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+4]]:4 = #0 -// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = #0 +// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:1 -> [[@LINE+3]]:4 = 0 void func3(void) M1 int x = 0; M11 -// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 -// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0 +// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = 0 +// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = 0 // CHECK-NEXT: File 3, 3:12 -> 3:13 = #0 // CHECK-NEXT: File 4, 5:13 -> 5:14 = #0 // CHECK-LABEL: func4: -// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = #0 +// CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:18 -> [[@LINE+3]]:20 = 0 // CHECK-NEXT: File 0, [[@LINE+2]]:20 -> [[@LINE+2]]:24 = #0 -// CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:24 = #0 +// CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:24 = 0 void func4(void) M1 M11 -// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0 -// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0 +// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = 0 +// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = 0 // CHECK-NEXT: File 3, 3:12 -> 3:13 = #0 // CHECK-NEXT: File 4, 5:13 -> 5:14 = #0 diff --git a/clang/test/CoverageMapping/macroparams.c b/clang/test/CoverageMapping/macroparams.c index 2f60cffbfdb77..227ee2d0e355b 100644 --- a/clang/test/CoverageMapping/macroparams.c +++ b/clang/test/CoverageMapping/macroparams.c @@ -2,10 +2,10 @@ // CHECK: main // CHECK-NEXT: File 0, {{[0-9]+}}:16 -> {{[0-9]+}}:2 = #0 -// CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:3 -> {{[0-9]+}}:8 = #0 +// CHECK-NEXT: Expansion,File 0, {{[0-9]+}}:3 -> {{[0-9]+}}:8 = 0 // CHECK-NEXT: File 1, [[@LINE+2]]:18 -> [[@LINE+2]]:27 = #0 -// CHECK-NEXT: Expansion,File 1, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = #0 +// CHECK-NEXT: Expansion,File 1, [[@LINE+1]]:18 -> [[@LINE+1]]:24 = 0 #define MACRO(X) MACRO2(x) // CHECK-NEXT: File 2, [[@LINE+1]]:20 -> [[@LINE+1]]:28 = #0 #define MACRO2(X2) (X2 + 2) diff --git a/clang/test/CoverageMapping/macroparams2.c b/clang/test/CoverageMapping/macroparams2.c index 7873b6ac12a9a..27323bdb384fc 100644 --- a/clang/test/CoverageMapping/macroparams2.c +++ b/clang/test/CoverageMapping/macroparams2.c @@ -10,7 +10,7 @@ struct S { int main(void) { struct S arr[32] = { 0 }; int n = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:12 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:33 -> [[@LINE+2]]:34 = #1 // CHECK-NEXT: File 0, [[@LINE+1]]:34 -> [[@LINE+3]]:4 = #1 if (MACRO(arr[n].j, arr[n].i)) { diff --git a/clang/test/CoverageMapping/macros.c b/clang/test/CoverageMapping/macros.c index 00139f33229d5..a4acc8699e9fb 100644 --- a/clang/test/CoverageMapping/macros.c +++ b/clang/test/CoverageMapping/macros.c @@ -11,7 +11,7 @@ void bar(void) {} // CHECK: func void func(void) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+5]]:2 = #0 int i = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = 0 MACRO; // CHECK-NEXT: File 0, [[@LINE]]:8 -> [[@LINE+2]]:2 = 0 i = 2; } @@ -21,7 +21,7 @@ void func(void) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+5]]:2 = #0 // CHECK-NEXT: func2 void func2(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+5]]:2 = #0 int i = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:10 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:10 = 0 MACRO_1; // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE+2]]:2 = 0 i = 2; } @@ -31,8 +31,8 @@ void func2(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+5]]:2 = #0 // CHECK-NEXT: func3 void func3(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+3]]:2 = #0 - MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = #0 - MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = #0 + MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = 0 + MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:3 -> [[@LINE]]:10 = 0 } // CHECK-NEXT: File 1, 4:17 -> 4:22 = #0 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #0 @@ -45,7 +45,7 @@ void func4(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+8]]:2 = #0 // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1 // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:14 = #2, (#1 - #2) // CHECK-NEXT: Gap,File 0, [[@LINE-3]]:15 -> [[@LINE+1]]:7 = #2 - MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = #2 + MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = 0 } // CHECK-NEXT: File 1, 4:17 -> 4:22 = #2 // CHECK-NOT: File 1 @@ -56,9 +56,9 @@ void func5(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+6]]:2 = #0 if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:12 = #1, (#0 - #1) // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:13 -> [[@LINE+1]]:5 = #1 - MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1 + MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = 0 } -// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1 +// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = 0 // CHECK-NEXT: File 2, 4:17 -> 4:22 = #1 // CHECK-NEXT: func6 @@ -69,7 +69,7 @@ void func6(unsigned count) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+6]]: // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:17 -> [[@LINE+1]]:9 = #2 GOTO begin; // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:19 = #2 } -// CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = #2 +// CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:13 = 0 // CHECK-NEXT: File 1, 7:14 -> 7:18 = #2 // Regression test for gap region between macros. @@ -80,10 +80,10 @@ void func7(void) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+6]]:2 = #0 int kk,ll; // CHECK-NEXT: File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:8 = #0 if (k) // CHECK-NEXT: Branch,File 0, [[@LINE]]:7 -> [[@LINE]]:8 = #1 m(k); // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:9 -> [[@LINE]]:5 = #1 - else // CHECK-NEXT: Expansion,File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:6 = #0 + else // CHECK-NEXT: Expansion,File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:6 = 0 l = m(l); // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:7 -> [[@LINE]]:5 = (#0 - #1) } // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = (#0 - #1) - // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:10 = (#0 - #1) + // CHECK-NEXT: Expansion,File 0, [[@LINE-2]]:9 -> [[@LINE-2]]:10 = 0 // CHECK-NEXT: File 1, [[@LINE-9]]:14 -> [[@LINE-9]]:18 = #0 // CHECK-NEXT: File 1, [[@LINE-10]]:14 -> [[@LINE-10]]:17 = #1 // CHECK-NEXT: File 2, [[@LINE-11]]:14 -> [[@LINE-11]]:17 = (#0 - #1) diff --git a/clang/test/CoverageMapping/macroscopes.cpp b/clang/test/CoverageMapping/macroscopes.cpp index 88a72116fa7dc..d81a481c06cd7 100644 --- a/clang/test/CoverageMapping/macroscopes.cpp +++ b/clang/test/CoverageMapping/macroscopes.cpp @@ -37,49 +37,49 @@ // CHECK-NEXT: File 0, [[@LINE+1]]:12 -> {{[0-9]+}}:2 = #0 int main() { int x = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:17 = 0 // CHECK-NEXT: File 0, [[@LINE+1]]:17 -> [[@LINE+7]]:15 = #1 starts_a_scope x = x; - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:14 = #1 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:5 -> [[@LINE+1]]:14 = 0 some_code x = x; - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = #1 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:15 = 0 ends_a_scope - // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:3 -> [[@LINE+4]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+4]]:3 -> [[@LINE+4]]:17 = 0 // CHECK-NEXT: File 0, [[@LINE+3]]:17 -> [[@LINE+5]]:15 = #4 - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:14 = #4 - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #4 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:14 = 0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = 0 starts_a_scope some_code ends_a_scope - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = 0 // CHECK-NEXT: File 0, [[@LINE+2]]:17 -> [[@LINE+3]]:15 = #7 - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:15 = #7 + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:15 = 0 starts_a_scope ends_a_scope - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:17 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+2]]:17 -> [[@LINE+3]]:5 = #8 - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:16 = #8 + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:16 = 0 starts_a_while simple_stmt; x = 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:17 = 0 // CHECK-NEXT: Gap,File 0, [[@LINE+4]]:17 -> [[@LINE+4]]:18 = #9 // CHECK-NEXT: File 0, [[@LINE+3]]:18 -> [[@LINE+5]]:15 = #9 - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = #9 - // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = #9 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:5 -> [[@LINE+3]]:16 = 0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+3]]:3 -> [[@LINE+3]]:15 = 0 starts_a_while { simple_stmt; ends_a_scope - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:17 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:17 = 0 macro_with_for - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:19 = #0 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:19 = 0 macro_with_while return 0; diff --git a/clang/test/CoverageMapping/mcdc-scratch-space.c b/clang/test/CoverageMapping/mcdc-scratch-space.c index 60e456948a518..b5252d6c5d406 100644 --- a/clang/test/CoverageMapping/mcdc-scratch-space.c +++ b/clang/test/CoverageMapping/mcdc-scratch-space.c @@ -19,7 +19,7 @@ int builtin_macro1(int a) { // CHECK: pre0: int pre0(int pre_a, int b_post) { // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:20 = M:3, C:2 - // CHECK: Expansion,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:14 = #0 (Expanded file = 1) + // CHECK: Expansion,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:14 = 0 (Expanded file = 1) return (PRE(a) && b_post); // CHECK: Branch,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:20 = #2, (#1 - #2) [2,0,0] @@ -31,11 +31,11 @@ int pre0(int pre_a, int b_post) { // CHECK: pre1: int pre1(int pre_a, int b_post) { // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:20 = M:3, C:2 - // CHECK: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:14 = #0 (Expanded file = 1) + // CHECK: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:14 = 0 (Expanded file = 1) // CHECK: Branch,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #2, (#1 - #2) [2,0,0] return (PRE(foo) && b_post); - // CHECK: Expansion,File 1, 17:16 -> 17:20 = #0 (Expanded file = 2) + // CHECK: Expansion,File 1, 17:16 -> 17:20 = 0 (Expanded file = 2) // CHECK: Branch,File 2, 29:17 -> 29:22 = #1, (#0 - #1) [1,2,0] } @@ -47,7 +47,7 @@ int post0(int pre_a, int b_post) { // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:16 = (#0 - #1), #1 [1,0,2] return (pre_a || POST(b)); - // CHECK: Expansion,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:18 = #1 (Expanded file = 1) + // CHECK: Expansion,File 0, [[@LINE-1]]:14 -> [[@LINE-1]]:18 = 0 (Expanded file = 1) // CHECK: Branch,File 1, [[@LINE-9]]:17 -> [[@LINE-9]]:20 = (#1 - #2), #2 [2,0,0] } @@ -60,6 +60,6 @@ int post1(int pre_a, int b_post) { // CHECK: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:18 = 0 (Expanded file = 1) return (pre_a || POST(bar)); - // CHECK: Expansion,File 1, 42:17 -> 42:18 = #1 (Expanded file = 2) + // CHECK: Expansion,File 1, 42:17 -> 42:18 = 0 (Expanded file = 2) // CHECK: Branch,File 2, 54:18 -> 54:24 = (#1 - #2), #2 [2,0,0] } diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp index cb1c8743c36e8..b2fa7af5872c1 100644 --- a/clang/test/CoverageMapping/mcdc-system-headers.cpp +++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp @@ -16,7 +16,7 @@ // CHECK: _Z5func0i: int func0(int a) { // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:3, C:2 - // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1) + // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = 0 (Expanded file = 1) // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, 0 [1,2,0] return (CONST && a); // CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) [2,0,0] @@ -28,7 +28,7 @@ int func1(int a, int b) { // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:3, C:2 // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 [1,0,2] return (a || EXPR1(b)); - // W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded file = 1) + // W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = 0 (Expanded file = 1) // W_SYS: Branch,File 1, [[@LINE-24]]:18 -> [[@LINE-24]]:21 = (#1 - #2), #2 [2,0,0] // X_SYS: Branch,File 0, [[@LINE-3]]:16 -> [[@LINE-3]]:16 = (#1 - #2), #2 [2,0,0] } @@ -37,8 +37,8 @@ int func1(int a, int b) { int func2(int a, int b) { // W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:4, C:3 // X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:3, C:2 - // W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded file = 1) - // W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded file = 2) + // W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = 0 (Expanded file = 1) + // W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = 0 (Expanded file = 2) // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) [1,2,0] return (EXPR2(a) && EXPR1(a)); // W_SYS: Branch,File 1, [[@LINE-35]]:19 -> [[@LINE-35]]:22 = #3, (#0 - #3) [1,3,0] diff --git a/clang/test/CoverageMapping/moremacros.c b/clang/test/CoverageMapping/moremacros.c index 64e5c62bfac37..aeda4e81699bd 100644 --- a/clang/test/CoverageMapping/moremacros.c +++ b/clang/test/CoverageMapping/moremacros.c @@ -12,18 +12,18 @@ int main(int argc, const char *argv[]) { // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #2, (#0 - #2) // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #2 - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #2 + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = 0 // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+4]]:8 = #2 if (!argc) LBRAC return 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #2 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = 0 RBRAC // CHECK-NEXT: [[@LINE]]:8 -> [[@LINE+8]]:3 = (#0 - #2) // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+17]]:2 = (#0 - #2) // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:12 = (#0 - #2) // CHECK-NEXT: Branch,File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:12 = #3, ((#0 - #2) - #3) // CHECK-NEXT: Gap,File 0, [[@LINE+3]]:13 -> [[@LINE+3]]:14 = #3 - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = #3 + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:19 = 0 // CHECK-NEXT: File 0, [[@LINE+1]]:19 -> [[@LINE+3]]:4 = #3 if (!argc) LBRAC return 0; @@ -34,7 +34,7 @@ int main(int argc, const char *argv[]) { // CHECK: File 0, [[@LINE+1]]:14 -> [[@LINE+4]]:8 = #4 if (!argc) { return 0; - // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = #4 + // CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:3 -> [[@LINE+1]]:8 = 0 RBRAC } diff --git a/clang/test/CoverageMapping/switchmacro.c b/clang/test/CoverageMapping/switchmacro.c index 4c98cc7d9403a..e65529a33d3bb 100644 --- a/clang/test/CoverageMapping/switchmacro.c +++ b/clang/test/CoverageMapping/switchmacro.c @@ -11,7 +11,7 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 = #3, (#2 - #3) return 0; // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3 // CHECK-NEXT: File 0, [[@LINE-1]]:16 -> [[@LINE+3]]:5 = (#2 - #3) - // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:8 = (#2 - #3) (Expanded file = 1) + // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:5 -> [[@LINE+2]]:8 = 0 (Expanded file = 1) // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3) FOO(1); case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:13 = ((#2 + #4) - #3) @@ -41,7 +41,7 @@ default: ; #define START2 switch (0) default: void baz(void) { for (;;) - START2 return; // CHECK: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:11 = #1 (Expanded file = 1) + START2 return; // CHECK: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:11 = 0 (Expanded file = 1) } int main(int argc, const char *argv[]) { diff --git a/clang/test/CoverageMapping/trymacro.cpp b/clang/test/CoverageMapping/trymacro.cpp index 22de2ccb07769..6876908be6cdc 100644 --- a/clang/test/CoverageMapping/trymacro.cpp +++ b/clang/test/CoverageMapping/trymacro.cpp @@ -19,7 +19,7 @@ CATCH(...) {} // CHECK: [[@LINE]]:12 -> [[@LINE]]:14 = #2 // CHECK: Z3fn4v: #define TRY2 try { // CHECK-DAG: File 1, [[@LINE]]:18 -> [[@LINE]]:19 = #1 -void fn4() TRY2 // CHECK-DAG: Expansion,File 0, [[@LINE]]:12 -> [[@LINE]]:16 = #1 (Expanded file = 1) +void fn4() TRY2 // CHECK-DAG: Expansion,File 0, [[@LINE]]:12 -> [[@LINE]]:16 = 0 (Expanded file = 1) for (;;) return; } @@ -27,10 +27,10 @@ catch (...) {} // CHECK: Z3fn5v: #define TRY3 try { return; } catch (...) // CHECK-DAG: File 2, [[@LINE]]:18 -> [[@LINE]]:29 = #1 -#define TRY4 try { TRY3 { return; } } catch (...) // CHECK-DAG: Expansion,File 1, [[@LINE]]:20 -> [[@LINE]]:24 = #1 (Expanded file = 2) +#define TRY4 try { TRY3 { return; } } catch (...) // CHECK-DAG: Expansion,File 1, [[@LINE]]:20 -> [[@LINE]]:24 = 0 (Expanded file = 2) void fn5() { for (;;) { - TRY4 { return; } // CHECK-DAG: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:9 = #1 (Expanded file = 1) + TRY4 { return; } // CHECK-DAG: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:9 = 0 (Expanded file = 1) } // CHECK-DAG: File 0, [[@LINE-1]]:10 -> [[@LINE-1]]:21 = #5 } diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 8c5eae9015abe..5cfd4330479ad 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -704,6 +704,8 @@ struct CountedRegionEmitter { /// Evaluated Counters. std::map<Counter, uint64_t> CounterValues; + /// Induced Counter values for Expansions. + DenseMap<const CounterMappingRegion *, uint64_t> ExpansionCounterValues; /// Decisions are nestable. SmallVector<DecisionRecord, 1> DecisionStack; @@ -746,18 +748,20 @@ struct CountedRegionEmitter { } /// Evaluate C and store its evaluated Value into CounterValues. - Error evaluateAndCacheCounter(Counter C) { - if (CounterValues.count(C) > 0) - return Error::success(); + Expected<uint64_t> evaluateAndCacheCounter(Counter C) { + auto C1 = CounterValues.find(C); + if (C1 != CounterValues.end()) + return C1->second; // Cached auto ValueOrErr = Ctx.evaluate(C); if (!ValueOrErr) return ValueOrErr.takeError(); CounterValues[C] = *ValueOrErr; - return Error::success(); + return ValueOrErr; } - Error walk(unsigned Idx) { + Expected<uint64_t> walk(unsigned Idx) { + std::optional<uint64_t> FirstCnt; assert(Idx < Files.size()); unsigned B = (Idx == 0 ? 0 : Files[Idx - 1].LastIndex); unsigned E = Files[Idx].LastIndex; @@ -768,12 +772,27 @@ struct CountedRegionEmitter { if (Region.FileID != Idx) break; - if (Region.Kind == CounterMappingRegion::ExpansionRegion) - if (auto E = walk(Region.ExpandedFileID)) - return E; + if (Region.Kind == CounterMappingRegion::ExpansionRegion) { + auto ExpandedCntOrErr = walk(Region.ExpandedFileID); + if (!ExpandedCntOrErr) + return ExpandedCntOrErr.takeError(); - if (auto E = evaluateAndCacheCounter(Region.Count)) - return E; + // Expansion doesn't have Counters. + assert(Region.Count.isZero()); + ExpansionCounterValues[&Region] = *ExpandedCntOrErr; + // Propagate Expanded Count to parent. + if (!FirstCnt) + FirstCnt = *ExpandedCntOrErr; + + continue; + } + + auto TrueCntOrErr = evaluateAndCacheCounter(Region.Count); + if (!TrueCntOrErr) + return TrueCntOrErr.takeError(); + // Propagate 1st Count to parent. + if (!FirstCnt) + FirstCnt = *TrueCntOrErr; if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) { // Start the new Decision on the stack. @@ -797,13 +816,13 @@ struct CountedRegionEmitter { // Evaluate FalseCount // It may have the Counter in Branches, or Zero. - if (auto E = evaluateAndCacheCounter(Region.FalseCount)) - return E; + if (auto E = evaluateAndCacheCounter(Region.FalseCount); !E) + return E.takeError(); } assert((Idx != 0 || DecisionStack.empty()) && "Decision wasn't closed"); - return Error::success(); + return (FirstCnt ? *FirstCnt : 0); } Error emitCountedRegions() { @@ -812,8 +831,8 @@ struct CountedRegionEmitter { // - Emit MCDCRecords for (auto [I, F] : enumerate(Files)) { if (!F.IsExpanded) - if (auto E = walk(I)) - return E; + if (auto E = walk(I); !E) + return E.takeError(); } assert(Visited.size() == Files.size() && "Dangling FileID"); @@ -821,6 +840,14 @@ struct CountedRegionEmitter { for (const auto &Region : Record.MappingRegions) { if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) continue; // Don't emit. + + if (auto EI = ExpansionCounterValues.find(&Region); + EI != ExpansionCounterValues.end()) { + // Adopt the Counter value induced in the Recorder. + Function.pushRegion(Region, EI->second, 0); + continue; + } + // Adopt values from the CounterValues. // FalseCount may be Zero unless Branches. Function.pushRegion(Region, CounterValues[Region.Count], diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index cdf4412c6477a..d15355dc6e07d 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -437,28 +437,6 @@ Error RawCoverageMappingReader::read() { return Err; } - // Set the counters for the expansion regions. - // i.e. Counter of expansion region = counter of the first region - // from the expanded file. - // Perform multiple passes to correctly propagate the counters through - // all the nested expansion regions. - SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; - FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); - for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { - for (auto &R : MappingRegions) { - if (R.Kind != CounterMappingRegion::ExpansionRegion) - continue; - assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); - FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; - } - for (auto &R : MappingRegions) { - if (FileIDExpansionRegionMapping[R.FileID]) { - FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; - FileIDExpansionRegionMapping[R.FileID] = nullptr; - } - } - } - return Error::success(); } diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp index 46f881ecddb5f..945d0acdc7026 100644 --- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp +++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp @@ -707,13 +707,16 @@ TEST_P(CoverageMappingTest, expansion_gets_first_counter) { addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1); addExpansionCMR("bar", "foo", 3, 3, 3, 3); - writeAndReadCoverageRegions(); - ASSERT_EQ(1u, OutputFunctions.size()); - OutputFunctionCoverageData &Output = OutputFunctions.back(); + ProfileWriter.addRecord({"func", 0x1234, {1, 2, 4}}, Err); + EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); + + auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); + ASSERT_EQ(1u, std::distance(FunctionRecords.begin(), FunctionRecords.end())); - ASSERT_EQ(CounterMappingRegion::ExpansionRegion, Output.Regions[2].Kind); - ASSERT_EQ(Counter::getCounter(2), Output.Regions[2].Count); - ASSERT_EQ(3U, Output.Regions[2].LineStart); + const auto &CR = (*FunctionRecords.begin()).CountedRegions; + ASSERT_EQ(CounterMappingRegion::ExpansionRegion, CR[2].Kind); + ASSERT_EQ(4u, CR[2].ExecutionCount); + ASSERT_EQ(3U, CR[2].LineStart); } TEST_P(CoverageMappingTest, basic_coverage_iteration) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits