diff options
Diffstat (limited to 'llvm/lib/ProfileData/Coverage/CoverageMapping.cpp')
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 64 |
1 files changed, 52 insertions, 12 deletions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index e46b735..2a4ed54 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -223,19 +223,59 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const { } unsigned CounterMappingContext::getMaxCounterID(const Counter &C) const { - switch (C.getKind()) { - case Counter::Zero: - return 0; - case Counter::CounterValueReference: - return C.getCounterID(); - case Counter::Expression: { - if (C.getExpressionID() >= Expressions.size()) - return 0; - const auto &E = Expressions[C.getExpressionID()]; - return std::max(getMaxCounterID(E.LHS), getMaxCounterID(E.RHS)); - } + struct StackElem { + Counter ICounter; + int64_t LHS = 0; + enum { + KNeverVisited = 0, + KVisitedOnce = 1, + KVisitedTwice = 2, + } VisitCount = KNeverVisited; + }; + + std::stack<StackElem> CounterStack; + CounterStack.push({C}); + + int64_t LastPoppedValue; + + while (!CounterStack.empty()) { + StackElem &Current = CounterStack.top(); + + switch (Current.ICounter.getKind()) { + case Counter::Zero: + LastPoppedValue = 0; + CounterStack.pop(); + break; + case Counter::CounterValueReference: + LastPoppedValue = Current.ICounter.getCounterID(); + CounterStack.pop(); + break; + case Counter::Expression: { + if (Current.ICounter.getExpressionID() >= Expressions.size()) { + LastPoppedValue = 0; + CounterStack.pop(); + } else { + const auto &E = Expressions[Current.ICounter.getExpressionID()]; + if (Current.VisitCount == StackElem::KNeverVisited) { + CounterStack.push(StackElem{E.LHS}); + Current.VisitCount = StackElem::KVisitedOnce; + } else if (Current.VisitCount == StackElem::KVisitedOnce) { + Current.LHS = LastPoppedValue; + CounterStack.push(StackElem{E.RHS}); + Current.VisitCount = StackElem::KVisitedTwice; + } else { + int64_t LHS = Current.LHS; + int64_t RHS = LastPoppedValue; + LastPoppedValue = std::max(LHS, RHS); + CounterStack.pop(); + } + } + break; + } + } } - llvm_unreachable("Unhandled CounterKind"); + + return LastPoppedValue; } void FunctionRecordIterator::skipOtherFiles() { |