Skip to content

Commit a5b6068

Browse files
committed
[ValueLattice] Move intersect from LVI into ValueLattice API (NFC)
So we can reuse the logic inside IPSCCP.
1 parent ec9f36a commit a5b6068

File tree

3 files changed

+91
-69
lines changed

3 files changed

+91
-69
lines changed

llvm/include/llvm/Analysis/ValueLattice.h

+17
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,23 @@ class ValueLatticeElement {
471471
const ValueLatticeElement &Other,
472472
const DataLayout &DL) const;
473473

474+
/// Combine two sets of facts about the same value into a single set of
475+
/// facts. Note that this method is not suitable for merging facts along
476+
/// different paths in a CFG; that's what the mergeIn function is for. This
477+
/// is for merging facts gathered about the same value at the same location
478+
/// through two independent means.
479+
/// Notes:
480+
/// * This method does not promise to return the most precise possible lattice
481+
/// value implied by A and B. It is allowed to return any lattice element
482+
/// which is at least as strong as *either* A or B (unless our facts
483+
/// conflict, see below).
484+
/// * Due to unreachable code, the intersection of two lattice values could be
485+
/// contradictory. If this happens, we return some valid lattice value so
486+
/// as not confuse the rest of LVI. Ideally, we'd always return Undefined,
487+
/// but we do not make this guarantee. TODO: This would be a useful
488+
/// enhancement.
489+
ValueLatticeElement intersect(const ValueLatticeElement &Other) const;
490+
474491
unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
475492
void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
476493
};

llvm/lib/Analysis/LazyValueInfo.cpp

+18-69
Original file line numberDiff line numberDiff line change
@@ -83,57 +83,6 @@ static bool hasSingleValue(const ValueLatticeElement &Val) {
8383
return false;
8484
}
8585

86-
/// Combine two sets of facts about the same value into a single set of
87-
/// facts. Note that this method is not suitable for merging facts along
88-
/// different paths in a CFG; that's what the mergeIn function is for. This
89-
/// is for merging facts gathered about the same value at the same location
90-
/// through two independent means.
91-
/// Notes:
92-
/// * This method does not promise to return the most precise possible lattice
93-
/// value implied by A and B. It is allowed to return any lattice element
94-
/// which is at least as strong as *either* A or B (unless our facts
95-
/// conflict, see below).
96-
/// * Due to unreachable code, the intersection of two lattice values could be
97-
/// contradictory. If this happens, we return some valid lattice value so as
98-
/// not confuse the rest of LVI. Ideally, we'd always return Undefined, but
99-
/// we do not make this guarantee. TODO: This would be a useful enhancement.
100-
static ValueLatticeElement intersect(const ValueLatticeElement &A,
101-
const ValueLatticeElement &B) {
102-
// Undefined is the strongest state. It means the value is known to be along
103-
// an unreachable path.
104-
if (A.isUnknown())
105-
return A;
106-
if (B.isUnknown())
107-
return B;
108-
109-
// If we gave up for one, but got a useable fact from the other, use it.
110-
if (A.isOverdefined())
111-
return B;
112-
if (B.isOverdefined())
113-
return A;
114-
115-
// Can't get any more precise than constants.
116-
if (hasSingleValue(A))
117-
return A;
118-
if (hasSingleValue(B))
119-
return B;
120-
121-
// Could be either constant range or not constant here.
122-
if (!A.isConstantRange() || !B.isConstantRange()) {
123-
// TODO: Arbitrary choice, could be improved
124-
return A;
125-
}
126-
127-
// Intersect two constant ranges
128-
ConstantRange Range =
129-
A.getConstantRange().intersectWith(B.getConstantRange());
130-
// Note: An empty range is implicitly converted to unknown or undef depending
131-
// on MayIncludeUndef internally.
132-
return ValueLatticeElement::getRange(
133-
std::move(Range), /*MayIncludeUndef=*/A.isConstantRangeIncludingUndef() ||
134-
B.isConstantRangeIncludingUndef());
135-
}
136-
13786
//===----------------------------------------------------------------------===//
13887
// LazyValueInfoCache Decl
13988
//===----------------------------------------------------------------------===//
@@ -812,9 +761,9 @@ void LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange(
812761
if (I->getParent() != BB || !isValidAssumeForContext(I, BBI))
813762
continue;
814763

815-
BBLV = intersect(BBLV, *getValueFromCondition(Val, I->getArgOperand(0),
816-
/*IsTrueDest*/ true,
817-
/*UseBlockValue*/ false));
764+
BBLV = BBLV.intersect(*getValueFromCondition(Val, I->getArgOperand(0),
765+
/*IsTrueDest*/ true,
766+
/*UseBlockValue*/ false));
818767
}
819768

