[llvm] a5b6068 - [ValueLattice] Move intersect from LVI into ValueLattice API (NFC)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 28 06:18:44 PDT 2024
Author: Nikita Popov
Date: 2024-08-28T15:18:31+02:00
New Revision: a5b60684468ceb7d6e45e24ce94f3a49c6606b6f
URL: https://github.com/llvm/llvm-project/commit/a5b60684468ceb7d6e45e24ce94f3a49c6606b6f
DIFF: https://github.com/llvm/llvm-project/commit/a5b60684468ceb7d6e45e24ce94f3a49c6606b6f.diff
LOG: [ValueLattice] Move intersect from LVI into ValueLattice API (NFC)
So we can reuse the logic inside IPSCCP.
Added:
Modified:
llvm/include/llvm/Analysis/ValueLattice.h
llvm/lib/Analysis/LazyValueInfo.cpp
llvm/lib/Analysis/ValueLattice.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h
index a704cce0c082b9..9357a15f7619f1 100644
--- a/llvm/include/llvm/Analysis/ValueLattice.h
+++ b/llvm/include/llvm/Analysis/ValueLattice.h
@@ -471,6 +471,23 @@ class ValueLatticeElement {
const ValueLatticeElement &Other,
const DataLayout &DL) const;
+ /// Combine two sets of facts about the same value into a single set of
+ /// facts. Note that this method is not suitable for merging facts along
+ ///
diff erent paths in a CFG; that's what the mergeIn function is for. This
+ /// is for merging facts gathered about the same value at the same location
+ /// through two independent means.
+ /// Notes:
+ /// * This method does not promise to return the most precise possible lattice
+ /// value implied by A and B. It is allowed to return any lattice element
+ /// which is at least as strong as *either* A or B (unless our facts
+ /// conflict, see below).
+ /// * Due to unreachable code, the intersection of two lattice values could be
+ /// contradictory. If this happens, we return some valid lattice value so
+ /// as not confuse the rest of LVI. Ideally, we'd always return Undefined,
+ /// but we do not make this guarantee. TODO: This would be a useful
+ /// enhancement.
+ ValueLatticeElement intersect(const ValueLatticeElement &Other) const;
+
unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
};
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 615d8b7ccd8ccf..69e0627a89cc29 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -83,57 +83,6 @@ static bool hasSingleValue(const ValueLatticeElement &Val) {
return false;
}
-/// Combine two sets of facts about the same value into a single set of
-/// facts. Note that this method is not suitable for merging facts along
-///
diff erent paths in a CFG; that's what the mergeIn function is for. This
-/// is for merging facts gathered about the same value at the same location
-/// through two independent means.
-/// Notes:
-/// * This method does not promise to return the most precise possible lattice
-/// value implied by A and B. It is allowed to return any lattice element
-/// which is at least as strong as *either* A or B (unless our facts
-/// conflict, see below).
-/// * Due to unreachable code, the intersection of two lattice values could be
-/// contradictory. If this happens, we return some valid lattice value so as
-/// not confuse the rest of LVI. Ideally, we'd always return Undefined, but
-/// we do not make this guarantee. TODO: This would be a useful enhancement.
-static ValueLatticeElement intersect(const ValueLatticeElement &A,
- const ValueLatticeElement &B) {
- // Undefined is the strongest state. It means the value is known to be along
- // an unreachable path.
- if (A.isUnknown())
- return A;
- if (B.isUnknown())
- return B;
-
- // If we gave up for one, but got a useable fact from the other, use it.
- if (A.isOverdefined())
- return B;
- if (B.isOverdefined())
- return A;
-
- // Can't get any more precise than constants.
- if (hasSingleValue(A))
- return A;
- if (hasSingleValue(B))
- return B;
-
- // Could be either constant range or not constant here.
- if (!A.isConstantRange() || !B.isConstantRange()) {
- // TODO: Arbitrary choice, could be improved
- return A;
- }
-
- // Intersect two constant ranges
- ConstantRange Range =
- A.getConstantRange().intersectWith(B.getConstantRange());
- // Note: An empty range is implicitly converted to unknown or undef depending
- // on MayIncludeUndef internally.
- return ValueLatticeElement::getRange(
- std::move(Range), /*MayIncludeUndef=*/A.isConstantRangeIncludingUndef() ||
- B.isConstantRangeIncludingUndef());
-}
-
//===----------------------------------------------------------------------===//
// LazyValueInfoCache Decl
//===----------------------------------------------------------------------===//
@@ -812,9 +761,9 @@ void LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange(
if (I->getParent() != BB || !isValidAssumeForContext(I, BBI))
continue;
- BBLV = intersect(BBLV, *getValueFromCondition(Val, I->getArgOperand(0),
- /*IsTrueDest*/ true,
- /*UseBlockValue*/ false));
+ BBLV = BBLV.intersect(*getValueFromCondition(Val, I->getArgOperand(0),
+ /*IsTrueDest*/ true,
+ /*UseBlockValue*/ false));
}
// If guards are not used in the module, don't spend time looking for them
@@ -824,9 +773,9 @@ void LazyValueInfoImpl::intersectAssumeOrGuardBlockValueConstantRange(
make_range(std::next(BBI->getIterator().getReverse()), BB->rend())) {
Value *Cond = nullptr;
if (match(&I, m_Intrinsic<Intrinsic::experimental_guard>(m_Value(Cond))))
- BBLV = intersect(BBLV,
- *getValueFromCondition(Val, Cond, /*IsTrueDest*/ true,
- /*UseBlockValue*/ false));
+ BBLV = BBLV.intersect(*getValueFromCondition(Val, Cond,
+ /*IsTrueDest*/ true,
+ /*UseBlockValue*/ false));
}
}
@@ -913,13 +862,13 @@ LazyValueInfoImpl::solveBlockValueSelect(SelectInst *SI, BasicBlock *BB) {
// the select condition.
if (isGuaranteedNotToBeUndef(Cond, AC)) {
TrueVal =
- intersect(TrueVal, *getValueFromCondition(SI->getTrueValue(), Cond,
- /*IsTrueDest*/ true,
- /*UseBlockValue*/ false));
+ TrueVal.intersect(*getValueFromCondition(SI->getTrueValue(), Cond,
+ /*IsTrueDest*/ true,
+ /*UseBlockValue*/ false));
FalseVal =
- intersect(FalseVal, *getValueFromCondition(SI->getFalseValue(), Cond,
- /*IsTrueDest*/ false,
- /*UseBlockValue*/ false));
+ FalseVal.intersect(*getValueFromCondition(SI->getFalseValue(), Cond,
+ /*IsTrueDest*/ false,
+ /*UseBlockValue*/ false));
}
ValueLatticeElement Result = TrueVal;
@@ -1037,9 +986,9 @@ LazyValueInfoImpl::solveBlockValueIntrinsic(IntrinsicInst *II, BasicBlock *BB) {
OpRanges.push_back(*Range);
}
- return intersect(ValueLatticeElement::getRange(ConstantRange::intrinsic(
- II->getIntrinsicID(), OpRanges)),
- MetadataVal);
+ return ValueLatticeElement::getRange(
+ ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges))
+ .intersect(MetadataVal);
}
std::optional<ValueLatticeElement>
@@ -1310,7 +1259,7 @@ LazyValueInfoImpl::getValueFromCondition(Value *Val, Value *Cond,
return *LV;
}
- return intersect(*LV, *RV);
+ return LV->intersect(*RV);
}
// Return true if Usr has Op as an operand, otherwise false.
@@ -1522,7 +1471,7 @@ LazyValueInfoImpl::getEdgeValue(Value *Val, BasicBlock *BBFrom,
// but then the result is not cached.
intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock, CxtI);
- return intersect(*LocalResult, InBlock);
+ return LocalResult->intersect(InBlock);
}
ValueLatticeElement LazyValueInfoImpl::getValueInBlock(Value *V, BasicBlock *BB,
@@ -1612,7 +1561,7 @@ ValueLatticeElement LazyValueInfoImpl::getValueAtUse(const Use &U) {
PHI->getParent(), /*UseBlockValue*/ false);
}
if (CondVal)
- VL = intersect(VL, *CondVal);
+ VL = VL.intersect(*CondVal);
// Only follow one-use chain, to allow direct intersection of conditions.
// If there are multiple uses, we would have to intersect with the union of
diff --git a/llvm/lib/Analysis/ValueLattice.cpp b/llvm/lib/Analysis/ValueLattice.cpp
index 5001fc2d310dd4..03810f1c554e5d 100644
--- a/llvm/lib/Analysis/ValueLattice.cpp
+++ b/llvm/lib/Analysis/ValueLattice.cpp
@@ -53,6 +53,62 @@ ValueLatticeElement::getCompare(CmpInst::Predicate Pred, Type *Ty,
return nullptr;
}
+static bool hasSingleValue(const ValueLatticeElement &Val) {
+ if (Val.isConstantRange() && Val.getConstantRange().isSingleElement())
+ // Integer constants are single element ranges
+ return true;
+ return Val.isConstant();
+}
+
+/// Combine two sets of facts about the same value into a single set of
+/// facts. Note that this method is not suitable for merging facts along
+///
diff erent paths in a CFG; that's what the mergeIn function is for. This
+/// is for merging facts gathered about the same value at the same location
+/// through two independent means.
+/// Notes:
+/// * This method does not promise to return the most precise possible lattice
+/// value implied by A and B. It is allowed to return any lattice element
+/// which is at least as strong as *either* A or B (unless our facts
+/// conflict, see below).
+/// * Due to unreachable code, the intersection of two lattice values could be
+/// contradictory. If this happens, we return some valid lattice value so as
+/// not confuse the rest of LVI. Ideally, we'd always return Undefined, but
+/// we do not make this guarantee. TODO: This would be a useful enhancement.
+ValueLatticeElement
+ValueLatticeElement::intersect(const ValueLatticeElement &Other) const {
+ if (isUnknown())
+ return *this;
+ if (Other.isUnknown())
+ return Other;
+
+ // If we gave up for one, but got a useable fact from the other, use it.
+ if (isOverdefined())
+ return Other;
+ if (Other.isOverdefined())
+ return *this;
+
+ // Can't get any more precise than constants.
+ if (hasSingleValue(*this))
+ return *this;
+ if (hasSingleValue(Other))
+ return Other;
+
+ // Could be either constant range or not constant here.
+ if (!isConstantRange() || !Other.isConstantRange()) {
+ // TODO: Arbitrary choice, could be improved
+ return *this;
+ }
+
+ // Intersect two constant ranges
+ ConstantRange Range =
+ getConstantRange().intersectWith(Other.getConstantRange());
+ // Note: An empty range is implicitly converted to unknown or undef depending
+ // on MayIncludeUndef internally.
+ return ValueLatticeElement::getRange(
+ std::move(Range), /*MayIncludeUndef=*/isConstantRangeIncludingUndef() ||
+ Other.isConstantRangeIncludingUndef());
+}
+
raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val) {
if (Val.isUnknown())
return OS << "unknown";
More information about the llvm-commits
mailing list