Skip to content

Commit f78bc60

Browse files
committed
ConstraintSystem: replace data structure with Matrix
ConstraintSystem currently stores constraints in a vector-of-vectors, performing inefficient memory operations on it, as part of its operation. Replace this data structure with the newly-minted Matrix, using MatrixView to eliminate row-swaps and truncation of the underlying storage. Since Matrix requires knowing an upper bounds on the number of columns ahead-of-time, add a cl::opt to ConstraintElimination upper-bounding this, and change addVariableRowFill to not add constraints whose length exceeds this upper bound.
1 parent ef1851a commit f78bc60

File tree

3 files changed

+76
-42
lines changed

3 files changed

+76
-42
lines changed

llvm/include/llvm/Analysis/ConstraintSystem.h

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,19 @@
99
#ifndef LLVM_ANALYSIS_CONSTRAINTSYSTEM_H
1010
#define LLVM_ANALYSIS_CONSTRAINTSYSTEM_H
1111

12-
#include "llvm/ADT/APInt.h"
13-
#include "llvm/ADT/ArrayRef.h"
1412
#include "llvm/ADT/DenseMap.h"
15-
#include "llvm/ADT/SmallVector.h"
13+
#include "llvm/ADT/Matrix.h"
1614
#include "llvm/Support/MathExtras.h"
1715

