[llvm] r218879  InstrProf: Don't keep a large sparse list around just to zero it
Justin Bogner
mail at justinbogner.com
Thu Oct 2 09:04:03 PDT 2014
Author: bogner
Date: Thu Oct 2 11:04:03 2014
New Revision: 218879
URL: http://llvm.org/viewvc/llvmproject?rev=218879&view=rev
Log:
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.
Modified:
llvm/trunk/include/llvm/ProfileData/CoverageMapping.h
llvm/trunk/lib/ProfileData/CoverageMapping.cpp
Modified: llvm/trunk/include/llvm/ProfileData/CoverageMapping.h
URL: http://llvm.org/viewvc/llvmproject/llvm/trunk/include/llvm/ProfileData/CoverageMapping.h?rev=218879&r1=218878&r2=218879&view=diff
==============================================================================
 llvm/trunk/include/llvm/ProfileData/CoverageMapping.h (original)
+++ llvm/trunk/include/llvm/ProfileData/CoverageMapping.h Thu Oct 2 11:04:03 2014
@@ 103,8 +103,6 @@ struct CounterExpression {
class CounterExpressionBuilder {
/// \brief A list of all the counter 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.
///
@@ 113,18 +111,19 @@ class CounterExpressionBuilder {
/// expression is added to the builder's collection of expressions.
Counter get(const CounterExpression &E);
 /// \brief Convert the expression tree represented by a counter
 /// into a polynomial in the form of K1Counter1 + .. + KNCounterN
 /// where K1 .. KN are integer constants that are stored in the Terms array.
 void extractTerms(Counter C, int Sign = 1);
+ /// \brief Gather the terms of the expression tree for processing.
+ ///
+ /// This collects each addition and subtraction referenced by the counter into
+ /// 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
/// by getting rid of algebraically redundant operations.
Counter simplify(Counter ExpressionTree);
public:
 CounterExpressionBuilder(unsigned NumCounterValues);

ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
/// \brief Return a counter that represents the expression
Modified: llvm/trunk/lib/ProfileData/CoverageMapping.cpp
URL: http://llvm.org/viewvc/llvmproject/llvm/trunk/lib/ProfileData/CoverageMapping.cpp?rev=218879&r1=218878&r2=218879&view=diff
==============================================================================
 llvm/trunk/lib/ProfileData/CoverageMapping.cpp (original)
+++ llvm/trunk/lib/ProfileData/CoverageMapping.cpp Thu Oct 2 11:04:03 2014
@@ 27,10 +27,6 @@ using namespace coverage;
#define DEBUG_TYPE "coveragemapping"
CounterExpressionBuilder::CounterExpressionBuilder(unsigned NumCounterValues) {
 Terms.resize(NumCounterValues);
}

Counter CounterExpressionBuilder::get(const CounterExpression &E) {
for (unsigned I = 0, S = Expressions.size(); I < S; ++I) {
if (Expressions[I] == E)
@@ 40,50 +36,68 @@ Counter CounterExpressionBuilder::get(co
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()) {
case Counter::Zero:
break;
case Counter::CounterValueReference:
 Terms[C.getCounterID()] += Sign;
+ Terms.push_back(std::make_pair(C.getCounterID(), Sign));
break;
case Counter::Expression:
const auto &E = Expressions[C.getExpressionID()];
 extractTerms(E.LHS, Sign);
 extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? Sign : Sign);
+ extractTerms(E.LHS, Sign, Terms);
+ extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? Sign : Sign,
+ Terms);
break;
}
}
Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
// Gather constant terms.
 for (auto &I : Terms)
 I = 0;
 extractTerms(ExpressionTree);
+ llvm::SmallVector<std::pair<unsigned, int>, 32> Terms;
+ extractTerms(ExpressionTree, +1, Terms);
+
+ // 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;
 // Create additions.
 // Note: the additions are created first
 // to avoid creation of a tree like ((0  X) + Y) instead of (Y  X).
 for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
 if (Terms[I] <= 0)
+ // Create additions. We do this before subtractions to avoid constructs like
+ // ((0  X) + Y), as opposed to (Y  X).
+ for (auto Term : Terms) {
+ if (Term.second <= 0)
continue;
 for (int J = 0; J < Terms[I]; ++J) {
+ for (int I = 0; I < Term.second; ++I)
if (C.isZero())
 C = Counter::getCounter(I);
+ C = Counter::getCounter(Term.first);
else
C = get(CounterExpression(CounterExpression::Add, C,
 Counter::getCounter(I)));
 }
+ Counter::getCounter(Term.first)));
}
// Create subtractions.
 for (unsigned I = 0, S = Terms.size(); I < S; ++I) {
 if (Terms[I] >= 0)
+ for (auto Term : Terms) {
+ if (Term.second >= 0)
continue;
 for (int J = 0; J < (Terms[I]); ++J)
+ for (int I = 0; I < Term.second; ++I)
C = get(CounterExpression(CounterExpression::Subtract, C,
 Counter::getCounter(I)));
+ Counter::getCounter(Term.first)));
}
return C;
}
More information about the llvmcommits
mailing list