@@ -21,30 +21,33 @@ namespace
21
21
static char ID;
22
22
Hpps () : FunctionPass(ID) {}
23
23
24
- // Run over a single function
24
+ // Run over a single function (main)
25
25
bool runOnFunction (Function &Func) override
26
26
{
27
- // Null Value reference
27
+ // Create a Null Value reference
28
+ // Assigned as placeholder when no variable reference available
28
29
LLVMContext &context = Func.getContext ();
29
30
Value *nullValue = ConstantInt::get (Type::getInt32Ty (context), -1 );
30
31
31
- // Keep reference of value still left to find the ranges
32
- // 'from' is unknown, it depends on 'to', 'toValue', and 'toOps' ('+' or '-')
32
+ // Keep reference of values still left to find the ranges
33
+ // 'from' is unknown, it depends on 'to', 'to2', 'toValue', and 'toOps' ('+' or '-')
34
+ //
33
35
// from = to toOps toValue (a = b + 1)
34
- // from = toValue toOps to (a = 1 + b)
36
+ // from = toValue toOps to2 (a = 1 + b)
35
37
// from = to toOps to2 (a = b + c)
36
38
std::vector<Value *> from;
37
39
std::vector<Value *> to;
38
40
std::vector<Value *> to2;
39
41
std::vector<int > toValue;
40
42
std::vector<unsigned > toOps;
41
43
42
- // Reference of variabiles for which range has been found
43
- std::vector<Value *> ranged; // Reference to the variable
44
+ // Reference of variables for which range has been found
45
+ // Note: Since no branches, minRange = maxRange (constant values)
46
+ std::vector<Value *> ranged; // Reference to the variable (name)
44
47
std::vector<int > minRange; // Min range of variable
45
48
std::vector<int > maxRange; // Max range of variable
46
49
47
- // Keep reference of variables in load instructions
50
+ // Keep reference of variables (alias) from load instructions
48
51
std::vector<Value *> loadRef;
49
52
50
53
// Run over all basic blocks in the function
@@ -56,9 +59,11 @@ namespace
56
59
// Print instruction
57
60
errs () << I << " \n " ;
58
61
59
- // When instruction is load, store reference to its variables
62
+ // When instruction is load, store reference (alias) to its real variables
60
63
if (auto *loadInst = dyn_cast<LoadInst>(&I))
61
64
{
65
+ // Cycle over all the operands and store them for later use in 'loadRef'
66
+ // Used to identify references in binary operations
62
67
for (Use &U : loadInst->operands ())
63
68
{
64
69
Value *v = U.get ();
@@ -71,24 +76,37 @@ namespace
71
76
// Save operand0 (reference/constant) and operand1 (reference/constant)
72
77
if (auto *operInst = dyn_cast<BinaryOperator>(&I))
73
78
{
79
+ // Get operands from binary operation
74
80
Value *oper0 = operInst->getOperand (0 );
75
81
Value *oper1 = operInst->getOperand (1 );
76
82
77
83
// Store reference of variable still to find range
78
84
from.push_back (operInst); // left-hand side of the operation
79
85
toOps.push_back (operInst->getOpcode ()); // '+' ot '-'
80
86
81
- // Store constants/references
82
- errs () << " -Operation: " << operInst->getName () << " \n " ;
87
+ // Print variable assigned and name of operands
88
+ errs () << " -Var: " << operInst->getName () << " \n " ;
89
+ errs () << " -Op0: " << oper0->getName () << " \n " ;
90
+ errs () << " -Op1: " << oper1->getName () << " \n " ;
83
91
84
92
// a = b + 1 (variable + constant)
85
93
// Get reference from previous load instruction
86
94
if (ConstantInt *CI = dyn_cast<ConstantInt>(oper1))
87
95
{
88
96
toValue.push_back (CI->getZExtValue ());
89
- to.push_back (loadRef.at (0 ));
90
97
to2.push_back (nullValue);
91
- loadRef.pop_back ();
98
+
99
+ // If operand0 is reference (and not an alias) store it
100
+ if (oper0->hasName ())
101
+ {
102
+ to.push_back (oper0);
103
+ }
104
+ // Otherwise get value from previous load instruction (alias)
105
+ else
106
+ {
107
+ to.push_back (loadRef.at (0 ));
108
+ loadRef.pop_back ();
109
+ }
92
110
}
93
111
94
112
// a = 1 + b (constant + variable)
@@ -97,30 +115,54 @@ namespace
97
115
{
98
116
toValue.push_back (CI->getZExtValue ());
99
117
to.push_back (nullValue);
100
- to2.push_back (loadRef.at (0 ));
101
- loadRef.pop_back ();
118
+
119
+ // If operand1 is reference (and not an alias) store it
120
+ if (oper1->hasName ())
121
+ {
122
+ to2.push_back (oper1);
123
+ }
124
+ // Otherwise get value from previous load instruction (alias)
125
+ else
126
+ {
127
+ to2.push_back (loadRef.at (0 ));
128
+ loadRef.pop_back ();
129
+ }
102
130
}
103
131
104
132
// a = b + c (variable + variable)
105
133
// Get reference from two previous load instructions
106
134
else
107
135
{
108
- // It may be that there are x2 'to'
109
- toValue.push_back (0 );
110
- to.push_back (loadRef.at (0 ));
111
-
112
- // TODO: When a = a + b + 3, the IR creates two loads for a and b, then
113
- // it does the 'add' = a + b, and then uses 'add1' = 'add' + 3. The problem
114
- // is that 'add' is not in loadRef, so there is an error!
115
- //
116
- // Same with a = a + b + c, 'add' = a + b, then load of c and 'add1' = 'add' + c,
117
- // but since those are both variables, and loadRef contains only c, calling
118
- // loadRef.at(1) gives error!
119
- to2.push_back (loadRef.at (1 ));
120
-
121
- // Remove previous used load instruction value
122
- loadRef.pop_back ();
123
- loadRef.pop_back ();
136
+ toValue.push_back (0 ); // Placeholder
137
+
138
+ // Both operand0 and operand1 as reference
139
+ if (oper0->hasName () && oper1->hasName ())
140
+ {
141
+ to.push_back (oper0);
142
+ to2.push_back (oper1);
143
+ }
144
+ // Operand0 from load and operand1 as reference
145
+ else if (!oper0->hasName () && oper1->hasName ())
146
+ {
147
+ to.push_back (loadRef.at (0 ));
148
+ to2.push_back (oper1);
149
+ loadRef.pop_back ();
150
+ }
151
+ // Operand1 from load and operand0 as reference
152
+ else if (oper0->hasName () && !oper1->hasName ())
153
+ {
154
+ to.push_back (oper0);
155
+ to2.push_back (loadRef.at (0 ));
156
+ loadRef.pop_back ();
157
+ }
158
+ // Both operand0 and operand1 from load (alias)
159
+ else
160
+ {
161
+ to.push_back (loadRef.at (0 ));
162
+ to2.push_back (loadRef.at (1 ));
163
+ loadRef.pop_back ();
164
+ loadRef.pop_back ();
165
+ }
124
166
}
125
167
}
126
168
@@ -146,12 +188,14 @@ namespace
146
188
}
147
189
148
190
// Store constant range value (Value-Range Found!)
149
- // a = 1
191
+ // a = 1 (variable assigned constant value)
150
192
else
151
193
{
152
194
if (ConstantInt *CI = dyn_cast<ConstantInt>(oper0))
153
195
{
154
196
errs () << " -Range found: " << CI->getZExtValue () << " \n " ;
197
+
198
+ // Store found value-range
155
199
ranged.push_back (oper1);
156
200
minRange.push_back (CI->getZExtValue ());
157
201
maxRange.push_back (CI->getZExtValue ());
@@ -163,7 +207,7 @@ namespace
163
207
}
164
208
}
165
209
166
- // Resolve references
210
+ // Resolve references/dependencies
167
211
errs () << " \n --- REFERENCES ---\n " ;
168
212
for (unsigned i = 0 ; i < from.size (); ++i)
169
213
{
@@ -190,16 +234,16 @@ namespace
190
234
int refValue1 = -1 ;
191
235
int refValue2 = -1 ;
192
236
237
+ // If 'to' is placeholder, then value is constant number
193
238
if (to.at (i) == nullValue)
194
239
{
195
240
refValue1 = toValue.at (i);
196
- // errs() << "- F(const):" << refValue1 << "\n";
197
241
}
198
242
243
+ // If 'to2' is placeholder, then value is constant number
199
244
if (to2.at (i) == nullValue)
200
245
{
201
246
refValue2 = toValue.at (i);
202
- // errs() << "- F(const):" << refValue2 << "\n";
203
247
}
204
248
205
249
// Search variable reference inside already found ranges
@@ -210,18 +254,17 @@ namespace
210
254
{
211
255
// When range found, add a new found range
212
256
refValue1 = minRange.at (v);
213
- // errs() << "- F(to):" << ranged.at(v)->getName() << " (" << refValue1 << "\n\n";
214
257
}
215
258
216
259
// When found value of 'to2' in 'ranged'
217
260
if (to2.at (i) == ranged.at (v))
218
261
{
219
262
// When range found, add a new found range
220
263
refValue2 = minRange.at (v);
221
- // errs() << "- F(to2):" << ranged.at(v)->getName() << " (" << refValue2 << "\n\n";
222
264
}
223
265
}
224
266
267
+ // Compute found value-range from resolved dependencies
225
268
if (toOps.at (i) == Instruction::Add)
226
269
{
227
270
minRange.push_back (refValue1 + refValue2);
@@ -251,7 +294,7 @@ namespace
251
294
} // end of anonymous namespace
252
295
253
296
char Hpps::ID = 0 ;
254
- static RegisterPass<Hpps> X (" hpps " , " Hpps World Pass" ,
297
+ static RegisterPass<Hpps> X (" const-range " , " Constant Range Pass" ,
255
298
false /* Only looks at CFG */ ,
256
299
false /* Analysis Pass */ );
257
300
0 commit comments