Skip to content

Commit bace7be

Browse files
fhahntstellar
authored andcommitted
Backport 4878aa3 [ValueLattice] Add new state for undef constants.
Summary: NOTE: I mostly put it on Phabricator to make it easy for other people to fetch & check if that fixes a bug. This patch backports 4878aa3 and required earlier patches onto the release/10.x branch. It includes the following patches: aa5ebfd [ValueLattice] Make mark* functions public, return if value changed. c1943b4 [ValueLattice] Update markConstantRange to return false equal ranges. e30c257 [CVP,SCCP] Precommit test for D75055. 4878aa3 [ValueLattice] Add new state for undef constants. All patches except the last one apply cleanly. For the last one, the changes to SCCP.cpp were stripped, because SCCP does not yet use ValueLattice on release/10.x. Otherwise we would have to pull in more additional changes. Subscribers: tstellar, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D76596
1 parent 4a89d0d commit bace7be

File tree

10 files changed

+1018
-68
lines changed

10 files changed

+1018
-68
lines changed

llvm/include/llvm/Analysis/ValueLattice.h

Lines changed: 102 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ValueLatticeElement {
2929
/// producing instruction is dead. Caution: We use this as the starting
3030
/// state in our local meet rules. In this usage, it's taken to mean
3131
/// "nothing known yet".
32-
undefined,
32+
unknown,
3333

3434
/// This Value has a specific constant value. (For constant integers,
3535
/// constantrange is used instead. Integer typed constantexprs can appear
@@ -45,7 +45,12 @@ class ValueLatticeElement {
4545
constantrange,
4646

4747
/// 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
4954
};
5055

5156
ValueLatticeElementTy Tag;
@@ -60,14 +65,15 @@ class ValueLatticeElement {
6065

6166
public:
6267
// Const and Range are initialized on-demand.
63-
ValueLatticeElement() : Tag(undefined) {}
68+
ValueLatticeElement() : Tag(unknown) {}
6469

6570
/// Custom destructor to ensure Range is properly destroyed, when the object
6671
/// is deallocated.
6772
~ValueLatticeElement() {
6873
switch (Tag) {
6974
case overdefined:
70-
case undefined:
75+
case unknown:
76+
case undef:
7177
case constant:
7278
case notconstant:
7379
break;
@@ -79,7 +85,7 @@ class ValueLatticeElement {
7985

8086
/// Custom copy constructor, to ensure Range gets initialized when
8187
/// copying a constant range lattice element.
82-
ValueLatticeElement(const ValueLatticeElement &Other) : Tag(undefined) {
88+
ValueLatticeElement(const ValueLatticeElement &Other) : Tag(unknown) {
8389
*this = Other;
8490
}
8591

@@ -109,7 +115,8 @@ class ValueLatticeElement {
109115
ConstVal = Other.ConstVal;
110116
break;
111117
case overdefined:
112-
case undefined:
118+
case unknown:
119+
case undef:
113120
break;
114121
}
115122
Tag = Other.Tag;
@@ -118,14 +125,16 @@ class ValueLatticeElement {
118125

119126
static ValueLatticeElement get(Constant *C) {
120127
ValueLatticeElement Res;
121-
if (!isa<UndefValue>(C))
128+
if (isa<UndefValue>(C))
129+
Res.markUndef();
130+
else
122131
Res.markConstant(C);
123132
return Res;
124133
}
125134
static ValueLatticeElement getNot(Constant *C) {
126135
ValueLatticeElement Res;
127-
if (!isa<UndefValue>(C))
128-
Res.markNotConstant(C);
136+
assert(!isa<UndefValue>(C) && "!= undef is not supported");
137+
Res.markNotConstant(C);
129138
return Res;
130139
}
131140
static ValueLatticeElement getRange(ConstantRange CR) {
@@ -139,7 +148,10 @@ class ValueLatticeElement {
139148
return Res;
140149
}
141150

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(); }
143155
bool isConstant() const { return Tag == constant; }
144156
bool isNotConstant() const { return Tag == notconstant; }
145157
bool isConstantRange() const { return Tag == constantrange; }
@@ -170,89 +182,123 @@ class ValueLatticeElement {
170182
return None;
171183
}
172184

173-
private:
174-
void markOverdefined() {
185+
bool markOverdefined() {
175186
if (isOverdefined())
176-
return;
187+
return false;
177188
if (isConstant() || isNotConstant())
178189
ConstVal = nullptr;
179190
if (isConstantRange())
180191
Range.~ConstantRange();
181192
Tag = overdefined;
193+
return true;
182194
}
183195

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) {
190206
if (isa<UndefValue>(V))
191-
return;
207+
return markUndef();
192208

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());
196218
Tag = constant;
197219
ConstVal = V;
220+
return true;
198221
}
199222

200-
void markNotConstant(Constant *V) {
223+
bool markNotConstant(Constant *V) {
201224
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+
206229
if (isa<UndefValue>(V))
207-
return;
230+
return false;
208231

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());
214238
Tag = notconstant;
215239
ConstVal = V;
240+
return true;
216241
}
217242

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) {
219248
if (isConstantRange()) {
249+
if (getConstantRange() == NewR)
250+
return false;
251+
220252
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;
226259
}
227260

228-
assert(isUndefined());
261+
assert(isUnknown() || isUndef());
229262
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;
235268
}
236269

237-
public:
238270
/// Updates this object to approximate both this object and RHS. Returns
239271
/// true if this object has been changed.
240272
bool mergeIn(const ValueLatticeElement &RHS, const DataLayout &DL) {
241-
if (RHS.isUndefined() || isOverdefined())
273+
if (RHS.isUnknown() || isOverdefined())
242274
return false;
243275
if (RHS.isOverdefined()) {
244276
markOverdefined();
245277
return true;
246278
}
247279

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");
249293
*this = RHS;
250-
return !RHS.isUndefined();
294+
return true;
251295
}
252296

253297
if (isConstant()) {
254298
if (RHS.isConstant() && getConstant() == RHS.getConstant())
255299
return false;
300+
if (RHS.isUndef())
301+
return false;
256302
markOverdefined();
257303
return true;
258304
}
@@ -265,6 +311,9 @@ class ValueLatticeElement {
265311
}
266312

267313
assert(isConstantRange() && "New ValueLattice type?");
314+
if (RHS.isUndef() && getConstantRange().isSingleElement())
315+
return false;
316+
268317
if (!RHS.isConstantRange()) {
269318
// We can get here if we've encountered a constantexpr of integer type
270319
// and merge it with a constantrange.
@@ -273,26 +322,19 @@ class ValueLatticeElement {
273322
}
274323
ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
275324
if (NewR.isFullSet())
276-
markOverdefined();
325+
return markOverdefined();
277326
else if (NewR == getConstantRange())
278327
return false;
279328
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));
288330
}
289331

290332
/// Compares this symbolic value with Other using Pred and returns either
291333
/// true, false or undef constants, or nullptr if the comparison cannot be
292334
/// evaluated.
293335
Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
294336
const ValueLatticeElement &Other) const {
295-
if (isUndefined() || Other.isUndefined())
337+
if (isUnknownOrUndef() || Other.isUnknownOrUndef())
296338
return UndefValue::get(Ty);
297339

298340
if (isConstant() && Other.isConstant())

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ static ValueLatticeElement intersect(const ValueLatticeElement &A,
9696
const ValueLatticeElement &B) {
9797
// Undefined is the strongest state. It means the value is known to be along
9898
// an unreachable path.
99-
if (A.isUndefined())
99+
if (A.isUnknown())
100100
return A;
101-
if (B.isUndefined())
101+
if (B.isUnknown())
102102
return B;
103103

104104
// If we gave up for one, but got a useable fact from the other, use it.
@@ -1203,7 +1203,7 @@ static ValueLatticeElement getValueFromICmpCondition(Value *Val, ICmpInst *ICI,
12031203
// false SETNE.
12041204
if (isTrueDest == (Predicate == ICmpInst::ICMP_EQ))
12051205
return ValueLatticeElement::get(cast<Constant>(RHS));
1206-
else
1206+
else if (!isa<UndefValue>(RHS))
12071207
return ValueLatticeElement::getNot(cast<Constant>(RHS));
12081208
}
12091209
}
@@ -1722,7 +1722,7 @@ ConstantRange LazyValueInfo::getConstantRange(Value *V, BasicBlock *BB,
17221722
const DataLayout &DL = BB->getModule()->getDataLayout();
17231723
ValueLatticeElement Result =
17241724
getImpl(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
1725-
if (Result.isUndefined())
1725+
if (Result.isUnknown())
17261726
return ConstantRange::getEmpty(Width);
17271727
if (Result.isConstantRange())
17281728
return Result.getConstantRange();
@@ -1761,7 +1761,7 @@ ConstantRange LazyValueInfo::getConstantRangeOnEdge(Value *V,
17611761
ValueLatticeElement Result =
17621762
getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
17631763

1764-
if (Result.isUndefined())
1764+
if (Result.isUnknown())
17651765
return ConstantRange::getEmpty(Width);
17661766
if (Result.isConstantRange())
17671767
return Result.getConstantRange();
@@ -1991,7 +1991,7 @@ void LazyValueInfoAnnotatedWriter::emitBasicBlockStartAnnot(
19911991
for (auto &Arg : F->args()) {
19921992
ValueLatticeElement Result = LVIImpl->getValueInBlock(
19931993
const_cast<Argument *>(&Arg), const_cast<BasicBlock *>(BB));
1994-
if (Result.isUndefined())
1994+
if (Result.isUnknown())
19951995
continue;
19961996
OS << "; LatticeVal for: '" << Arg << "' is: " << Result << "\n";
19971997
}

llvm/lib/Analysis/ValueLattice.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111
namespace llvm {
1212
raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val) {
13-
if (Val.isUndefined())
14-
return OS << "undefined";
13+
if (Val.isUnknown())
14+
return OS << "unknown";
15+
if (Val.isUndef())
16+
return OS << "undef";
1517
if (Val.isOverdefined())
1618
return OS << "overdefined";
1719

0 commit comments

Comments
 (0)