Skip to content

Commit 4878aa3

Browse files
committed
[ValueLattice] Add new state for undef constants.
This patch adds a new undef lattice state, which is used to represent UndefValue constants or instructions producing undef. The main difference to the unknown state is that merging undef values with constants (or single element constant ranges) produces the constant/constant range, assuming all uses of the merge result will be replaced by the found constant. Contrary, merging non-single element ranges with undef needs to go to overdefined. Using unknown for UndefValues currently causes mis-compiles in CVP/LVI (PR44949) and will become problematic once we use ValueLatticeElement for SCCP. Reviewers: efriedma, reames, davide, nikic Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D75120
1 parent b236b4c commit 4878aa3

File tree

8 files changed

+246
-58
lines changed

8 files changed

+246
-58
lines changed

llvm/include/llvm/Analysis/ValueLattice.h

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ 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,
33+
34+
/// This Value is an UndefValue constant or produces undef. Undefined values
35+
/// can be merged with constants (or single element constant ranges),
36+
/// assuming all uses of the result will be replaced.
37+
undef,
3338

3439
/// This Value has a specific constant value. (For constant integers,
3540
/// constantrange is used instead. Integer typed constantexprs can appear
@@ -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,8 +148,9 @@ class ValueLatticeElement {
139148
return Res;
140149
}
141150

142-
bool isUndefined() const { return Tag == undefined; }
143-
bool isUnknown() 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; }
144154
bool isConstant() const { return Tag == constant; }
145155
bool isNotConstant() const { return Tag == notconstant; }
146156
bool isConstantRange() const { return Tag == constantrange; }
@@ -182,9 +192,18 @@ class ValueLatticeElement {
182192
return true;
183193
}
184194

195+
bool markUndef() {
196+
if (isUndef())
197+
return false;
198+
199+
assert(isUnknown());
200+
Tag = undef;
201+
return true;
202+
}
203+
185204
bool markConstant(Constant *V) {
186205
if (isa<UndefValue>(V))
187-
return false;
206+
return markUndef();
188207

189208
if (isConstant()) {
190209
assert(getConstant() == V && "Marking constant with different value");
@@ -194,7 +213,7 @@ class ValueLatticeElement {
194213
if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
195214
return markConstantRange(ConstantRange(CI->getValue()));
196215

197-
assert(isUndefined());
216+
assert(isUnknown() || isUndef());
198217
Tag = constant;
199218
ConstVal = V;
200219
return true;
@@ -214,7 +233,7 @@ class ValueLatticeElement {
214233
return false;
215234
}
216235

217-
assert(isUndefined());
236+
assert(isUnknown());
218237
Tag = notconstant;
219238
ConstVal = V;
220239
return true;
@@ -223,7 +242,7 @@ class ValueLatticeElement {
223242
/// Mark the object as constant range with \p NewR. If the object is already a
224243
/// constant range, nothing changes if the existing range is equal to \p
225244
/// NewR. Otherwise \p NewR must be a superset of the existing range or the
226-
/// object must be undefined.
245+
/// object must be undef.
227246
bool markConstantRange(ConstantRange NewR) {
228247
if (isConstantRange()) {
229248
if (getConstantRange() == NewR)
@@ -238,7 +257,7 @@ class ValueLatticeElement {
238257
return true;
239258
}
240259

241-
assert(isUndefined());
260+
assert(isUnknown() || isUndef());
242261
if (NewR.isEmptySet())
243262
return markOverdefined();
244263

@@ -250,21 +269,35 @@ class ValueLatticeElement {
250269
/// Updates this object to approximate both this object and RHS. Returns
251270
/// true if this object has been changed.
252271
bool mergeIn(const ValueLatticeElement &RHS, const DataLayout &DL) {
253-
if (RHS.isUndefined() || isOverdefined())
272+
if (RHS.isUnknown() || isOverdefined())
254273
return false;
255274
if (RHS.isOverdefined()) {
256275
markOverdefined();
257276
return true;
258277
}
259278

260-
if (isUndefined()) {
279+
if (isUndef()) {
280+
assert(!RHS.isUnknown());
281+
if (RHS.isUndef())
282+
return false;
283+
if (RHS.isConstant())
284+
return markConstant(RHS.getConstant());
285+
if (RHS.isConstantRange() && RHS.getConstantRange().isSingleElement())
286+
return markConstantRange(RHS.getConstantRange());
287+
return markOverdefined();
288+
}
289+
290+
if (isUnknown()) {
291+
assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
261292
*this = RHS;
262-
return !RHS.isUndefined();
293+
return true;
263294
}
264295

265296
if (isConstant()) {
266297
if (RHS.isConstant() && getConstant() == RHS.getConstant())
267298
return false;
299+
if (RHS.isUndef())
300+
return false;
268301
markOverdefined();
269302
return true;
270303
}
@@ -277,6 +310,9 @@ class ValueLatticeElement {
277310
}
278311

279312
assert(isConstantRange() && "New ValueLattice type?");
313+
if (RHS.isUndef() && getConstantRange().isSingleElement())
314+
return false;
315+
280316
if (!RHS.isConstantRange()) {
281317
// We can get here if we've encountered a constantexpr of integer type
282318
// and merge it with a constantrange.
@@ -292,12 +328,12 @@ class ValueLatticeElement {
292328
return markConstantRange(std::move(NewR));
293329
}
294330

295-
/// Compares this symbolic value with Other using Pred and returns either
331+
// Compares this symbolic value with Other using Pred and returns either
296332
/// true, false or undef constants, or nullptr if the comparison cannot be
297333
/// evaluated.
298334
Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
299335
const ValueLatticeElement &Other) const {
300-
if (isUndefined() || Other.isUndefined())
336+
if (isUnknownOrUndef() || Other.isUnknownOrUndef())
301337
return UndefValue::get(Ty);
302338

303339
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)