[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