1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
//===- Expressions.cpp - Expression Analysis Utilities ----------------------=//
//
// This file defines a package of expression analysis utilties:
//
// ClassifyExpression: Analyze an expression to determine the complexity of the
// expression, and which other variables it depends on.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/Expressions.h"
#include "llvm/Optimizations/ConstantHandling.h"
#include "llvm/Method.h"
#include "llvm/BasicBlock.h"
using namespace opt; // Get all the constant handling stuff
using namespace analysis;
class DefVal {
const ConstPoolInt * const Val;
const Type * const Ty;
protected:
inline DefVal(const ConstPoolInt *val, const Type *ty) : Val(val), Ty(ty) {}
public:
inline const Type *getType() const { return Ty; }
inline const ConstPoolInt *getVal() const { return Val; }
inline operator const ConstPoolInt * () const { return Val; }
inline const ConstPoolInt *operator->() const { return Val; }
};
struct DefZero : public DefVal {
inline DefZero(const ConstPoolInt *val, const Type *ty) : DefVal(val, ty) {}
inline DefZero(const ConstPoolInt *val) : DefVal(val, val->getType()) {}
};
struct DefOne : public DefVal {
inline DefOne(const ConstPoolInt *val, const Type *ty) : DefVal(val, ty) {}
};
// getIntegralConstant - Wrapper around the ConstPoolInt member of the same
// name. This method first checks to see if the desired constant is already in
// the constant pool. If it is, it is quickly recycled, otherwise a new one
// is allocated and added to the constant pool.
//
static ConstPoolInt *getIntegralConstant(unsigned char V, const Type *Ty) {
return ConstPoolInt::get(Ty, V);
}
static ConstPoolInt *getUnsignedConstant(uint64_t V, const Type *Ty) {
if (Ty->isPointerType()) Ty = Type::ULongTy;
return Ty->isSigned() ? ConstPoolSInt::get(Ty, V) : ConstPoolUInt::get(Ty, V);
}
// Add - Helper function to make later code simpler. Basically it just adds
// the two constants together, inserts the result into the constant pool, and
// returns it. Of course life is not simple, and this is no exception. Factors
// that complicate matters:
// 1. Either argument may be null. If this is the case, the null argument is
// treated as either 0 (if DefOne = false) or 1 (if DefOne = true)
// 2. Types get in the way. We want to do arithmetic operations without
// regard for the underlying types. It is assumed that the constants are
// integral constants. The new value takes the type of the left argument.
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
// is false, a null return value indicates a value of 0.
//
static const ConstPoolInt *Add(const ConstPoolInt *Arg1,
const ConstPoolInt *Arg2, bool DefOne) {
assert(Arg1 && Arg2 && "No null arguments should exist now!");
assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
// Actually perform the computation now!
ConstPoolVal *Result = *Arg1 + *Arg2;
assert(Result && Result->getType() == Arg1->getType() &&
"Couldn't perform addition!");
ConstPoolInt *ResultI = (ConstPoolInt*)Result;
// Check to see if the result is one of the special cases that we want to
// recognize...
if (ResultI->equalsInt(DefOne ? 1 : 0)) {
// Yes it is, simply delete the constant and return null.
delete ResultI;
return 0;
}
return ResultI;
}
inline const ConstPoolInt *operator+(const DefZero &L, const DefZero &R) {
if (L == 0) return R;
if (R == 0) return L;
return Add(L, R, false);
}
inline const ConstPoolInt *operator+(const DefOne &L, const DefOne &R) {
if (L == 0) {
if (R == 0)
return getIntegralConstant(2, L.getType());
else
return Add(getIntegralConstant(1, L.getType()), R, true);
} else if (R == 0) {
return Add(L, getIntegralConstant(1, L.getType()), true);
}
return Add(L, R, true);
}
// Mul - Helper function to make later code simpler. Basically it just
// multiplies the two constants together, inserts the result into the constant
// pool, and returns it. Of course life is not simple, and this is no
// exception. Factors that complicate matters:
// 1. Either argument may be null. If this is the case, the null argument is
// treated as either 0 (if DefOne = false) or 1 (if DefOne = true)
// 2. Types get in the way. We want to do arithmetic operations without
// regard for the underlying types. It is assumed that the constants are
// integral constants.
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
// is false, a null return value indicates a value of 0.
//
inline const ConstPoolInt *Mul(const ConstPoolInt *Arg1,
const ConstPoolInt *Arg2, bool DefOne = false) {
assert(Arg1 && Arg2 && "No null arguments should exist now!");
assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
// Actually perform the computation now!
ConstPoolVal *Result = *Arg1 * *Arg2;
assert(Result && Result->getType() == Arg1->getType() &&
"Couldn't perform mult!");
ConstPoolInt *ResultI = (ConstPoolInt*)Result;
// Check to see if the result is one of the special cases that we want to
// recognize...
if (ResultI->equalsInt(DefOne ? 1 : 0)) {
// Yes it is, simply delete the constant and return null.
delete ResultI;
return 0;
}
return ResultI;
}
inline const ConstPoolInt *operator*(const DefZero &L, const DefZero &R) {
if (L == 0 || R == 0) return 0;
return Mul(L, R, false);
}
inline const ConstPoolInt *operator*(const DefOne &L, const DefZero &R) {
if (R == 0) return getIntegralConstant(0, L.getType());
if (L == 0) return R->equalsInt(1) ? 0 : R.getVal();
return Mul(L, R, false);
}
inline const ConstPoolInt *operator*(const DefZero &L, const DefOne &R) {
return R*L;
}
// ClassifyExpression: Analyze an expression to determine the complexity of the
// expression, and which other values it depends on.
//
// Note that this analysis cannot get into infinite loops because it treats PHI
// nodes as being an unknown linear expression.
//
ExprType analysis::ClassifyExpression(Value *Expr) {
assert(Expr != 0 && "Can't classify a null expression!");
switch (Expr->getValueType()) {
case Value::InstructionVal: break; // Instruction... hmmm... investigate.
case Value::TypeVal: case Value::BasicBlockVal:
case Value::MethodVal: case Value::ModuleVal:
assert(0 && "Unexpected expression type to classify!");
case Value::MethodArgumentVal: // Method arg: nothing known, return var
return Expr;
case Value::ConstantVal: // Constant value, just return constant
ConstPoolVal *CPV = Expr->castConstantAsserting();
if (CPV->getType()->isIntegral()) { // It's an integral constant!
ConstPoolInt *CPI = (ConstPoolInt*)Expr;
return ExprType(CPI->equalsInt(0) ? 0 : (ConstPoolInt*)Expr);
}
return Expr;
}
Instruction *I = Expr->castInstructionAsserting();
const Type *Ty = I->getType();
switch (I->getOpcode()) { // Handle each instruction type seperately
case Instruction::Add: {
ExprType Left (ClassifyExpression(I->getOperand(0)));
ExprType Right(ClassifyExpression(I->getOperand(1)));
if (Left.ExprTy > Right.ExprTy)
swap(Left, Right); // Make left be simpler than right
switch (Left.ExprTy) {
case ExprType::Constant:
return ExprType(Right.Scale, Right.Var,
DefZero(Right.Offset, Ty) + DefZero(Left.Offset, Ty));
case ExprType::Linear: // RHS side must be linear or scaled
case ExprType::ScaledLinear: // RHS must be scaled
if (Left.Var != Right.Var) // Are they the same variables?
return ExprType(I); // if not, we don't know anything!
return ExprType( DefOne(Left.Scale , Ty) + DefOne(Right.Scale , Ty),
Left.Var,
DefZero(Left.Offset, Ty) + DefZero(Right.Offset, Ty));
}
} // end case Instruction::Add
case Instruction::Shl: {
ExprType Right(ClassifyExpression(I->getOperand(1)));
if (Right.ExprTy != ExprType::Constant) break;
ExprType Left(ClassifyExpression(I->getOperand(0)));
if
|