[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