InstrProf: Don't keep a large sparse list around just to zero it

The Terms vector here represented a polynomial of of all possible
counters, and is used to simplify expressions when generating coverage
mapping. There are a few problems with this:

1. Keeping the vector as a member is wasteful, since we clear it every
   time we use it.
2. Most expressions refer to a subset of the counters, so we end up
   iterating over a large number of zeros doing nothing a lot of the
   time.

This updates the user of the vector to store the terms locally, and
uses a sort and combine approach so that we only operate on counters
that are actually used in a given expression. For small cases this
makes very little difference, but in cases with a very large number of
counted regions this is a significant performance fix.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218879 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Justin Bogner
2014-10-02 16:04:03 +00:00
parent dafb357bb5
commit 1476756523
2 changed files with 45 additions and 32 deletions

View File

@@ -103,8 +103,6 @@ struct CounterExpression {
class CounterExpressionBuilder { class CounterExpressionBuilder {
/// \brief A list of all the counter expressions /// \brief A list of all the counter expressions
llvm::SmallVector<CounterExpression, 16> Expressions; llvm::SmallVector<CounterExpression, 16> Expressions;
/// \brief An array of terms used in expression simplification.
llvm::SmallVector<int, 16> Terms;
/// \brief Return the counter which corresponds to the given expression. /// \brief Return the counter which corresponds to the given expression.
/// ///
@@ -113,18 +111,19 @@ class CounterExpressionBuilder {
/// expression is added to the builder's collection of expressions. /// expression is added to the builder's collection of expressions.
Counter get(const CounterExpression &E); Counter get(const CounterExpression &E);
/// \brief Convert the expression tree represented by a counter /// \brief Gather the terms of the expression tree for processing.
/// into a polynomial in the form of K1Counter1 + .. + KNCounterN ///
/// where K1 .. KN are integer constants that are stored in the Terms array. /// This collects each addition and subtraction referenced by the counter into
void extractTerms(Counter C, int Sign = 1); /// a sequence that can be sorted and combined to build a simplified counter
/// expression.
void extractTerms(Counter C, int Sign,
SmallVectorImpl<std::pair<unsigned, int>> &Terms);
/// \brief Simplifies the given expression tree /// \brief Simplifies the given expression tree
/// by getting rid of algebraically redundant operations. /// by getting rid of algebraically redundant operations.
Counter simplify(Counter ExpressionTree); Counter simplify(Counter ExpressionTree);
public: public:
CounterExpressionBuilder(unsigned NumCounterValues);
ArrayRef<CounterExpression> getExpressions() const { return Expressions; } ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
/// \brief Return a counter that represents the expression /// \brief Return a counter that represents the expression

View File

@@ -27,10 +27,6 @@ using namespace coverage;
#define DEBUG_TYPE "coverage-mapping" #define DEBUG_TYPE "coverage-mapping"
CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
Terms.resize(NumCounterValues);
}
Counter CounterExpressionBuilder::get(const CounterExpression &E) { Counter CounterExpressionBuilder::get(const CounterExpression &E) {
for (unsigned I = 0, S = Expressions.size(); I < S; ++I) { for (unsigned I = 0, S = Expressions.size(); I < S; ++I) {
if (Expressions[I] == E) if (Expressions[I] == E)
@@ -40,50 +36,68 @@ Counter CounterExpressionBuilder::get(const CounterExpression &E) {
return Counter::getExpression(Expressions.size() - 1); return Counter::getExpression(Expressions.size() - 1);
} }
void CounterExpressionBuilder::extractTerms(Counter C, int Sign) { void CounterExpressionBuilder::extractTerms(
Counter C, int Sign, SmallVectorImpl<std::pair<unsigned, int>> &Terms) {
switch (C.getKind()) { switch (C.getKind()) {
case Counter::Zero: case Counter::Zero:
break; break;
case Counter::CounterValueReference: case Counter::CounterValueReference:
Terms[C.getCounterID()] += Sign; Terms.push_back(std::make_pair(C.getCounterID(), Sign));
break; break;
case Counter::Expression: case Counter::Expression:
const auto &E = Expressions[C.getExpressionID()]; const auto &E = Expressions[C.getExpressionID()];
extractTerms(E.LHS, Sign); extractTerms(E.LHS, Sign, Terms);
extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign); extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign,
Terms);
break; break;
} }
} }
Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
// Gather constant terms. // Gather constant terms.
for (auto &I : Terms) llvm::SmallVector<std::pair<unsigned, int>, 32> Terms;
I = 0; extractTerms(ExpressionTree, +1, Terms);
extractTerms(ExpressionTree);
// Group the terms by counter ID.
std::sort(Terms.begin(), Terms.end(),
[](const std::pair<unsigned, int> &LHS,
const std::pair<unsigned, int> &RHS) {
return LHS.first < RHS.first;
});
// Combine terms by counter ID to eliminate counters that sum to zero.
auto Prev = Terms.begin();
for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
if (I->first == Prev->first) {
Prev->second += I->second;
continue;
}
++Prev;
*Prev = *I;
}
Terms.erase(++Prev, Terms.end());
Counter C; Counter C;
// Create additions. // Create additions. We do this before subtractions to avoid constructs like
// Note: the additions are created first // ((0 - X) + Y), as opposed to (Y - X).
// to avoid creation of a tree like ((0 - X) + Y) instead of (Y - X). for (auto Term : Terms) {
for (unsigned I = 0, S = Terms.size(); I < S; ++I) { if (Term.second <= 0)
if (Terms[I] <= 0)
continue; continue;
for (int J = 0; J < Terms[I]; ++J) { for (int I = 0; I < Term.second; ++I)
if (C.isZero()) if (C.isZero())
C = Counter::getCounter(I); C = Counter::getCounter(Term.first);
else else
C = get(CounterExpression(CounterExpression::Add, C, C = get(CounterExpression(CounterExpression::Add, C,
Counter::getCounter(I))); Counter::getCounter(Term.first)));
}
} }
// Create subtractions. // Create subtractions.
for (unsigned I = 0, S = Terms.size(); I < S; ++I) { for (auto Term : Terms) {
if (Terms[I] >= 0) if (Term.second >= 0)
continue; continue;
for (int J = 0; J < (-Terms[I]); ++J) for (int I = 0; I < -Term.second; ++I)
C = get(CounterExpression(CounterExpression::Subtract, C, C = get(CounterExpression(CounterExpression::Subtract, C,
Counter::getCounter(I))); Counter::getCounter(Term.first)));
} }
return C; return C;
} }