[llvm] [KnownBits] Add fast path for udiv by pow2 and overloads for shift ops by constant (PR #189779)
Max Graey via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 2 11:50:37 PDT 2026
https://github.com/MaxGraey updated https://github.com/llvm/llvm-project/pull/189779
>From bc71364b702b686d437e63bd8fb043ff3d001a6b Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Wed, 1 Apr 2026 03:48:37 +0300
Subject: [PATCH 01/17] add fast-path for KnownBits::udiv when RHS is contant
---
llvm/lib/Support/KnownBits.cpp | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 07e7781d0839d..5809fff3ad6ab 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -1209,6 +1209,20 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
return Known;
}
+ if (RHS.isConstant()) {
+ const APInt Divisor = RHS.getConstant();
+ if (Divisor.isOne())
+ return LHS;
+
+ if (Divisor.isPowerOf2()) {
+ unsigned Shift = Divisor.logBase2();
+ KnownBits Known = LHS;
+ Known.One.lshrInPlace(Shift);
+ Known.Zero.lshrInPlace(Shift);
+ return Known;
+ }
+ }
+
// We can figure out the minimum number of upper zero bits by doing
// MaxNumerator / MinDenominator. If the Numerator gets smaller or Denominator
// gets larger, the number of upper zero bits increases.
>From 98fbc0b1f97150ca44a9fe1b4ca9152665c75868 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Wed, 1 Apr 2026 03:56:48 +0300
Subject: [PATCH 02/17] refactor
---
llvm/lib/Support/KnownBits.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 5809fff3ad6ab..25530d7e46727 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -1216,7 +1216,7 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
if (Divisor.isPowerOf2()) {
unsigned Shift = Divisor.logBase2();
- KnownBits Known = LHS;
+ Known = LHS;
Known.One.lshrInPlace(Shift);
Known.Zero.lshrInPlace(Shift);
return Known;
>From f326a707d239257f17684715800cb511c523dda9 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Wed, 1 Apr 2026 05:01:20 +0300
Subject: [PATCH 03/17] fix: preserve high bits of LHS
---
llvm/lib/Support/KnownBits.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 25530d7e46727..56ec9de6af77e 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -1216,9 +1216,15 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
if (Divisor.isPowerOf2()) {
unsigned Shift = Divisor.logBase2();
+
+ APInt MaxRes = LHS.getMaxValue().lshr(Shift);
+ unsigned LeadZ = MaxRes.countLeadingZeros();
+
Known = LHS;
Known.One.lshrInPlace(Shift);
Known.Zero.lshrInPlace(Shift);
+ Known.Zero.setHighBits(LeadZ);
+
return Known;
}
}
>From 7c6b11aeec5d951c899adbae80635abd721540e9 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Wed, 1 Apr 2026 11:31:59 +0300
Subject: [PATCH 04/17] update mir tests
---
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sdiv.mir | 4 ++--
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-udiv.mir | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sdiv.mir
index 7b315205bc2e8..ae56e9097c99f 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sdiv.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sdiv.mir
@@ -8,7 +8,7 @@ body: |
; CHECK-LABEL: name: @Cst
; CHECK-NEXT: %0:_ KnownBits:01100100 SignBits:1
; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
- ; CHECK-NEXT: %2:_ KnownBits:000????? SignBits:3
+ ; CHECK-NEXT: %2:_ KnownBits:00011001 SignBits:3
%0:_(s8) = G_CONSTANT i8 100
%1:_(s8) = G_CONSTANT i8 4
%2:_(s8) = G_SDIV %0, %1
@@ -36,7 +36,7 @@ body: |
; CHECK-LABEL: name: @Exact
; CHECK-NEXT: %0:_ KnownBits:00001100 SignBits:4
; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
- ; CHECK-NEXT: %2:_ KnownBits:000000?1 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:00000011 SignBits:6
%0:_(s8) = G_CONSTANT i8 12
%1:_(s8) = G_CONSTANT i8 4
%2:_(s8) = exact G_SDIV %0, %1
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-udiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-udiv.mir
index dfbcd3f3c6188..0a0a00ce456ae 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-udiv.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-udiv.mir
@@ -8,7 +8,7 @@ body: |
; CHECK-LABEL: name: @Cst
; CHECK-NEXT: %0:_ KnownBits:01100100 SignBits:1
; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
- ; CHECK-NEXT: %2:_ KnownBits:000????? SignBits:3
+ ; CHECK-NEXT: %2:_ KnownBits:00011001 SignBits:3
%0:_(s8) = G_CONSTANT i8 100
%1:_(s8) = G_CONSTANT i8 4
%2:_(s8) = G_UDIV %0, %1
@@ -36,7 +36,7 @@ body: |
; CHECK-LABEL: name: @Exact
; CHECK-NEXT: %0:_ KnownBits:00001100 SignBits:4
; CHECK-NEXT: %1:_ KnownBits:00000100 SignBits:5
- ; CHECK-NEXT: %2:_ KnownBits:000000?1 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:00000011 SignBits:6
%0:_(s8) = G_CONSTANT i8 12
%1:_(s8) = G_CONSTANT i8 4
%2:_(s8) = exact G_UDIV %0, %1
>From c223b1f1b92bc4d0c4b90e6e7c9b55fe9b7031e0 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Wed, 1 Apr 2026 13:36:25 +0300
Subject: [PATCH 05/17] simplify
---
llvm/lib/Support/KnownBits.cpp | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 56ec9de6af77e..97ae3138356ee 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -1209,24 +1209,12 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
return Known;
}
- if (RHS.isConstant()) {
- const APInt Divisor = RHS.getConstant();
- if (Divisor.isOne())
- return LHS;
-
- if (Divisor.isPowerOf2()) {
- unsigned Shift = Divisor.logBase2();
-
- APInt MaxRes = LHS.getMaxValue().lshr(Shift);
- unsigned LeadZ = MaxRes.countLeadingZeros();
-
- Known = LHS;
- Known.One.lshrInPlace(Shift);
- Known.Zero.lshrInPlace(Shift);
- Known.Zero.setHighBits(LeadZ);
-
- return Known;
- }
+ if (RHS.isConstant() && RHS.getConstant().isPowerOf2()) {
+ unsigned Shift = RHS.getConstant().logBase2();
+ Known = LHS;
+ Known >>= Shift;
+ Known.Zero.setHighBits(Shift);
+ return Known;
}
// We can figure out the minimum number of upper zero bits by doing
>From 185302411f5ea48bc3d5c4c48b90566a9da8cb76 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 03:15:09 +0300
Subject: [PATCH 06/17] refactor: intoduce shifted by const KnownBits::lshr and
KnownBits::ashr versions and reuse it
---
llvm/include/llvm/Support/KnownBits.h | 8 ++++++
llvm/lib/Support/KnownBits.cpp | 38 +++++++++++++--------------
2 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index d99817dc43e5b..d773339d679cf 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -460,11 +460,19 @@ struct KnownBits {
bool NUW = false, bool NSW = false,
bool ShAmtNonZero = false);
+ /// Compute known bits for lshr(LHS, ShiftAmt).
+ /// This is shift by constant variant of lshr(LHS, RHS).
+ LLVM_ABI static KnownBits lshr(const KnownBits &LHS, unsigned ShiftAmt);
+
/// Compute known bits for lshr(LHS, RHS).
/// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
LLVM_ABI static KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS,
bool ShAmtNonZero = false, bool Exact = false);
+ /// Compute known bits for ashr(LHS, ShiftAmt).
+ /// This is shift by constant variant of ashr(LHS, RHS).
+ LLVM_ABI static KnownBits ashr(const KnownBits &LHS, unsigned ShiftAmt);
+
/// Compute known bits for ashr(LHS, RHS).
/// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
LLVM_ABI static KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS,
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 97ae3138356ee..fb1a9f8638639 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -488,16 +488,17 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
return Known;
}
+KnownBits KnownBits::lshr(const KnownBits &LHS, unsigned ShiftAmt) {
+ KnownBits Known = LHS;
+ Known >>= ShiftAmt;
+ // High bits are known zero.
+ Known.Zero.setHighBits(ShiftAmt);
+ return Known;
+}
+
KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS,
bool ShAmtNonZero, bool Exact) {
unsigned BitWidth = LHS.getBitWidth();
- auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) {
- KnownBits Known = LHS;
- Known >>= ShiftAmt;
- // High bits are known zero.
- Known.Zero.setHighBits(ShiftAmt);
- return Known;
- };
// Fast path for a common case when LHS is completely unknown.
KnownBits Known(BitWidth);
@@ -533,7 +534,7 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS,
if ((ShiftAmtZeroMask & ShiftAmt) != 0 ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
- Known = Known.intersectWith(ShiftByConst(LHS, ShiftAmt));
+ Known = Known.intersectWith(lshr(LHS, ShiftAmt));
if (Known.isUnknown())
break;
}
@@ -544,15 +545,16 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS,
return Known;
}
+KnownBits KnownBits::ashr(const KnownBits &LHS, unsigned ShiftAmt) {
+ KnownBits Known = LHS;
+ Known.Zero.ashrInPlace(ShiftAmt);
+ Known.One.ashrInPlace(ShiftAmt);
+ return Known;
+}
+
KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS,
bool ShAmtNonZero, bool Exact) {
unsigned BitWidth = LHS.getBitWidth();
- auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) {
- KnownBits Known = LHS;
- Known.Zero.ashrInPlace(ShiftAmt);
- Known.One.ashrInPlace(ShiftAmt);
- return Known;
- };
// Fast path for a common case when LHS is completely unknown.
KnownBits Known(BitWidth);
@@ -592,7 +594,7 @@ KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS,
if ((ShiftAmtZeroMask & ShiftAmt) != 0 ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
- Known = Known.intersectWith(ShiftByConst(LHS, ShiftAmt));
+ Known = Known.intersectWith(ashr(LHS, ShiftAmt));
if (Known.isUnknown())
break;
}
@@ -1210,11 +1212,7 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
}
if (RHS.isConstant() && RHS.getConstant().isPowerOf2()) {
- unsigned Shift = RHS.getConstant().logBase2();
- Known = LHS;
- Known >>= Shift;
- Known.Zero.setHighBits(Shift);
- return Known;
+ return lshr(LHS, RHS.getConstant().logBase2());
}
// We can figure out the minimum number of upper zero bits by doing
>From a045228f606745445eab57adde4dd3730fb992e1 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 14:39:13 +0300
Subject: [PATCH 07/17] add KnownBits::shl with immidiate shift overload
---
llvm/include/llvm/Support/KnownBits.h | 5 +++
llvm/lib/Support/KnownBits.cpp | 44 ++++++++++++++-------------
2 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index d773339d679cf..131908d205ddf 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -454,6 +454,11 @@ struct KnownBits {
/// Compute known bits for abds(LHS, RHS).
LLVM_ABI static KnownBits abds(KnownBits LHS, KnownBits RHS);
+ /// Compute known bits for shl(LHS, ShiftAmt).
+ /// This is shift by constant variant of shl(LHS, RHS).
+ LLVM_ABI static KnownBits shl(const KnownBits &LHS, unsigned ShiftAmt,
+ bool NUW = false, bool NSW = false);
+
/// Compute known bits for shl(LHS, RHS).
/// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
LLVM_ABI static KnownBits shl(const KnownBits &LHS, const KnownBits &RHS,
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index fb1a9f8638639..82bf6c1229960 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -404,29 +404,31 @@ static unsigned getMaxShiftAmount(const APInt &MaxValue, unsigned BitWidth) {
return MaxValue.getLimitedValue(BitWidth - 1);
}
+KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt, bool NUW,
+ bool NSW) {
+ KnownBits Known;
+ bool ShiftedOutZero, ShiftedOutOne;
+ Known.Zero = LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero);
+ Known.Zero.setLowBits(ShiftAmt);
+ Known.One = LHS.One.ushl_ov(ShiftAmt, ShiftedOutOne);
+
+ // All cases returning poison have been handled by MaxShiftAmount already.
+ if (NSW) {
+ if (NUW && ShiftAmt != 0)
+ // NUW means we can assume anything shifted out was a zero.
+ ShiftedOutZero = true;
+
+ if (ShiftedOutZero)
+ Known.makeNonNegative();
+ else if (ShiftedOutOne)
+ Known.makeNegative();
+ }
+ return Known;
+}
+
KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
bool NSW, bool ShAmtNonZero) {
unsigned BitWidth = LHS.getBitWidth();
- auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) {
- KnownBits Known;
- bool ShiftedOutZero, ShiftedOutOne;
- Known.Zero = LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero);
- Known.Zero.setLowBits(ShiftAmt);
- Known.One = LHS.One.ushl_ov(ShiftAmt, ShiftedOutOne);
-
- // All cases returning poison have been handled by MaxShiftAmount already.
- if (NSW) {
- if (NUW && ShiftAmt != 0)
- // NUW means we can assume anything shifted out was a zero.
- ShiftedOutZero = true;
-
- if (ShiftedOutZero)
- Known.makeNonNegative();
- else if (ShiftedOutOne)
- Known.makeNegative();
- }
- return Known;
- };
// Fast path for a common case when LHS is completely unknown.
KnownBits Known(BitWidth);
@@ -477,7 +479,7 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
if ((ShiftAmtZeroMask & ShiftAmt) != 0 ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
- Known = Known.intersectWith(ShiftByConst(LHS, ShiftAmt));
+ Known = Known.intersectWith(shl(LHS, ShiftAmt, NUW, NSW));
if (Known.isUnknown())
break;
}
>From d0314c064c6a1ee0df252ca61331fd4654deac9d Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 15:37:33 +0300
Subject: [PATCH 08/17] fix?
---
llvm/lib/Support/KnownBits.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 82bf6c1229960..5df6123a9b59b 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -406,7 +406,7 @@ static unsigned getMaxShiftAmount(const APInt &MaxValue, unsigned BitWidth) {
KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt, bool NUW,
bool NSW) {
- KnownBits Known;
+ KnownBits Known(LHS.getBitWidth());
bool ShiftedOutZero, ShiftedOutOne;
Known.Zero = LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero);
Known.Zero.setLowBits(ShiftAmt);
>From a8f161def7554c3d7ba2cff26982464d4bc741a5 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 16:51:39 +0300
Subject: [PATCH 09/17] refactor KnownBits::shl. Address review comments
---
llvm/lib/Support/KnownBits.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 5df6123a9b59b..15483f00c5b21 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -406,13 +406,13 @@ static unsigned getMaxShiftAmount(const APInt &MaxValue, unsigned BitWidth) {
KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt, bool NUW,
bool NSW) {
- KnownBits Known(LHS.getBitWidth());
bool ShiftedOutZero, ShiftedOutOne;
- Known.Zero = LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero);
+ KnownBits Known(LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero),
+ LHS.One.ushl_ov(ShiftAmt, ShiftedOutOne));
Known.Zero.setLowBits(ShiftAmt);
- Known.One = LHS.One.ushl_ov(ShiftAmt, ShiftedOutOne);
- // All cases returning poison have been handled by MaxShiftAmount already.
+ // This part assumes a valid shift amount and does not check for
+ // cases that would result in poison.
if (NSW) {
if (NUW && ShiftAmt != 0)
// NUW means we can assume anything shifted out was a zero.
>From 4069ae9ff0d4d66f48b56f398acab41cc28a06a3 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 17:35:07 +0300
Subject: [PATCH 10/17] simplify KnownBits add self add path by reusing new
overloaded KnownBits::shl
---
llvm/include/llvm/Support/KnownBits.h | 3 +--
llvm/lib/Support/KnownBits.cpp | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index 131908d205ddf..4041e82c04f97 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -368,8 +368,7 @@ struct KnownBits {
// Shift amount bitwidth is independent of src bitwidth (and we're
// just shifting by one so don't have any bounds issues).
assert(LHS == RHS && "Expected matching knownbits");
- KnownBits Amt = KnownBits::makeConstant(APInt(8, 1));
- return KnownBits::shl(LHS, Amt, NUW, NSW, /*ShAmtNonZero=*/true);
+ return KnownBits::shl(LHS, 1, NUW, NSW);
}
return computeForAddSub(/*Add=*/true, NSW, NUW, LHS, RHS);
}
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 15483f00c5b21..5e283758cade3 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -1213,9 +1213,8 @@ KnownBits KnownBits::udiv(const KnownBits &LHS, const KnownBits &RHS,
return Known;
}
- if (RHS.isConstant() && RHS.getConstant().isPowerOf2()) {
+ if (RHS.isConstant() && RHS.getConstant().isPowerOf2())
return lshr(LHS, RHS.getConstant().logBase2());
- }
// We can figure out the minimum number of upper zero bits by doing
// MaxNumerator / MinDenominator. If the Numerator gets smaller or Denominator
>From ad7223a3b843cc3c12da7fdeff307eb20cb0b78e Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 17:40:50 +0300
Subject: [PATCH 11/17] add more usages for new overloaded shift ops
---
.../Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 28cfa55b968dc..d25e9e3a8c7da 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -787,8 +787,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
if (SimplifyDemandedBits(I, 0, DemandedMaskIn, Known, Q, Depth + 1))
return I;
- Known = KnownBits::shl(Known,
- KnownBits::makeConstant(APInt(BitWidth, ShiftAmt)),
+ Known = KnownBits::shl(Known, ShiftAmt,
/* NUW */ IOp->hasNoUnsignedWrap(),
/* NSW */ IOp->hasNoSignedWrap());
} else {
@@ -931,9 +930,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
return InsertNewInstWith(LShr, I->getIterator());
}
- Known = KnownBits::ashr(
- Known, KnownBits::makeConstant(APInt(BitWidth, ShiftAmt)),
- ShiftAmt != 0, I->isExact());
+ Known = KnownBits::ashr(Known, ShiftAmt, ShiftAmt != 0, I->isExact());
} else {
llvm::computeKnownBits(I, Known, Q, Depth);
}
>From 56fda86c855ca111f87d82ea42ca065c6472b10f Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 17:46:23 +0300
Subject: [PATCH 12/17] fix
---
llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index d25e9e3a8c7da..7be7c2f12e355 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -930,7 +930,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
return InsertNewInstWith(LShr, I->getIterator());
}
- Known = KnownBits::ashr(Known, ShiftAmt, ShiftAmt != 0, I->isExact());
+ Known = KnownBits::ashr(Known, ShiftAmt);
} else {
llvm::computeKnownBits(I, Known, Q, Depth);
}
>From c6e05d3ae9194ad660019e52d83df5e608cef54e Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 21:01:52 +0300
Subject: [PATCH 13/17] use fallback to general version for overloaded
---
llvm/lib/Support/KnownBits.cpp | 50 +++++++++++++++++++---------------
1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 5e283758cade3..5748dfb21e7c0 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -404,31 +404,37 @@ static unsigned getMaxShiftAmount(const APInt &MaxValue, unsigned BitWidth) {
return MaxValue.getLimitedValue(BitWidth - 1);
}
-KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt, bool NUW,
- bool NSW) {
- bool ShiftedOutZero, ShiftedOutOne;
- KnownBits Known(LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero),
- LHS.One.ushl_ov(ShiftAmt, ShiftedOutOne));
- Known.Zero.setLowBits(ShiftAmt);
-
- // This part assumes a valid shift amount and does not check for
- // cases that would result in poison.
- if (NSW) {
- if (NUW && ShiftAmt != 0)
- // NUW means we can assume anything shifted out was a zero.
- ShiftedOutZero = true;
-
- if (ShiftedOutZero)
- Known.makeNonNegative();
- else if (ShiftedOutOne)
- Known.makeNegative();
- }
- return Known;
+KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt,
+ bool NUW, bool NSW) {
+ // TODO: This is simple fallback to generic RHS-based shl.
+ // Add a specialized constant-shift implementation with identical semantics.
+ KnownBits RHS = KnownBits::makeConstant(APInt(LHS.getBitWidth(), ShiftAmt));
+ return shl(LHS, RHS, NUW, NSW);
}
KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
bool NSW, bool ShAmtNonZero) {
unsigned BitWidth = LHS.getBitWidth();
+ auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) {
+ KnownBits Known;
+ bool ShiftedOutZero, ShiftedOutOne;
+ Known.Zero = LHS.Zero.ushl_ov(ShiftAmt, ShiftedOutZero);
+ Known.Zero.setLowBits(ShiftAmt);
+ Known.One = LHS.One.ushl_ov(ShiftAmt, ShiftedOutOne);
+
+ // All cases returning poison have been handled by MaxShiftAmount already.
+ if (NSW) {
+ if (NUW && ShiftAmt != 0)
+ // NUW means we can assume anything shifted out was a zero.
+ ShiftedOutZero = true;
+
+ if (ShiftedOutZero)
+ Known.makeNonNegative();
+ else if (ShiftedOutOne)
+ Known.makeNegative();
+ }
+ return Known;
+ };
// Fast path for a common case when LHS is completely unknown.
KnownBits Known(BitWidth);
@@ -454,7 +460,7 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
MaxShiftAmount,
std::max(LHS.countMaxLeadingZeros(), LHS.countMaxLeadingOnes()) - 1);
- // Fast path for common case where the shift amount is unknown.
+ // Fast path for common case where the shift amount is unknown.
if (MinShiftAmount == 0 && MaxShiftAmount == BitWidth - 1 &&
isPowerOf2_32(BitWidth)) {
Known.Zero.setLowBits(LHS.countMinTrailingZeros());
@@ -479,7 +485,7 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
if ((ShiftAmtZeroMask & ShiftAmt) != 0 ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
- Known = Known.intersectWith(shl(LHS, ShiftAmt, NUW, NSW));
+ Known = Known.intersectWith(ShiftByConst(LHS, ShiftAmt));
if (Known.isUnknown())
break;
}
>From 1a099f1280bb6526cf5e8943f04bdf364718b55d Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 21:06:14 +0300
Subject: [PATCH 14/17] format fix
---
llvm/lib/Support/KnownBits.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 5748dfb21e7c0..f4eb5fb946475 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -460,7 +460,7 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW,
MaxShiftAmount,
std::max(LHS.countMaxLeadingZeros(), LHS.countMaxLeadingOnes()) - 1);
- // Fast path for common case where the shift amount is unknown.
+ // Fast path for common case where the shift amount is unknown.
if (MinShiftAmount == 0 && MaxShiftAmount == BitWidth - 1 &&
isPowerOf2_32(BitWidth)) {
Known.Zero.setLowBits(LHS.countMinTrailingZeros());
>From a1897b0f9bed0b2e2b1bd4a4d71274e9c9efd414 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 21:06:54 +0300
Subject: [PATCH 15/17] format fix
---
llvm/lib/Support/KnownBits.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index f4eb5fb946475..8c58ef1db8af3 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -404,8 +404,8 @@ static unsigned getMaxShiftAmount(const APInt &MaxValue, unsigned BitWidth) {
return MaxValue.getLimitedValue(BitWidth - 1);
}
-KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt,
- bool NUW, bool NSW) {
+KnownBits KnownBits::shl(const KnownBits &LHS, unsigned ShiftAmt, bool NUW,
+ bool NSW) {
// TODO: This is simple fallback to generic RHS-based shl.
// Add a specialized constant-shift implementation with identical semantics.
KnownBits RHS = KnownBits::makeConstant(APInt(LHS.getBitWidth(), ShiftAmt));
>From 083641d56fd2c12450fad7e6d57f952145e34787 Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 21:22:33 +0300
Subject: [PATCH 16/17] do the same for KnownBits::ashr
---
llvm/include/llvm/Support/KnownBits.h | 5 +++--
llvm/lib/Support/KnownBits.cpp | 11 ++++++-----
.../InstCombine/InstCombineSimplifyDemanded.cpp | 2 +-
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h
index 4041e82c04f97..b31ae60ff5800 100644
--- a/llvm/include/llvm/Support/KnownBits.h
+++ b/llvm/include/llvm/Support/KnownBits.h
@@ -474,8 +474,9 @@ struct KnownBits {
bool ShAmtNonZero = false, bool Exact = false);
/// Compute known bits for ashr(LHS, ShiftAmt).
- /// This is shift by constant variant of ashr(LHS, RHS).
- LLVM_ABI static KnownBits ashr(const KnownBits &LHS, unsigned ShiftAmt);
+ /// This is shift by constant variant of ashr(LHS, ShiftAmt).
+ LLVM_ABI static KnownBits ashr(const KnownBits &LHS, unsigned ShiftAmt,
+ bool ShAmtNonZero = false, bool Exact = false);
/// Compute known bits for ashr(LHS, RHS).
/// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 8c58ef1db8af3..b71e24a0eaec7 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -553,11 +553,12 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS,
return Known;
}
-KnownBits KnownBits::ashr(const KnownBits &LHS, unsigned ShiftAmt) {
- KnownBits Known = LHS;
- Known.Zero.ashrInPlace(ShiftAmt);
- Known.One.ashrInPlace(ShiftAmt);
- return Known;
+KnownBits KnownBits::ashr(const KnownBits &LHS, unsigned ShiftAmt,
+ bool ShAmtNonZero, bool Exact) {
+ // TODO: This is simple fallback to generic RHS-based ashr.
+ // Add a specialized constant-shift implementation with identical semantics.
+ KnownBits RHS = KnownBits::makeConstant(APInt(LHS.getBitWidth(), ShiftAmt));
+ return ashr(LHS, RHS, ShAmtNonZero, Exact);
}
KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 7be7c2f12e355..d25e9e3a8c7da 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -930,7 +930,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
return InsertNewInstWith(LShr, I->getIterator());
}
- Known = KnownBits::ashr(Known, ShiftAmt);
+ Known = KnownBits::ashr(Known, ShiftAmt, ShiftAmt != 0, I->isExact());
} else {
llvm::computeKnownBits(I, Known, Q, Depth);
}
>From 74e50ef4c55fe80ad830ee97b028500e5ed7031c Mon Sep 17 00:00:00 2001
From: MaxGraey <maxgraey at gmail.com>
Date: Thu, 2 Apr 2026 21:50:15 +0300
Subject: [PATCH 17/17] fix ashr
---
llvm/lib/Support/KnownBits.cpp | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index b71e24a0eaec7..53fdd2435825e 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -564,6 +564,12 @@ KnownBits KnownBits::ashr(const KnownBits &LHS, unsigned ShiftAmt,
KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS,
bool ShAmtNonZero, bool Exact) {
unsigned BitWidth = LHS.getBitWidth();
+ auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) {
+ KnownBits Known = LHS;
+ Known.Zero.ashrInPlace(ShiftAmt);
+ Known.One.ashrInPlace(ShiftAmt);
+ return Known;
+ };
// Fast path for a common case when LHS is completely unknown.
KnownBits Known(BitWidth);
@@ -603,7 +609,7 @@ KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS,
if ((ShiftAmtZeroMask & ShiftAmt) != 0 ||
(ShiftAmtOneMask | ShiftAmt) != ShiftAmt)
continue;
- Known = Known.intersectWith(ashr(LHS, ShiftAmt));
+ Known = Known.intersectWith(ShiftByConst(LHS, ShiftAmt));
if (Known.isUnknown())
break;
}
More information about the llvm-commits
mailing list