18-
#include <string>
19-
2016
namespace llvm {
2117

2218
class Value;
2319
class ConstraintSystem {
2420
struct Entry {
25-
int64_t Coefficient;
26-
uint16_t Id;
21+
int64_t Coefficient = 0;
22+
uint16_t Id = 0;
2723

24+
Entry() = default;
2825
Entry(int64_t Coefficient, uint16_t Id)
2926
: Coefficient(Coefficient), Id(Id) {}
3027
};
@@ -48,7 +45,10 @@ class ConstraintSystem {
4845
/// Current linear constraints in the system.
4946
/// An entry of the form c0, c1, ... cn represents the following constraint:
5047
/// c0 >= v0 * c1 + .... + v{n-1} * cn
51-
SmallVector<SmallVector<Entry, 8>, 4> Constraints;
48+
MatrixStorage<Entry, 64> Constraints;
49+
50+
/// Constraints is only ever manipulated via this View.
51+
JaggedArrayView<Entry, 16, 64> View;
5252

5353
/// A map of variables (IR values) to their corresponding index in the
5454
/// constraint system.
@@ -64,18 +64,40 @@ class ConstraintSystem {
6464
SmallVector<std::string> getVarNamesList() const;
6565

6666
public:
67-
ConstraintSystem() {}
68-
ConstraintSystem(ArrayRef<Value *> FunctionArgs) {
67+
// The Matrix Constraints should always be initialized with an upper-bound
68+
// number of columns. The default constructor hard-codes an upper-bound of 6,
69+
// as it is only used in unit tests, and not in the actual
70+
// ConstraintElimination Analysis.
71+
ConstraintSystem() : Constraints(6), View(Constraints) {}
72+
73+
// This constructor is used by ConstraintElimination, inside ConstraintInfo.
74+
// Unfortunately, due to calls to addFact, that adds local variables, it is
75+
// impossible to know how many local variables there are in advance.
76+
// ConstraintElimination has a fixed upper-bound on the number of columns,
77+
// configurable as a cl::opt, so use that number, and don't add the constraint
78+
// if it exceeds that number.
79+
ConstraintSystem(ArrayRef<Value *> FunctionArgs, size_t NCols)
80+
: Constraints(NCols), View(Constraints) {
6981
NumVariables += FunctionArgs.size();
7082
for (auto *Arg : FunctionArgs) {
7183
Value2Index.insert({Arg, Value2Index.size() + 1});
7284
}
7385
}
74-
ConstraintSystem(const DenseMap<Value *, unsigned> &Value2Index)
75-
: NumVariables(Value2Index.size()), Value2Index(Value2Index) {}
86+
87+
// This constructor is only used by the dump function in
88+
// ConstraintElimination.
89+
ConstraintSystem(const DenseMap<Value *, unsigned> &Value2Index,
90+
unsigned NVars)
91+
: NumVariables(Value2Index.size()),
92+
Constraints(std::max(Value2Index.size(), NVars)), View(Constraints),
93+
Value2Index(Value2Index) {}
94+
95+
ConstraintSystem(const ConstraintSystem &Other)
96+
: NumVariables(Other.NumVariables), Constraints(Other.Constraints),
97+
View(Other.View, Constraints), Value2Index(Other.Value2Index) {}
7698

7799
bool addVariableRow(ArrayRef<int64_t> R) {
78-
assert(Constraints.empty() || R.size() == NumVariables);
100+
assert(View.empty() || R.size() == NumVariables);
79101
// If all variable coefficients are 0, the constraint does not provide any
80102
// usable information.
81103
if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
@@ -87,9 +109,10 @@ class ConstraintSystem {
87109
continue;
88110
NewRow.emplace_back(C, Idx);
89111
}
90-
if (Constraints.empty())
112+
if (View.empty())
91113
NumVariables = R.size();
92-
Constraints.push_back(std::move(NewRow));
114+
115+
View.addRow(std::move(NewRow));
93116
return true;
94117
}
95118

@@ -104,6 +127,11 @@ class ConstraintSystem {
104127
if (all_of(ArrayRef(R).drop_front(1), [](int64_t C) { return C == 0; }))
105128
return false;
106129

130+
// There is no correctness issue if we don't add a constraint, for whatever
131+
// reason.
132+
if (R.size() > Constraints.getNumCols())
133+
return false;
134+
107135
NumVariables = std::max(R.size(), NumVariables);
108136
return addVariableRow(R);
109137
}
@@ -145,21 +173,21 @@ class ConstraintSystem {
145173
bool isConditionImplied(SmallVector<int64_t, 8> R) const;
146174

147175
SmallVector<int64_t> getLastConstraint() const {
148-
assert(!Constraints.empty() && "Constraint system is empty");
176+
assert(!View.empty() && "Constraint system is empty");
149177
SmallVector<int64_t> Result(NumVariables, 0);
150-
for (auto &Entry : Constraints.back())
178+
for (auto &Entry : View.lastRow())
151179
Result[Entry.Id] = Entry.Coefficient;
152180
return Result;
153181
}
154182

155-
void popLastConstraint() { Constraints.pop_back(); }
183+
void popLastConstraint() { View.dropLastRow(); }
156184
void popLastNVariables(unsigned N) {
157185
assert(NumVariables > N);
158186
NumVariables -= N;
159187
}
160188

161189
/// Returns the number of rows in the constraint system.
162-
unsigned size() const { return Constraints.size(); }
190+
unsigned size() const { return View.getRowSpan(); }
163191

164192
/// Print the constraints in the system.
165193
void dump() const;

llvm/lib/Analysis/ConstraintSystem.cpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Analysis/ConstraintSystem.h"
10+
#include "llvm/ADT/Matrix.h"
1011
#include "llvm/ADT/SmallVector.h"
11-
#include "llvm/Support/MathExtras.h"
1212
#include "llvm/ADT/StringExtras.h"
1313
#include "llvm/IR/Value.h"
1414
#include "llvm/Support/Debug.h"
15+
#include "llvm/Support/MathExtras.h"
1516

1617
#include <string>
1718

@@ -26,37 +27,38 @@ bool ConstraintSystem::eliminateUsingFM() {
2627
// analysis."
2728
// Supercomputing'91: Proceedings of the 1991 ACM/
2829
// IEEE conference on Supercomputing. IEEE, 1991.
29-
assert(!Constraints.empty() &&
30+
assert(!View.empty() &&
3031
"should only be called for non-empty constraint systems");
3132

3233
unsigned LastIdx = NumVariables - 1;
3334

3435
// First, either remove the variable in place if it is 0 or add the row to
3536
// RemainingRows and remove it from the system.
36-
SmallVector<SmallVector<Entry, 8>, 4> RemainingRows;
37-
for (unsigned R1 = 0; R1 < Constraints.size();) {
38-
SmallVector<Entry, 8> &Row1 = Constraints[R1];
37+
MatrixStorage<Entry, 32> RemainingRows(View.getMaxColSpan());
38+
JaggedArrayView<Entry, 8, 32> RemainingRowsView{RemainingRows};
39+
for (unsigned R1 = 0; R1 < View.getRowSpan();) {
40+
auto &Row1 = View[R1];
3941
if (getLastCoefficient(Row1, LastIdx) == 0) {
4042
if (Row1.size() > 0 && Row1.back().Id == LastIdx)
4143
Row1.pop_back();
4244
R1++;
4345
} else {
44-
std::swap(Constraints[R1], Constraints.back());
45-
RemainingRows.push_back(std::move(Constraints.back()));
46-
Constraints.pop_back();
46+
std::swap(View[R1], View.lastRow());
47+
RemainingRowsView.addRow(View.lastRow());
48+
View.dropLastRow();
4749
}
4850
}
4951

5052
// Process rows where the variable is != 0.
51-
unsigned NumRemainingConstraints = RemainingRows.size();
53+
unsigned NumRemainingConstraints = RemainingRowsView.getRowSpan();
5254
for (unsigned R1 = 0; R1 < NumRemainingConstraints; R1++) {
5355
// FIXME do not use copy
5456
for (unsigned R2 = R1 + 1; R2 < NumRemainingConstraints; R2++) {
5557
if (R1 == R2)
5658
continue;
5759

58-
int64_t UpperLast = getLastCoefficient(RemainingRows[R2], LastIdx);
59-
int64_t LowerLast = getLastCoefficient(RemainingRows[R1], LastIdx);
60+
int64_t UpperLast = getLastCoefficient(RemainingRowsView[R2], LastIdx);
61+
int64_t LowerLast = getLastCoefficient(RemainingRowsView[R1], LastIdx);
6062
assert(
6163
UpperLast != 0 && LowerLast != 0 &&
6264
"RemainingRows should only contain rows where the variable is != 0");
@@ -74,8 +76,8 @@ bool ConstraintSystem::eliminateUsingFM() {
7476
SmallVector<Entry, 8> NR;
7577
unsigned IdxUpper = 0;
7678
unsigned IdxLower = 0;
77-
auto &LowerRow = RemainingRows[LowerR];
78-
auto &UpperRow = RemainingRows[UpperR];
79+
auto &LowerRow = RemainingRowsView[LowerR];
80+
auto &UpperRow = RemainingRowsView[UpperR];
7981
while (true) {
8082
if (IdxUpper >= UpperRow.size() || IdxLower >= LowerRow.size())
8183
break;
@@ -112,9 +114,9 @@ bool ConstraintSystem::eliminateUsingFM() {
112114
}
113115
if (NR.empty())
114116
continue;
115-
Constraints.push_back(std::move(NR));
117+
View.addRow(std::move(NR));
116118
// Give up if the new system gets too big.
117-
if (Constraints.size() > 500)
119+
if (size() > 500)
118120
return false;
119121
}
120122
}
@@ -124,15 +126,15 @@ bool ConstraintSystem::eliminateUsingFM() {
124126
}
125127

126128
bool ConstraintSystem::mayHaveSolutionImpl() {
127-
while (!Constraints.empty() && NumVariables > 1) {
129+
while (!View.empty() && NumVariables > 1) {
128130
if (!eliminateUsingFM())
129131
return true;
130132
}
131133

132-
if (Constraints.empty() || NumVariables > 1)
134+
if (View.empty() || NumVariables > 1)
133135
return true;
134136

135-
return all_of(Constraints, [](auto &R) {
137+
return all_of(View, [](auto &R) {
136138
if (R.empty())
137139
return true;
138140
if (R[0].Id == 0)
@@ -158,10 +160,10 @@ SmallVector<std::string> ConstraintSystem::getVarNamesList() const {
158160

159161
void ConstraintSystem::dump() const {
160162
#ifndef NDEBUG
161-
if (Constraints.empty())
163+
if (View.empty())
162164
return;
163165
SmallVector<std::string> Names = getVarNamesList();
164-
for (const auto &Row : Constraints) {
166+
for (const auto &Row : View) {
165167
SmallVector<std::string, 16> Parts;
166168
for (const Entry &E : Row) {
167169
if (E.Id >= NumVariables)

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#include "llvm/Transforms/Utils/Cloning.h"
4141
#include "llvm/Transforms/Utils/ValueMapper.h"
4242

43-
#include <cmath>
4443
#include <optional>
4544
#include <string>
4645

@@ -57,6 +56,10 @@ static cl::opt<unsigned>
5756
MaxRows("constraint-elimination-max-rows", cl::init(500), cl::Hidden,
5857
cl::desc("Maximum number of rows to keep in constraint system"));
5958

59+
static cl::opt<unsigned> MaxColumns(
60+
"constraint-elimination-max-cols", cl::init(16), cl::Hidden,
61+
cl::desc("Maximum number of columns to keep in constraint system"));
62+
6063
static cl::opt<bool> DumpReproducers(
6164
"constraint-elimination-dump-reproducers", cl::init(false), cl::Hidden,
6265
cl::desc("Dump IR to reproduce successful transformations."));
@@ -274,7 +277,8 @@ class ConstraintInfo {
274277

275278
public:
276279
ConstraintInfo(const DataLayout &DL, ArrayRef<Value *> FunctionArgs)
277-
: UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
280+
: UnsignedCS(FunctionArgs, MaxColumns),
281+
SignedCS(FunctionArgs, MaxColumns), DL(DL) {
278282
auto &Value2Index = getValue2Index(false);
279283
// Add Arg > -1 constraints to unsigned system for all function arguments.
280284
for (Value *Arg : FunctionArgs) {
@@ -894,7 +898,7 @@ void ConstraintInfo::transferToOtherSystem(
894898

895899
static void dumpConstraint(ArrayRef<int64_t> C,
896900
const DenseMap<Value *, unsigned> &Value2Index) {
897-
ConstraintSystem CS(Value2Index);
901+
ConstraintSystem CS(Value2Index, C.size());
898902
CS.addVariableRowFill(C);
899903
CS.dump();
900904
}

0 commit comments

Comments
 (0)