[llvm] [KnownBits] Optimize isConstant (NFC) (PR #191919)
Max Graey via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 06:25:28 PDT 2026
https://github.com/MaxGraey updated https://github.com/llvm/llvm-project/pull/191919
>From 7bd5aaeffb247c23a051ffca097d011ea36dde5c Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Tue, 14 Apr 2026 04:18:19 +0300
Subject: [PATCH 1/3] init
---
llvm/include/llvm/Support/KnownBits.h | 8 +++++++-
llvm/lib/Support/KnownBits.cpp | 14 ++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index ecedccc9afd95..d3ce50c7f78d1 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -52,7 +52,10 @@ struct KnownBits {
/// Returns true if we know the value of all bits.
bool isConstant() const {
- return Zero.popcount() + One.popcount() == getBitWidth();
+ if (Zero.isSingleWord())
+ return (Zero.getZExtValue() | One.getZExtValue()) ==
+ llvm::maskTrailingOnes<uint64_t>(getBitWidth());
+ return isConstantSlowCase();
}
/// Returns the value when all bits have a known value. This just returns One
@@ -576,6 +579,9 @@ struct KnownBits {
// Internal helper for getting the initial KnownBits for an `srem` or `urem`
// operation with the low-bits set.
static KnownBits remGetLowBits(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Multi-word case helper for isConstant().
+ bool isConstantSlowCase() const;
};
inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 07e7781d0839d..fc84f7b4100a7 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -19,6 +19,20 @@
using namespace llvm;
+bool KnownBits::isConstantSlowCase() const {
+ const unsigned LastWord = Zero.getNumWords() - 1;
+ const uint64_t *Zeros = Zero.getRawData();
+ const uint64_t *Ones = One.getRawData();
+
+ for (unsigned I = 0; I != LastWord; ++I)
+ if ((Zeros[I] | Ones[I]) != UINT64_MAX)
+ return false;
+
+ unsigned TailBits = getBitWidth() - LastWord * APInt::APINT_BITS_PER_WORD;
+ uint64_t TailMask = llvm::maskTrailingOnes<uint64_t>(TailBits);
+ return ((Zeros[LastWord] | Ones[LastWord]) & TailMask) == TailMask;
+}
+
KnownBits KnownBits::flipSignBit(const KnownBits &Val) {
unsigned SignBitPosition = Val.getBitWidth() - 1;
APInt Zero = Val.Zero;
>From 1b92e666d8effe816fd64c2a21459b33e3409dcf Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Tue, 14 Apr 2026 13:19:12 +0300
Subject: [PATCH 2/3] minor tuning
---
llvm/include/llvm/Support/KnownBits.h | 2 +-
llvm/lib/Support/KnownBits.cpp | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index d3ce50c7f78d1..c27eb651aa64d 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -52,7 +52,7 @@ struct KnownBits {
/// Returns true if we know the value of all bits.
bool isConstant() const {
- if (Zero.isSingleWord())
+ if (LLVM_LIKELY(Zero.isSingleWord()))
return (Zero.getZExtValue() | One.getZExtValue()) ==
llvm::maskTrailingOnes<uint64_t>(getBitWidth());
return isConstantSlowCase();
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index fc84f7b4100a7..b22acc1a2f3eb 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -20,17 +20,17 @@
using namespace llvm;
bool KnownBits::isConstantSlowCase() const {
- const unsigned LastWord = Zero.getNumWords() - 1;
+ const unsigned Last = Zero.getNumWords() - 1;
const uint64_t *Zeros = Zero.getRawData();
const uint64_t *Ones = One.getRawData();
- for (unsigned I = 0; I != LastWord; ++I)
+ for (unsigned I = 0; I != Last; ++I)
if ((Zeros[I] | Ones[I]) != UINT64_MAX)
return false;
- unsigned TailBits = getBitWidth() - LastWord * APInt::APINT_BITS_PER_WORD;
+ unsigned TailBits = getBitWidth() - Last * APInt::APINT_BITS_PER_WORD;
uint64_t TailMask = llvm::maskTrailingOnes<uint64_t>(TailBits);
- return ((Zeros[LastWord] | Ones[LastWord]) & TailMask) == TailMask;
+ return ((Zeros[Last] | Ones[Last]) & TailMask) == TailMask;
}
KnownBits KnownBits::flipSignBit(const KnownBits &Val) {
>From c1144c54f40d6f502a3253956c0a75fdf5baa498 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 16 Apr 2026 16:25:12 +0300
Subject: [PATCH 3/3] refactor: add isExhaustive for APInt and utilize it for
isConstant
---
llvm/include/llvm/ADT/APInt.h | 15 +++++++++++++++
llvm/include/llvm/Support/KnownBits.h | 8 +-------
llvm/lib/Support/APInt.cpp | 14 ++++++++++++++
llvm/lib/Support/KnownBits.cpp | 14 --------------
4 files changed, 30 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 683eea4fb19a3..d0bc5b77cc2d3 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -1268,6 +1268,18 @@ class [[nodiscard]] APInt {
return isSubsetOfSlowCase(RHS);
}
+ /// This operation checks if valid bits exclusively set in this APInt or RHS.
+ bool isExhaustive(const APInt &RHS) const {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord()) {
+ WordType Mask = BitWidth == APINT_BITS_PER_WORD
+ ? WORDTYPE_MAX
+ : llvm::maskTrailingOnes<WordType>(BitWidth);
+ return ((U.VAL | RHS.U.VAL) & Mask) == Mask;
+ }
+ return isExhaustiveSlowCase(RHS);
+ }
+
/// @}
/// \name Resizing Operators
/// @{
@@ -2094,6 +2106,9 @@ class [[nodiscard]] APInt {
/// out-of-line slow case for isSubsetOf.
LLVM_ABI bool isSubsetOfSlowCase(const APInt &RHS) const LLVM_READONLY;
+ /// out-of-line slow case for isExhaustive.
+ LLVM_ABI bool isExhaustiveSlowCase(const APInt &RHS) const LLVM_READONLY;
+
/// out-of-line slow case for setBits.
LLVM_ABI void setBitsSlowCase(unsigned loBit, unsigned hiBit);
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index c27eb651aa64d..2f6b9afa38cb3 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -52,10 +52,7 @@ struct KnownBits {
/// Returns true if we know the value of all bits.
bool isConstant() const {
- if (LLVM_LIKELY(Zero.isSingleWord()))
- return (Zero.getZExtValue() | One.getZExtValue()) ==
- llvm::maskTrailingOnes<uint64_t>(getBitWidth());
- return isConstantSlowCase();
+ return Zero.isExhaustive(One);
}
/// Returns the value when all bits have a known value. This just returns One
@@ -579,9 +576,6 @@ struct KnownBits {
// Internal helper for getting the initial KnownBits for an `srem` or `urem`
// operation with the low-bits set.
static KnownBits remGetLowBits(const KnownBits &LHS, const KnownBits &RHS);
-
- /// Multi-word case helper for isConstant().
- bool isConstantSlowCase() const;
};
inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 6aa5fc615a302..f054cc0b17e7b 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -753,6 +753,20 @@ bool APInt::isSubsetOfSlowCase(const APInt &RHS) const {
return true;
}
+bool APInt::isExhaustiveSlowCase(const APInt &RHS) const {
+ const unsigned Last = getNumWords() - 1;
+ const WordType *LHSWords = getRawData();
+ const WordType *RHSWords = RHS.getRawData();
+
+ for (unsigned I = 0; I != Last; ++I)
+ if ((LHSWords[I] | RHSWords[I]) != WORDTYPE_MAX)
+ return false;
+
+ unsigned TailBits = BitWidth - Last * APINT_BITS_PER_WORD;
+ WordType TailMask = llvm::maskTrailingOnes<WordType>(TailBits);
+ return ((LHSWords[Last] | RHSWords[Last]) & TailMask) == TailMask;
+}
+
APInt APInt::byteSwap() const {
assert(BitWidth >= 16 && BitWidth % 8 == 0 && "Cannot byteswap!");
if (BitWidth == 16)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index b22acc1a2f3eb..07e7781d0839d 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -19,20 +19,6 @@
using namespace llvm;
-bool KnownBits::isConstantSlowCase() const {
- const unsigned Last = Zero.getNumWords() - 1;
- const uint64_t *Zeros = Zero.getRawData();
- const uint64_t *Ones = One.getRawData();
-
- for (unsigned I = 0; I != Last; ++I)
- if ((Zeros[I] | Ones[I]) != UINT64_MAX)
- return false;
-
- unsigned TailBits = getBitWidth() - Last * APInt::APINT_BITS_PER_WORD;
- uint64_t TailMask = llvm::maskTrailingOnes<uint64_t>(TailBits);
- return ((Zeros[Last] | Ones[Last]) & TailMask) == TailMask;
-}
-
KnownBits KnownBits::flipSignBit(const KnownBits &Val) {
unsigned SignBitPosition = Val.getBitWidth() - 1;
APInt Zero = Val.Zero;
More information about the llvm-commits
mailing list