1 //===- ValueLattice.cpp - Value constraint analysis -------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/ValueLattice.h"
10 #include "llvm/Analysis/ConstantFolding.h"
11 #include "llvm/IR/Instructions.h"
15 ValueLatticeElement::getCompare(CmpInst::Predicate Pred
, Type
*Ty
,
16 const ValueLatticeElement
&Other
,
17 const DataLayout
&DL
) const {
19 if (isUnknown() || Other
.isUnknown())
22 // TODO: Can be made more precise, but always returning undef would be
24 if (isUndef() || Other
.isUndef())
27 if (isConstant() && Other
.isConstant())
28 return ConstantFoldCompareInstOperands(Pred
, getConstant(),
29 Other
.getConstant(), DL
);
31 if (ICmpInst::isEquality(Pred
)) {
32 // not(C) != C => true, not(C) == C => false.
33 if ((isNotConstant() && Other
.isConstant() &&
34 getNotConstant() == Other
.getConstant()) ||
35 (isConstant() && Other
.isNotConstant() &&
36 getConstant() == Other
.getNotConstant()))
37 return Pred
== ICmpInst::ICMP_NE
? ConstantInt::getTrue(Ty
)
38 : ConstantInt::getFalse(Ty
);
41 // Integer constants are represented as ConstantRanges with single
43 if (!isConstantRange() || !Other
.isConstantRange())
46 const auto &CR
= getConstantRange();
47 const auto &OtherCR
= Other
.getConstantRange();
48 if (CR
.icmp(Pred
, OtherCR
))
49 return ConstantInt::getTrue(Ty
);
50 if (CR
.icmp(CmpInst::getInversePredicate(Pred
), OtherCR
))
51 return ConstantInt::getFalse(Ty
);
56 static bool hasSingleValue(const ValueLatticeElement
&Val
) {
57 if (Val
.isConstantRange() && Val
.getConstantRange().isSingleElement())
58 // Integer constants are single element ranges
60 return Val
.isConstant();
63 /// Combine two sets of facts about the same value into a single set of
64 /// facts. Note that this method is not suitable for merging facts along
65 /// different paths in a CFG; that's what the mergeIn function is for. This
66 /// is for merging facts gathered about the same value at the same location
67 /// through two independent means.
69 /// * This method does not promise to return the most precise possible lattice
70 /// value implied by A and B. It is allowed to return any lattice element
71 /// which is at least as strong as *either* A or B (unless our facts
72 /// conflict, see below).
73 /// * Due to unreachable code, the intersection of two lattice values could be
74 /// contradictory. If this happens, we return some valid lattice value so as
75 /// not confuse the rest of LVI. Ideally, we'd always return Undefined, but
76 /// we do not make this guarantee. TODO: This would be a useful enhancement.
78 ValueLatticeElement::intersect(const ValueLatticeElement
&Other
) const {
81 if (Other
.isUnknown())
84 // If we gave up for one, but got a useable fact from the other, use it.
87 if (Other
.isOverdefined())
90 // Can't get any more precise than constants.
91 if (hasSingleValue(*this))
93 if (hasSingleValue(Other
))
96 // Could be either constant range or not constant here.
97 if (!isConstantRange() || !Other
.isConstantRange()) {
98 // TODO: Arbitrary choice, could be improved
102 // Intersect two constant ranges
103 ConstantRange Range
=
104 getConstantRange().intersectWith(Other
.getConstantRange());
105 // Note: An empty range is implicitly converted to unknown or undef depending
106 // on MayIncludeUndef internally.
107 return ValueLatticeElement::getRange(
108 std::move(Range
), /*MayIncludeUndef=*/isConstantRangeIncludingUndef() ||
109 Other
.isConstantRangeIncludingUndef());
112 raw_ostream
&operator<<(raw_ostream
&OS
, const ValueLatticeElement
&Val
) {
114 return OS
<< "unknown";
116 return OS
<< "undef";
117 if (Val
.isOverdefined())
118 return OS
<< "overdefined";
120 if (Val
.isNotConstant())
121 return OS
<< "notconstant<" << *Val
.getNotConstant() << ">";
123 if (Val
.isConstantRangeIncludingUndef())
124 return OS
<< "constantrange incl. undef <"
125 << Val
.getConstantRange(true).getLower() << ", "
126 << Val
.getConstantRange(true).getUpper() << ">";
128 if (Val
.isConstantRange())
129 return OS
<< "constantrange<" << Val
.getConstantRange().getLower() << ", "
130 << Val
.getConstantRange().getUpper() << ">";
131 return OS
<< "constant<" << *Val
.getConstant() << ">";
133 } // end namespace llvm