@@ -29,7 +29,7 @@ class ValueLatticeElement {
29
29
// / producing instruction is dead. Caution: We use this as the starting
30
30
// / state in our local meet rules. In this usage, it's taken to mean
31
31
// / "nothing known yet".
32
- undefined ,
32
+ unknown ,
33
33
34
34
// / This Value has a specific constant value. (For constant integers,
35
35
// / constantrange is used instead. Integer typed constantexprs can appear
@@ -45,7 +45,12 @@ class ValueLatticeElement {
45
45
constantrange,
46
46
47
47
// / We can not precisely model the dynamic values this value might take.
48
- overdefined
48
+ overdefined,
49
+
50
+ // / This Value is an UndefValue constant or produces undef. Undefined values
51
+ // / can be merged with constants (or single element constant ranges),
52
+ // / assuming all uses of the result will be replaced.
53
+ undef
49
54
};
50
55
51
56
ValueLatticeElementTy Tag;
@@ -60,14 +65,15 @@ class ValueLatticeElement {
60
65
61
66
public:
62
67
// Const and Range are initialized on-demand.
63
- ValueLatticeElement () : Tag(undefined ) {}
68
+ ValueLatticeElement () : Tag(unknown ) {}
64
69
65
70
// / Custom destructor to ensure Range is properly destroyed, when the object
66
71
// / is deallocated.
67
72
~ValueLatticeElement () {
68
73
switch (Tag) {
69
74
case overdefined:
70
- case undefined:
75
+ case unknown:
76
+ case undef:
71
77
case constant:
72
78
case notconstant:
73
79
break ;
@@ -79,7 +85,7 @@ class ValueLatticeElement {
79
85
80
86
// / Custom copy constructor, to ensure Range gets initialized when
81
87
// / copying a constant range lattice element.
82
- ValueLatticeElement (const ValueLatticeElement &Other) : Tag(undefined ) {
88
+ ValueLatticeElement (const ValueLatticeElement &Other) : Tag(unknown ) {
83
89
*this = Other;
84
90
}
85
91
@@ -109,7 +115,8 @@ class ValueLatticeElement {
109
115
ConstVal = Other.ConstVal ;
110
116
break ;
111
117
case overdefined:
112
- case undefined:
118
+ case unknown:
119
+ case undef:
113
120
break ;
114
121
}
115
122
Tag = Other.Tag ;
@@ -118,14 +125,16 @@ class ValueLatticeElement {
118
125
119
126
static ValueLatticeElement get (Constant *C) {
120
127
ValueLatticeElement Res;
121
- if (!isa<UndefValue>(C))
128
+ if (isa<UndefValue>(C))
129
+ Res.markUndef ();
130
+ else
122
131
Res.markConstant (C);
123
132
return Res;
124
133
}
125
134
static ValueLatticeElement getNot (Constant *C) {
126
135
ValueLatticeElement Res;
127
- if (!isa<UndefValue>(C))
128
- Res.markNotConstant (C);
136
+ assert (!isa<UndefValue>(C) && " != undef is not supported " );
137
+ Res.markNotConstant (C);
129
138
return Res;
130
139
}
131
140
static ValueLatticeElement getRange (ConstantRange CR) {
@@ -139,7 +148,10 @@ class ValueLatticeElement {
139
148
return Res;
140
149
}
141
150
142
- bool isUndefined () const { return Tag == undefined; }
151
+ bool isUndef () const { return Tag == undef; }
152
+ bool isUnknown () const { return Tag == unknown; }
153
+ bool isUnknownOrUndef () const { return Tag == unknown || Tag == undef; }
154
+ bool isUndefined () const { return isUnknownOrUndef (); }
143
155
bool isConstant () const { return Tag == constant; }
144
156
bool isNotConstant () const { return Tag == notconstant; }
145
157
bool isConstantRange () const { return Tag == constantrange; }
@@ -170,89 +182,123 @@ class ValueLatticeElement {
170
182
return None;
171
183
}
172
184
173
- private:
174
- void markOverdefined () {
185
+ bool markOverdefined () {
175
186
if (isOverdefined ())
176
- return ;
187
+ return false ;
177
188
if (isConstant () || isNotConstant ())
178
189
ConstVal = nullptr ;
179
190
if (isConstantRange ())
180
191
Range.~ConstantRange ();
181
192
Tag = overdefined;
193
+ return true ;
182
194
}
183
195
184
- void markConstant (Constant *V) {
185
- assert (V && " Marking constant with NULL" );
186
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
187
- markConstantRange (ConstantRange (CI->getValue ()));
188
- return ;
189
- }
196
+ bool markUndef () {
197
+ if (isUndef ())
198
+ return false ;
199
+
200
+ assert (isUnknown ());
201
+ Tag = undef;
202
+ return true ;
203
+ }
204
+
205
+ bool markConstant (Constant *V) {
190
206
if (isa<UndefValue>(V))
191
- return ;
207
+ return markUndef () ;
192
208
193
- assert ((!isConstant () || getConstant () == V) &&
194
- " Marking constant with different value" );
195
- assert (isUndefined ());
209
+ if (isConstant ()) {
210
+ assert (getConstant () == V && " Marking constant with different value" );
211
+ return false ;
212
+ }
213
+
214
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
215
+ return markConstantRange (ConstantRange (CI->getValue ()));
216
+
217
+ assert (isUnknown () || isUndef ());
196
218
Tag = constant;
197
219
ConstVal = V;
220
+ return true ;
198
221
}
199
222
200
- void markNotConstant (Constant *V) {
223
+ bool markNotConstant (Constant *V) {
201
224
assert (V && " Marking constant with NULL" );
202
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
203
- markConstantRange (ConstantRange (CI-> getValue () + 1 , CI-> getValue ()));
204
- return ;
205
- }
225
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
226
+ return markConstantRange (
227
+ ConstantRange (CI-> getValue () + 1 , CI-> getValue ())) ;
228
+
206
229
if (isa<UndefValue>(V))
207
- return ;
230
+ return false ;
208
231
209
- assert ((!isConstant () || getConstant () != V) &&
210
- " Marking constant !constant with same value" );
211
- assert ((!isNotConstant () || getNotConstant () == V) &&
212
- " Marking !constant with different value" );
213
- assert (isUndefined () || isConstant ());
232
+ if (isNotConstant ()) {
233
+ assert (getNotConstant () == V && " Marking !constant with different value" );
234
+ return false ;
235
+ }
236
+
237
+ assert (isUnknown ());
214
238
Tag = notconstant;
215
239
ConstVal = V;
240
+ return true ;
216
241
}
217
242
218
- void markConstantRange (ConstantRange NewR) {
243
+ // / Mark the object as constant range with \p NewR. If the object is already a
244
+ // / constant range, nothing changes if the existing range is equal to \p
245
+ // / NewR. Otherwise \p NewR must be a superset of the existing range or the
246
+ // / object must be undef.
247
+ bool markConstantRange (ConstantRange NewR) {
219
248
if (isConstantRange ()) {
249
+ if (getConstantRange () == NewR)
250
+ return false ;
251
+
220
252
if (NewR.isEmptySet ())
221
- markOverdefined ();
222
- else {
223
- Range = std::move (NewR);
224
- }
225
- return ;
253
+ return markOverdefined ();
254
+
255
+ assert (NewR.contains (getConstantRange ()) &&
256
+ " Existing range must be a subset of NewR" );
257
+ Range = std::move (NewR);
258
+ return true ;
226
259
}
227
260
228
- assert (isUndefined ());
261
+ assert (isUnknown () || isUndef ());
229
262
if (NewR.isEmptySet ())
230
- markOverdefined ();
231
- else {
232
- Tag = constantrange;
233
- new (&Range) ConstantRange (std::move (NewR));
234
- }
263
+ return markOverdefined ();
264
+
265
+ Tag = constantrange;
266
+ new (&Range) ConstantRange (std::move (NewR));
267
+ return true ;
235
268
}
236
269
237
- public:
238
270
// / Updates this object to approximate both this object and RHS. Returns
239
271
// / true if this object has been changed.
240
272
bool mergeIn (const ValueLatticeElement &RHS, const DataLayout &DL) {
241
- if (RHS.isUndefined () || isOverdefined ())
273
+ if (RHS.isUnknown () || isOverdefined ())
242
274
return false ;
243
275
if (RHS.isOverdefined ()) {
244
276
markOverdefined ();
245
277
return true ;
246
278
}
247
279
248
- if (isUndefined ()) {
280
+ if (isUndef ()) {
281
+ assert (!RHS.isUnknown ());
282
+ if (RHS.isUndef ())
283
+ return false ;
284
+ if (RHS.isConstant ())
285
+ return markConstant (RHS.getConstant ());
286
+ if (RHS.isConstantRange () && RHS.getConstantRange ().isSingleElement ())
287
+ return markConstantRange (RHS.getConstantRange ());
288
+ return markOverdefined ();
289
+ }
290
+
291
+ if (isUnknown ()) {
292
+ assert (!RHS.isUnknown () && " Unknow RHS should be handled earlier" );
249
293
*this = RHS;
250
- return !RHS. isUndefined () ;
294
+ return true ;
251
295
}
252
296
253
297
if (isConstant ()) {
254
298
if (RHS.isConstant () && getConstant () == RHS.getConstant ())
255
299
return false ;
300
+ if (RHS.isUndef ())
301
+ return false ;
256
302
markOverdefined ();
257
303
return true ;
258
304
}
@@ -265,6 +311,9 @@ class ValueLatticeElement {
265
311
}
266
312
267
313
assert (isConstantRange () && " New ValueLattice type?" );
314
+ if (RHS.isUndef () && getConstantRange ().isSingleElement ())
315
+ return false ;
316
+
268
317
if (!RHS.isConstantRange ()) {
269
318
// We can get here if we've encountered a constantexpr of integer type
270
319
// and merge it with a constantrange.
@@ -273,26 +322,19 @@ class ValueLatticeElement {
273
322
}
274
323
ConstantRange NewR = getConstantRange ().unionWith (RHS.getConstantRange ());
275
324
if (NewR.isFullSet ())
276
- markOverdefined ();
325
+ return markOverdefined ();
277
326
else if (NewR == getConstantRange ())
278
327
return false ;
279
328
else
280
- markConstantRange (std::move (NewR));
281
- return true ;
282
- }
283
-
284
- ConstantInt *getConstantInt () const {
285
- assert (isConstant () && isa<ConstantInt>(getConstant ()) &&
286
- " No integer constant" );
287
- return cast<ConstantInt>(getConstant ());
329
+ return markConstantRange (std::move (NewR));
288
330
}
289
331
290
332
// / Compares this symbolic value with Other using Pred and returns either
291
333
// / true, false or undef constants, or nullptr if the comparison cannot be
292
334
// / evaluated.
293
335
Constant *getCompare (CmpInst::Predicate Pred, Type *Ty,
294
336
const ValueLatticeElement &Other) const {
295
- if (isUndefined () || Other.isUndefined ())
337
+ if (isUnknownOrUndef () || Other.isUnknownOrUndef ())
296
338
return UndefValue::get (Ty);
297
339
298
340
if (isConstant () && Other.isConstant ())
0 commit comments