[llvm] [KnownBits] Add reduceUMin/reduceUMax support (PR #211310)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 23 07:31:10 PDT 2026
https://github.com/MohamedAbdullahi14 updated https://github.com/llvm/llvm-project/pull/211310
>From be918c4f946afb512f491e3bb971439c5013c558 Mon Sep 17 00:00:00 2001
From: Mohamed Abdullahi <Zlac453 at live.rhul.ac.uk>
Date: Wed, 22 Jul 2026 11:56:28 +0100
Subject: [PATCH] [KnownBits] Add reduceUMin/reduceUMax support
Includes exhaustive unit tests
Fixes #210019
---
llvm/include/llvm/Support/KnownBits.h | 10 ++++
llvm/lib/Support/KnownBits.cpp | 44 ++++++++++++++++
llvm/unittests/Support/KnownBitsTest.cpp | 64 ++++++++++++++++++++++++
3 files changed, 118 insertions(+)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index f88e5bdd1a92d..806cecf711e27 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -556,6 +556,16 @@ struct KnownBits {
/// object.
LLVM_ABI KnownBits reduceAdd(unsigned NumElts) const;
+ /// Compute known bits for horizontal umin for a vector with NumElts
+ /// elements, where each element has the known bits represented by this
+ /// object.
+ LLVM_ABI KnownBits reduceUMin(unsigned NumElts) const;
+
+ /// Compute known bits for horizontal umax for a vector with NumElts
+ /// elements, where each element has the known bits represented by this
+ /// object.
+ LLVM_ABI KnownBits reduceUMax(unsigned NumElts) const;
+
KnownBits byteSwap() const {
return KnownBits(Zero.byteSwap(), One.byteSwap());
}
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index c3acd2936e2ee..3d93d66db1b60 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -873,6 +873,50 @@ KnownBits KnownBits::reduceAdd(unsigned NumElts) const {
return Result;
}
+KnownBits KnownBits::reduceUMin(unsigned NumElts) const {
+ unsigned BitWidth = getBitWidth();
+ KnownBits Result(BitWidth);
+
+ if (NumElts == 0)
+ return Result;
+
+ // If all elements are the same constant, the result is that constant.
+ if (isConstant())
+ return KnownBits::makeConstant(getConstant());
+
+ // Selects one element, so any leading 0s or 1s shared by all
+ // elements stay in the result.
+ if (isNonNegative()) {
+ Result.Zero.setHighBits(countMinLeadingZeros());
+ } else if (isNegative()) {
+ Result.One.setHighBits(countMinLeadingOnes());
+ }
+
+ return Result;
+}
+
+KnownBits KnownBits::reduceUMax(unsigned NumElts) const {
+ unsigned BitWidth = getBitWidth();
+ KnownBits Result(BitWidth);
+
+ if (NumElts == 0)
+ return Result;
+
+ // If all elements are the same constant, the result is that constant.
+ if (isConstant())
+ return KnownBits::makeConstant(getConstant());
+
+ // Selects one element, so any leading 0s or 1s shared by all
+ // elements stay in the result.
+ if (isNonNegative()) {
+ Result.Zero.setHighBits(countMinLeadingZeros());
+ } else if (isNegative()) {
+ Result.One.setHighBits(countMinLeadingOnes());
+ }
+
+ return Result;
+}
+
static KnownBits computeForSatAddSub(bool Add, bool Signed,
const KnownBits &LHS,
const KnownBits &RHS) {
diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp
index d4b8dff54f3d6..611883c5a6e9e 100644
--- a/llvm/unittests/Support/KnownBitsTest.cpp
+++ b/llvm/unittests/Support/KnownBitsTest.cpp
@@ -1052,6 +1052,70 @@ TEST(KnownBitsTest, ReduceAddExhaustive) {
}
}
+TEST(KnownBitsTest, ReduceUMinExhaustive) {
+ unsigned Bits = 4;
+ for (unsigned NumElts : {2, 4, 5}) {
+ ForeachKnownBits(Bits, [&](const KnownBits &EltKnown) {
+ KnownBits Computed = EltKnown.reduceUMin(NumElts);
+ KnownBits Exact(Bits);
+ Exact.Zero.setAllBits();
+ Exact.One.setAllBits();
+
+ llvm::function_ref<void(unsigned, APInt)> EnumerateCombinations;
+ auto EnumerateCombinationsImpl = [&](unsigned Depth, APInt Min) {
+ if (Depth == NumElts) {
+ Exact.One &= Min;
+ Exact.Zero &= ~Min;
+ return;
+ }
+ ForeachNumInKnownBits(EltKnown, [&](const APInt &Elt) {
+ EnumerateCombinations(Depth + 1, APIntOps::umin(Min, Elt));
+ });
+ };
+ EnumerateCombinations = EnumerateCombinationsImpl;
+
+ EnumerateCombinations(0, APInt::getMaxValue(Bits));
+
+ if (!Exact.hasConflict()) {
+ EXPECT_TRUE(
+ checkResult("reduceUMin", Exact, Computed, {EltKnown}, false));
+ }
+ });
+ }
+}
+
+TEST(KnownBitsTest, ReduceUMaxExhaustive) {
+ unsigned Bits = 4;
+ for (unsigned NumElts : {2, 4, 5}) {
+ ForeachKnownBits(Bits, [&](const KnownBits &EltKnown) {
+ KnownBits Computed = EltKnown.reduceUMax(NumElts);
+ KnownBits Exact(Bits);
+ Exact.Zero.setAllBits();
+ Exact.One.setAllBits();
+
+ llvm::function_ref<void(unsigned, APInt)> EnumerateCombinations;
+ auto EnumerateCombinationsImpl = [&](unsigned Depth, APInt Max) {
+ if (Depth == NumElts) {
+ Exact.One &= Max;
+ Exact.Zero &= ~Max;
+ return;
+ }
+ ForeachNumInKnownBits(EltKnown, [&](const APInt &Elt) {
+ EnumerateCombinations(Depth + 1, APIntOps::umax(Max, Elt));
+ });
+ };
+ EnumerateCombinations = EnumerateCombinationsImpl;
+
+ EnumerateCombinations(0, APInt::getMinValue(Bits));
+
+ if (!Exact.hasConflict()) {
+ EXPECT_TRUE(
+ checkResult("reduceUMax", Exact, Computed, {EltKnown}, false));
+ }
+ });
+ }
+}
+
TEST(KnownBitsTest, TruncateSatExhaustive) {
for (unsigned FromBits : {4, 8}) {
for (unsigned ToBits = 1; ToBits < FromBits; ++ToBits) {
More information about the llvm-commits
mailing list