[llvm] [ValueLattice] Use two uint64_t when possible (PR #226642)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 25 22:54:43 PDT 2026
https://github.com/aokblast created https://github.com/llvm/llvm-project/pull/226642
None
>From af83fa1fef06805ad8b1c82769f95105cf077c62 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Sat, 26 Sep 2026 00:53:46 -0500
Subject: [PATCH] [ValueLattice] Use two uint64_t when possible
---
llvm/include/llvm/Analysis/ValueLattice.h | 111 ++++++++++++++++------
1 file changed, 83 insertions(+), 28 deletions(-)
diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h
index 705ad9a05be0f7..6e153565636165 100644
--- a/llvm/include/llvm/Analysis/ValueLattice.h
+++ b/llvm/include/llvm/Analysis/ValueLattice.h
@@ -83,30 +83,64 @@ class ValueLatticeElement {
// Pointer constants derived from equality predicates may have different
// provenance than the original value. Limit constant propagation if this
// happens to be the case.
- bool MayHaveDifferentProvenance = false;
+ unsigned MayHaveDifferentProvenance : 1;
- /// The union either stores a pointer to a constant or a constant range,
- /// associated to the lattice element. We have to ensure that Range is
- /// initialized or destroyed when changing state to or from constantrange.
+ /// Set when a constant range wider than 64 bits.
+ unsigned IsWideRange : 1;
+
+ /// Bit width of packaged constant range (log2(64) = 6).
+ unsigned RangeBitWidth : 7;
+
+ /// Stores either a constant pointer, the lower bound of a packed range, or
+ /// a pointer to an out-of-line range for widths above 64 bits.
union {
Constant *ConstVal;
- ConstantRange Range;
+ uint64_t RangeLo;
+ ConstantRange *WideRange;
};
+ /// Upper bound of a packed range.
+ uint64_t RangeHi;
+
+ bool hasRangeTag() const {
+ return Tag == constantrange || Tag == constantrange_including_undef;
+ }
+
+ ConstantRange getRangeImpl() const {
+ assert(hasRangeTag() && "not a range");
+ if (IsWideRange)
+ return *WideRange;
+ return ConstantRange(APInt(RangeBitWidth, RangeLo),
+ APInt(RangeBitWidth, RangeHi));
+ }
+
+ void setRangeImpl(ConstantRange CR) {
+ unsigned BW = CR.getBitWidth();
+ if (BW <= 64) {
+ IsWideRange = 0;
+ RangeBitWidth = BW;
+ RangeLo = CR.getLower().getZExtValue();
+ RangeHi = CR.getUpper().getZExtValue();
+ } else {
+ IsWideRange = 1;
+ RangeBitWidth = 0;
+ WideRange = new ConstantRange(std::move(CR));
+ }
+ }
+
+ /// True if the packed range holds exactly one element.
+ bool isSingleElementRange() const {
+ assert(hasRangeTag() && "not a range");
+ if (IsWideRange)
+ return WideRange->isSingleElement();
+ uint64_t Mask = RangeBitWidth >= 64 ? ~0ULL : ((1ULL << RangeBitWidth) - 1);
+ return RangeHi == ((RangeLo + 1) & Mask);
+ }
+
/// Destroy contents of lattice value, without destructing the object.
void destroy() {
- switch (Tag) {
- case overdefined:
- case unknown:
- case undef:
- case constant:
- case notconstant:
- break;
- case constantrange_including_undef:
- case constantrange:
- Range.~ConstantRange();
- break;
- };
+ if (hasRangeTag() && IsWideRange)
+ delete WideRange;
}
public:
@@ -148,18 +182,28 @@ class ValueLatticeElement {
};
// ConstVal and Range are initialized on-demand.
- ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {}
+ ValueLatticeElement()
+ : Tag(unknown), NumRangeExtensions(0), MayHaveDifferentProvenance(0),
+ IsWideRange(0), RangeBitWidth(0), ConstVal(nullptr), RangeHi(0) {}
~ValueLatticeElement() { destroy(); }
ValueLatticeElement(const ValueLatticeElement &Other)
: Tag(Other.Tag), NumRangeExtensions(0),
- MayHaveDifferentProvenance(Other.MayHaveDifferentProvenance) {
+ MayHaveDifferentProvenance(Other.MayHaveDifferentProvenance),
+ IsWideRange(0), RangeBitWidth(0), ConstVal(nullptr), RangeHi(0) {
switch (Other.Tag) {
case constantrange:
case constantrange_including_undef:
- new (&Range) ConstantRange(Other.Range);
NumRangeExtensions = Other.NumRangeExtensions;
+ RangeBitWidth = Other.RangeBitWidth;
+ if (LLVM_UNLIKELY(Other.IsWideRange)) {
+ IsWideRange = 1;
+ WideRange = new ConstantRange(*Other.WideRange);
+ } else {
+ RangeLo = Other.RangeLo;
+ RangeHi = Other.RangeHi;
+ }
break;
case constant:
case notconstant:
@@ -174,12 +218,20 @@ class ValueLatticeElement {
ValueLatticeElement(ValueLatticeElement &&Other)
: Tag(Other.Tag), NumRangeExtensions(0),
- MayHaveDifferentProvenance(Other.MayHaveDifferentProvenance) {
+ MayHaveDifferentProvenance(Other.MayHaveDifferentProvenance),
+ IsWideRange(0), RangeBitWidth(0), ConstVal(nullptr), RangeHi(0) {
switch (Other.Tag) {
case constantrange:
case constantrange_including_undef:
- new (&Range) ConstantRange(std::move(Other.Range));
NumRangeExtensions = Other.NumRangeExtensions;
+ RangeBitWidth = Other.RangeBitWidth;
+ IsWideRange = Other.IsWideRange;
+ if (LLVM_UNLIKELY(Other.IsWideRange))
+ WideRange = Other.WideRange;
+ else {
+ RangeLo = Other.RangeLo;
+ RangeHi = Other.RangeHi;
+ }
break;
case constant:
case notconstant:
@@ -191,6 +243,7 @@ class ValueLatticeElement {
break;
}
Other.Tag = unknown;
+ Other.IsWideRange = 0;
}
ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
@@ -253,7 +306,7 @@ class ValueLatticeElement {
/// contains a single element. In that case, it can be replaced by a constant.
bool isConstantRange(bool UndefAllowed = true) const {
return Tag == constantrange || (Tag == constantrange_including_undef &&
- (UndefAllowed || Range.isSingleElement()));
+ (UndefAllowed || isSingleElementRange()));
}
bool isOverdefined() const { return Tag == overdefined; }
@@ -271,10 +324,10 @@ class ValueLatticeElement {
/// non-singleton constant ranges that may also be undef. Note that this
/// function also returns a range if the range may include undef, but only
/// contains a single element. In that case, it can be replaced by a constant.
- const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
+ ConstantRange getConstantRange(bool UndefAllowed = true) const {
assert(isConstantRange(UndefAllowed) &&
"Cannot get the constant-range of a non-constant-range!");
- return Range;
+ return getRangeImpl();
}
std::optional<APInt> asConstantInteger() const {
@@ -388,7 +441,9 @@ class ValueLatticeElement {
assert(NewR.contains(getConstantRange()) &&
"Existing range must be a subset of NewR");
- Range = std::move(NewR);
+ if (LLVM_UNLIKELY(IsWideRange))
+ delete WideRange;
+ setRangeImpl(std::move(NewR));
return true;
}
@@ -398,7 +453,7 @@ class ValueLatticeElement {
NumRangeExtensions = 0;
Tag = NewTag;
- new (&Range) ConstantRange(std::move(NewR));
+ setRangeImpl(std::move(NewR));
return true;
}
@@ -509,7 +564,7 @@ class ValueLatticeElement {
void setMayHaveDifferentProvenance(bool V) { MayHaveDifferentProvenance = V; }
};
-static_assert(sizeof(ValueLatticeElement) <= 40,
+static_assert(sizeof(ValueLatticeElement) <= 24,
"size of ValueLatticeElement changed unexpectedly");
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS,
More information about the llvm-commits
mailing list