[llvm] [Support][APint] Optimize fallback case in APInt::reverseBits (PR #189291)

Max Graey via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 08:16:00 PDT 2026


https://github.com/MaxGraey updated https://github.com/llvm/llvm-project/pull/189291

>From d0e25e4c17bec88cb254be38afa0f25640e21f10 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 00:56:23 +0300
Subject: [PATCH 1/6] add case for 128 bit-width in APInt::reverseBits

---
 llvm/lib/Support/APInt.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 0a9cda5299fc8..ef36f9b782469 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -767,6 +767,12 @@ APInt APInt::byteSwap() const {
 
 APInt APInt::reverseBits() const {
   switch (BitWidth) {
+  case 128: {
+    APInt Result(BitWidth, 0);
+    Result.U.pVal[0] = llvm::reverseBits<uint64_t>(U.pVal[1]);
+    Result.U.pVal[1] = llvm::reverseBits<uint64_t>(U.pVal[0]);
+    return Result;
+  }
   case 64:
     return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL));
   case 32:

>From a8e33c614ce8366030c6c25c87a55bd06c4eb0ee Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 17:17:37 +0300
Subject: [PATCH 2/6] optimize fallback path in reverseBits

---
 llvm/lib/Support/APInt.cpp | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index ef36f9b782469..5a84741b2ef89 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -767,12 +767,6 @@ APInt APInt::byteSwap() const {
 
 APInt APInt::reverseBits() const {
   switch (BitWidth) {
-  case 128: {
-    APInt Result(BitWidth, 0);
-    Result.U.pVal[0] = llvm::reverseBits<uint64_t>(U.pVal[1]);
-    Result.U.pVal[1] = llvm::reverseBits<uint64_t>(U.pVal[0]);
-    return Result;
-  }
   case 64:
     return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL));
   case 32:
@@ -787,18 +781,24 @@ APInt APInt::reverseBits() const {
     break;
   }
 
-  APInt Val(*this);
-  APInt Reversed(BitWidth, 0);
-  unsigned S = BitWidth;
-
-  for (; Val != 0; Val.lshrInPlace(1)) {
-    Reversed <<= 1;
-    Reversed |= Val[0];
-    --S;
+  APInt Result(BitWidth, 0);
+  unsigned NumWords = getNumWords();
+  unsigned ExcessBits = NumWords * 64 - BitWidth;
+  if (LLVM_UNLIKELY(ExcessBits == 0)) {
+    // Fast path. No cross-word shift needed.
+    for (unsigned I = 0; I < NumWords; ++I)
+      Result.U.pVal[I] = llvm::reverseBits<uint64_t>(U.pVal[NumWords - 1 - I]);
+    return Result;
   }
-
-  Reversed <<= S;
-  return Reversed;
+  // Holds reversed bits of the previous (more significant) word.
+  uint64_t PrevRev = llvm::reverseBits<uint64_t>(U.pVal[NumWords - 1]);
+  for (unsigned I = 0; I < NumWords - 1; ++I) {
+    uint64_t CurrRev = llvm::reverseBits<uint64_t>(U.pVal[NumWords - 2 - I]);
+    Result.U.pVal[I] = (CurrRev >> ExcessBits) | (PrevRev << (64 - ExcessBits));
+    PrevRev = CurrRev;
+  }
+  Result.U.pVal[NumWords - 1] = PrevRev >> ExcessBits;
+  return Result;
 }
 
 APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {

>From 74e9ab046ee7b9b5144a92b5fd7426c6900c29b8 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 17:26:45 +0300
Subject: [PATCH 3/6] use APINT_BITS_PER_WORD instead 64

---
 llvm/lib/Support/APInt.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 5a84741b2ef89..1f69ae748895c 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -783,7 +783,7 @@ APInt APInt::reverseBits() const {
 
   APInt Result(BitWidth, 0);
   unsigned NumWords = getNumWords();
-  unsigned ExcessBits = NumWords * 64 - BitWidth;
+  unsigned ExcessBits = NumWords * APINT_BITS_PER_WORD - BitWidth;
   if (LLVM_UNLIKELY(ExcessBits == 0)) {
     // Fast path. No cross-word shift needed.
     for (unsigned I = 0; I < NumWords; ++I)

>From d8857f9d9e04c5edaae715f794507f22a6ce767e Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 18:06:58 +0300
Subject: [PATCH 4/6] add special handing for non-pow-of-2 cases which less
 than 64

---
 llvm/lib/Support/APInt.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 1f69ae748895c..a8ecaa7cde4bb 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -775,11 +775,15 @@ APInt APInt::reverseBits() const {
     return APInt(BitWidth, llvm::reverseBits<uint16_t>(U.VAL));
   case 8:
     return APInt(BitWidth, llvm::reverseBits<uint8_t>(U.VAL));
+  case 1:  // fallthrough
   case 0:
     return *this;
   default:
     break;
   }
+  // Special case for all widths less than 64 and non-power-of-2
+  if (BitWidth < 64)
+      return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL) >> (64 - BitWidth));
 
   APInt Result(BitWidth, 0);
   unsigned NumWords = getNumWords();

>From a28daae81d3dc0dfd29e44bf49c3e946ebc62c34 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 18:10:22 +0300
Subject: [PATCH 5/6] format fixes

---
 llvm/lib/Support/APInt.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index a8ecaa7cde4bb..e9fc4a6c3b27d 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -775,7 +775,7 @@ APInt APInt::reverseBits() const {
     return APInt(BitWidth, llvm::reverseBits<uint16_t>(U.VAL));
   case 8:
     return APInt(BitWidth, llvm::reverseBits<uint8_t>(U.VAL));
-  case 1:  // fallthrough
+  case 1: // fallthrough
   case 0:
     return *this;
   default:
@@ -783,7 +783,8 @@ APInt APInt::reverseBits() const {
   }
   // Special case for all widths less than 64 and non-power-of-2
   if (BitWidth < 64)
-      return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL) >> (64 - BitWidth));
+    return APInt(BitWidth,
+                 llvm::reverseBits<uint64_t>(U.VAL) >> (64 - BitWidth));
 
   APInt Result(BitWidth, 0);
   unsigned NumWords = getNumWords();

>From d07b323ed13798a1db0b7cfe2a4a9037a15a138f Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 18:15:38 +0300
Subject: [PATCH 6/6] use isSingleWord instead direct compare

---
 llvm/lib/Support/APInt.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index e9fc4a6c3b27d..0e82864498646 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -782,7 +782,7 @@ APInt APInt::reverseBits() const {
     break;
   }
   // Special case for all widths less than 64 and non-power-of-2
-  if (BitWidth < 64)
+  if (isSingleWord())
     return APInt(BitWidth,
                  llvm::reverseBits<uint64_t>(U.VAL) >> (64 - BitWidth));
 



More information about the llvm-commits mailing list