[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:48:49 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/8] 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/8] 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/8] 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/8] 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/8] 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/8] 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));
 

>From ded20155e8852a1d3f6550f586c9e9ef10426ce6 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 18:20:22 +0300
Subject: [PATCH 7/8] refactor

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

diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 0e82864498646..bbbc92af80519 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -766,25 +766,24 @@ APInt APInt::byteSwap() const {
 }
 
 APInt APInt::reverseBits() const {
-  switch (BitWidth) {
-  case 64:
-    return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL));
-  case 32:
-    return APInt(BitWidth, llvm::reverseBits<uint32_t>(U.VAL));
-  case 16:
-    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;
+  if (isSingleWord()) {
+    switch (BitWidth) {
+    case 64:
+      return APInt(BitWidth, llvm::reverseBits<uint64_t>(U.VAL));
+    case 32:
+      return APInt(BitWidth, llvm::reverseBits<uint32_t>(U.VAL));
+    case 16:
+      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:
+      return APInt(BitWidth,
+                   llvm::reverseBits<uint64_t>(U.VAL) >> (64 - BitWidth));
+    }
   }
-  // Special case for all widths less than 64 and non-power-of-2
-  if (isSingleWord())
-    return APInt(BitWidth,
-                 llvm::reverseBits<uint64_t>(U.VAL) >> (64 - BitWidth));
 
   APInt Result(BitWidth, 0);
   unsigned NumWords = getNumWords();

>From f6ca41d673561a5f4d4619983f946618dc20faf7 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Mon, 30 Mar 2026 18:48:02 +0300
Subject: [PATCH 8/8] fix

---
 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 bbbc92af80519..cdead43194c26 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -798,7 +798,7 @@ APInt APInt::reverseBits() const {
   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));
+    Result.U.pVal[I] = (PrevRev >> ExcessBits) | (CurrRev << (64 - ExcessBits));
     PrevRev = CurrRev;
   }
   Result.U.pVal[NumWords - 1] = PrevRev >> ExcessBits;



More information about the llvm-commits mailing list