820769
// If guards are not used in the module, don't spend time looking for them
@@ -824,9 +773,9 @@ void LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange(
824773
make_range(std::next(BBI->getIterator().getReverse()), BB->rend())) {
825774
Value *Cond = nullptr;
826775
if (match(&I, m_Intrinsic<Intrinsic::experimental_guard>(m_Value(Cond))))
827-
BBLV = intersect(BBLV,
828-
*getValueFromCondition(Val, Cond, /*IsTrueDest*/ true,
829-
/*UseBlockValue*/ false));
776+
BBLV = BBLV.intersect(*getValueFromCondition(Val, Cond,
777+
/*IsTrueDest*/ true,
778+
/*UseBlockValue*/ false));
830779
}
831780
}
832781

@@ -913,13 +862,13 @@ LazyValueInfoImpl::solveBlockValueSelect(SelectInst *SI, BasicBlock *BB) {
913862
// the select condition.
914863
if (isGuaranteedNotToBeUndef(Cond, AC)) {
915864
TrueVal =
916-
intersect(TrueVal, *getValueFromCondition(SI->getTrueValue(), Cond,
917-
/*IsTrueDest*/ true,
918-
/*UseBlockValue*/ false));
865+
TrueVal.intersect(*getValueFromCondition(SI->getTrueValue(), Cond,
866+
/*IsTrueDest*/ true,
867+
/*UseBlockValue*/ false));
919868
FalseVal =
920-
intersect(FalseVal, *getValueFromCondition(SI->getFalseValue(), Cond,
921-
/*IsTrueDest*/ false,
922-
/*UseBlockValue*/ false));
869+
FalseVal.intersect(*getValueFromCondition(SI->getFalseValue(), Cond,
870+
/*IsTrueDest*/ false,
871+
/*UseBlockValue*/ false));
923872
}
924873

925874
ValueLatticeElement Result = TrueVal;
@@ -1037,9 +986,9 @@ LazyValueInfoImpl::solveBlockValueIntrinsic(IntrinsicInst *II, BasicBlock *BB) {
1037986
OpRanges.push_back(*Range);
1038987
}
1039988

1040-
return intersect(ValueLatticeElement::getRange(ConstantRange::intrinsic(
1041-
II->getIntrinsicID(), OpRanges)),
1042-
MetadataVal);
989+
return ValueLatticeElement::getRange(
990+
ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges))
991+
.intersect(MetadataVal);
1043992
}
1044993

1045994
std::optional<ValueLatticeElement>
@@ -1310,7 +1259,7 @@ LazyValueInfoImpl::getValueFromCondition(Value *Val, Value *Cond,
13101259
return *LV;
13111260
}
13121261

1313-
return intersect(*LV, *RV);
1262+
return LV->intersect(*RV);
13141263
}
13151264

13161265
// Return true if Usr has Op as an operand, otherwise false.
@@ -1522,7 +1471,7 @@ LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
15221471
// but then the result is not cached.
15231472
intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock, CxtI);
15241473

1525-
return intersect(*LocalResult, InBlock);
1474+
return LocalResult->intersect(InBlock);
15261475
}
15271476

15281477
ValueLatticeElement LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB,
@@ -1612,7 +1561,7 @@ ValueLatticeElement LazyValueInfoImpl::getValueAtUse(const Use &U) {
16121561
PHI->getParent(), /*UseBlockValue*/ false);
16131562
}
16141563
if (CondVal)
1615-
VL = intersect(VL, *CondVal);
1564+
VL = VL.intersect(*CondVal);
16161565

16171566
// Only follow one-use chain, to allow direct intersection of conditions.
16181567
// If there are multiple uses, we would have to intersect with the union of

llvm/lib/Analysis/ValueLattice.cpp

+56
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,62 @@ ValueLatticeElement::getCompare(CmpInst::Predicate Pred, Type *Ty,
5353
return nullptr;
5454
}
5555

56+
static bool hasSingleValue(const ValueLatticeElement &Val) {
57+
if (Val.isConstantRange() && Val.getConstantRange().isSingleElement())
58+
// Integer constants are single element ranges
59+
return true;
60+
return Val.isConstant();
61+
}
62+
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.
68+
/// Notes:
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.
77+
ValueLatticeElement
78+
ValueLatticeElement::intersect(const ValueLatticeElement &Other) const {
79+
if (isUnknown())
80+
return *this;
81+
if (Other.isUnknown())
82+
return Other;
83+
84+
// If we gave up for one, but got a useable fact from the other, use it.
85+
if (isOverdefined())
86+
return Other;
87+
if (Other.isOverdefined())
88+
return *this;
89+
90+
// Can't get any more precise than constants.
91+
if (hasSingleValue(*this))
92+
return *this;
93+
if (hasSingleValue(Other))
94+
return Other;
95+
96+
// Could be either constant range or not constant here.
97+
if (!isConstantRange() || !Other.isConstantRange()) {
98+
// TODO: Arbitrary choice, could be improved
99+
return *this;
100+
}
101+
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());
110+
}
111+
56112
raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val) {
57113
if (Val.isUnknown())
58114
return OS << "unknown";

0 commit comments

Comments
 (0)