1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[ValueLattice] Add singlecrfromundef lattice value.

This patch adds a new singlecrfromundef lattice value, indicating a
single element constant range which was merge with undef at some point.
Merging it with another constant range results in overdefined, as we
won't be able to replace all users with a single value.

This patch uses a ConstantRange instead of a Constant*, because regular
integer constants are represented as single element constant ranges as
well and this allows the existing code working without additional
changes.

Reviewers: efriedma, nikic, reames, davide

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D75845
This commit is contained in:
Florian Hahn 2020-03-15 10:35:39 +00:00
parent 65f493cc03
commit 51df7978a6
3 changed files with 53 additions and 8 deletions

View File

@ -29,27 +29,48 @@ class ValueLatticeElement {
/// producing instruction is dead. Caution: We use this as the starting
/// state in our local meet rules. In this usage, it's taken to mean
/// "nothing known yet".
/// Transition to any other state allowed.
unknown,
/// This Value is an UndefValue constant or produces undef. Undefined values
/// can be merged with constants (or single element constant ranges),
/// assuming all uses of the result will be replaced.
/// Transition allowed to the following states:
/// constant
/// singlecrfromundef
/// overdefined
undef,
/// This Value has a specific constant value. (For constant integers,
/// constantrange is used instead. Integer typed constantexprs can appear
/// as constant.)
/// This Value has a specific constant value. The constant cannot be undef.
/// (For constant integers, constantrange is used instead. Integer typed
/// constantexprs can appear as constant.)
/// Transition allowed to the following states:
/// overdefined
constant,
/// This Value is known to not have the specified value. (For constant
/// This Value is known to not have the specified value. (For constant
/// integers, constantrange is used instead. As above, integer typed
/// constantexprs can appear here.)
/// Transition allowed to the following states:
/// overdefined
notconstant,
/// The Value falls within this range. (Used only for integer typed values.)
/// Transition allowed to the following states:
/// constantrange (new range must be a superset of the existing range)
/// singlecrfromundef (range must stay a single element range)
/// overdefined
constantrange,
/// This Value contains a single element constant range that was merged with
/// an Undef value. Merging it with other constant ranges results in
/// overdefined, unless they match the single element constant range.
/// Transition allowed to the following states:
/// overdefined
singlecrfromundef,
/// We can not precisely model the dynamic values this value might take.
/// No transitions are allowed after reaching overdefined.
overdefined
};
@ -75,6 +96,7 @@ public:
case unknown:
case undef:
case constant:
case singlecrfromundef:
case notconstant:
break;
case constantrange:
@ -105,6 +127,7 @@ public:
switch (Other.Tag) {
case constantrange:
case singlecrfromundef:
if (!isConstantRange())
new (&Range) ConstantRange(Other.Range);
else
@ -155,8 +178,11 @@ public:
bool isUnknown() const { return Tag == unknown; }
bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
bool isConstant() const { return Tag == constant; }
bool isSingleCRFromUndef() const { return Tag == singlecrfromundef; }
bool isNotConstant() const { return Tag == notconstant; }
bool isConstantRange() const { return Tag == constantrange; }
bool isConstantRange() const {
return Tag == constantrange || Tag == singlecrfromundef;
}
bool isOverdefined() const { return Tag == overdefined; }
Constant *getConstant() const {
@ -251,6 +277,8 @@ public:
if (getConstantRange() == NewR)
return false;
assert(!isSingleCRFromUndef());
if (NewR.isEmptySet())
return markOverdefined();
@ -260,11 +288,11 @@ public:
return true;
}
assert(isUnknown() || isUndef());
assert(isUnknown() || (isUndef() && NewR.isSingleElement()));
if (NewR.isEmptySet())
return markOverdefined();
Tag = constantrange;
Tag = isUnknown() ? constantrange : singlecrfromundef;
new (&Range) ConstantRange(std::move(NewR));
return true;
}
@ -322,7 +350,17 @@ public:
markOverdefined();
return true;
}
ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
if (isSingleCRFromUndef() || RHS.isSingleCRFromUndef()) {
if (NewR.isSingleElement()) {
assert(getConstantRange() == NewR);
return false;
}
markOverdefined();
return true;
}
if (NewR.isFullSet())
return markOverdefined();
else if (NewR == getConstantRange())

View File

@ -19,6 +19,12 @@ raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val) {
if (Val.isNotConstant())
return OS << "notconstant<" << *Val.getNotConstant() << ">";
if (Val.isSingleCRFromUndef())
return OS << "constantrange (from undef)<"
<< Val.getConstantRange().getLower() << ", "
<< Val.getConstantRange().getUpper() << ">";
if (Val.isConstantRange())
return OS << "constantrange<" << Val.getConstantRange().getLower() << ", "
<< Val.getConstantRange().getUpper() << ">";

View File

@ -199,7 +199,8 @@ define i64 @constant_range_and_undef_3_incoming_v2(i1 %c1, i1 %c2, i64 %a) {
; CHECK-NEXT: br label [[BB4]]
; CHECK: bb4:
; CHECK-NEXT: [[P:%.*]] = phi i64 [ undef, [[BB1]] ], [ 10, [[BB2]] ], [ [[R]], [[BB3]] ]
; CHECK-NEXT: ret i64 [[P]]
; CHECK-NEXT: [[RES:%.*]] = and i64 [[P]], 255
; CHECK-NEXT: ret i64 [[RES]]
;
entry:
br i1 %c1, label %bb1, label %bb2