[llvm] [DemandedBits] Support non-constant shift amounts for funnel shifts (PR #180569)
Panagiotis Karouzakis via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 7 18:59:28 PST 2026
https://github.com/karouzakisp updated https://github.com/llvm/llvm-project/pull/180569
>From e7a3c3da10dfe2141807a36067dde30b446c5e6a Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Sat, 27 Dec 2025 14:11:18 +0200
Subject: [PATCH 01/11] in progress fshr
---
llvm/lib/Analysis/DemandedBits.cpp | 42 ++++
llvm/test/Analysis/DemandedBits/fshr-fshl.ll | 201 +++++++++++++++++++
2 files changed, 243 insertions(+)
create mode 100644 llvm/test/Analysis/DemandedBits/fshr-fshl.ll
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index e0881751aef7e..f3de058299292 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -153,6 +153,48 @@ void DemandedBits::determineLiveOperandBits(
AB = AOut.lshr(ShiftAmt);
else if (OperandNo == 1)
AB = AOut.shl(BitWidth - ShiftAmt);
+ } else {
+ ComputeKnownBits(BitWidth, UserI->getOperand(2), nullptr);
+ if (!Known.getMaxValue().ult(BitWidth)) {
+ AB = APInt::getAllOnes(BitWidth);
+ return;
+ }
+ uint64_t Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
+ uint64_t Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
+ bool IsFShl = II->getIntrinsicID() == Intrinsic::fshl;
+ bool ShiftLeft;
+ uint64_t SMin = Min, SMax = Max;
+ // fshl(a, b, k ) is defined by concatenating a . b
+ // then doing a left shift by k and then extracting the upper bits.
+ // For BW = 4, k = 2 we have
+ // a4 a3 a2 a1 b4 b3 b2 b1, shift by k = 2 we get
+ // a2 a1 b4 b3.
+ // fshl(a,b,k) = (a << k) | (b >> (BW - k))
+ //
+ // Suppose AOut == 0b0000 0001
+ // [min, max] = [1, 3]
+ // iteration 1 shift by 1 mask is 0b0000 0011
+ // iteration 2 shift by 2 mask is 0b0000 1111
+ // iteration 3, shiftAmnt = 4 > max - min, we stop.
+ //
+ // fshr is defined in a similar way from fshl.
+ // a16 a15 .. a2 a1 b16 b15 ... b2 b1
+ //
+ // doing a right shift by (bw - k) and then extracting the lower bits.
+ // a4 a3 a2 a1 b4 b3 b2 b1, shift right by k = 2 we get
+ // a4 a3 a2 a1 b4 b3, then exracting the lower bits
+ // a2 a1 b4 b3
+ // fshr(a,b,k) = (a >> k) | (b << (BW - k))
+ //
+ if (OperandNo == 0) {
+ // We shift left for a only for fshr
+ ShiftLeft = !IsFShl;
+ } else {
+ SMin = BitWidth - Max;
+ SMax = BitWidth - Min;
+ ShiftLeft = IsFShl;
+ }
+ GetShiftedRange(SMin, SMax, ShiftLeft);
}
break;
}
diff --git a/llvm/test/Analysis/DemandedBits/fshr-fshl.ll b/llvm/test/Analysis/DemandedBits/fshr-fshl.ll
new file mode 100644
index 0000000000000..a8c9aba4d7bab
--- /dev/null
+++ b/llvm/test/Analysis/DemandedBits/fshr-fshl.ll
@@ -0,0 +1,201 @@
+; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
+declare i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+declare i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+
+
+define i8 @test_lshr_const_amount_4(i32 %a) {
+; CHECK-LABEL: 'test_lshr_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xff0 for %a in %lshr = lshr i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xffffffff for 4 in %lshr = lshr i32 %a, 4
+;
+ %lshr = lshr i32 %a, 4
+ %lshr.t = trunc i32 %lshr to i8
+ ret i8 %lshr.t
+}
+
+define i8 @test_lshr_const_amount_5(i32 %a) {
+; CHECK-LABEL: 'test_lshr_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 5
+; CHECK-DAG: DemandedBits: 0x1fe0 for %a in %lshr = lshr i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %lshr = lshr i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
+;
+ %lshr = lshr i32 %a, 5
+ %lshr.t = trunc i32 %lshr to i8
+ ret i8 %lshr.t
+}
+define i8 @test_lshr_const_amount_8(i32 %a) {
+; CHECK-LABEL: 'test_lshr_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff00 for %a in %lshr = lshr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %lshr = lshr i32 %a, 8
+;
+ %lshr = lshr i32 %a, 8
+ %lshr.t = trunc i32 %lshr to i8
+ ret i8 %lshr.t
+}
+
+define i8 @test_lshr_const_amount_9(i32 %a) {
+; CHECK-LABEL: 'test_lshr_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 9
+; CHECK-DAG: DemandedBits: 0x1fe00 for %a in %lshr = lshr i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xffffffff for 9 in %lshr = lshr i32 %a, 9
+;
+ %lshr = lshr i32 %a, 9
+ %lshr.t = trunc i32 %lshr to i8
+ ret i8 %lshr.t
+}
+
+define i8 @test_lshr(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr'
+; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
+;
+ %lshr = lshr i32 %a, %b
+ %lshr.t = trunc i32 %lshr to i8
+ ret i8 %lshr.t
+}
+
+define i8 @test_lshr_range_1(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_1'
+; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr in %shl.t = trunc i32 %lshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, %b2
+; CHECK-DAG: DemandedBits: 0x7ff for %a in %lshr = lshr i32 %a, %b2
+; CHECK-DAG: DemandedBits: 0xffffffff for %b2 in %lshr = lshr i32 %a, %b2
+; CHECK-DAG: DemandedBits: 0xffffffff for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0xffffffff for 3 in %b2 = and i32 %b, 3
+;
+ %b2 = and i32 %b, 3
+ %lshr = lshr i32 %a, %b2
+ %shl.t = trunc i32 %lshr to i8
+ ret i8 %shl.t
+}
+
+define i32 @test_lshr_range_2(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_2'
+; CHECK-DAG: DemandedBits: 0xffffffff for %lshr = lshr i32 %a, %b2
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %lshr = lshr i32 %a, %b2
+; CHECK-DAG: DemandedBits: 0xffffffff for %b2 in %lshr = lshr i32 %a, %b2
+; CHECK-DAG: DemandedBits: 0xffffffff for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0xffffffff for 3 in %b2 = and i32 %b, 3
+;
+ %b2 = and i32 %b, 3
+ %lshr = lshr i32 %a, %b2
+ ret i32 %lshr
+}
+
+define i32 @test_lshr_range_3(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_3'
+; CHECK-DAG: DemandedBits: 0xffff for %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %shl = shl i32 %lshr, 16
+; CHECK-DAG: DemandedBits: 0xffff for %lshr in %shl = shl i32 %lshr, 16
+; CHECK-DAG: DemandedBits: 0xffffffff for 16 in %shl = shl i32 %lshr, 16
+;
+ %lshr = lshr i32 %a, %b
+ %shl = shl i32 %lshr, 16
+ ret i32 %shl
+}
+
+define i32 @test_lshr_range_4(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_4'
+; CHECK-DAG: DemandedBits: 0xffffff00 for %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffff00 for %a in %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %lshr, 8
+; CHECK-DAG: DemandedBits: 0xffffff00 for %lshr in %shr = ashr i32 %lshr, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %lshr, 8
+ %lshr = lshr i32 %a, %b
+ %shr = ashr i32 %lshr, 8
+ ret i32 %shr
+}
+
+define i32 @test_lshr_range_5(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_5'
+; CHECK-DAG: DemandedBits: 0xff for %1 = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %2 = and i32 %1, 255
+; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = and i32 %1, 255
+; CHECK-DAG: DemandedBits: 0xffffffff for 255 in %2 = and i32 %1, 255
+;
+ %1 = lshr i32 %a, %b
+ %2 = and i32 %1, 255
+ ret i32 %2
+}
+
+define i32 @test_lshr_range_6(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_6'
+; CHECK-DAG: DemandedBits: 0xffff0000 for %lshr.1 = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffff0000 for %a in %lshr.1 = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr.1 = lshr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %lshr.2 = lshr i32 %lshr.1, 16
+; CHECK-DAG: DemandedBits: 0xffff0000 for %lshr.1 in %lshr.2 = lshr i32 %lshr.1, 16
+; CHECK-DAG: DemandedBits: 0xffffffff for 16 in %lshr.2 = lshr i32 %lshr.1, 16
+;
+ %lshr.1 = lshr i32 %a, %b
+ %lshr.2 = lshr i32 %lshr.1, 16
+ ret i32 %lshr.2
+}
+
+
+define i8 @test_lshr_var_amount(i32 %a, i32 %b){
+; CHECK-LABEL: 'test_lshr_var_amount'
+; CHECK-DAG: DemandedBits: 0xff for %4 = lshr i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = lshr i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = lshr i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xff for %5 = trunc i32 %4 to i8
+; CHECK-DAG: DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
+; CHECK-DAG: DemandedBits: 0xffffffff for %3 = zext i8 %2 to i32
+; CHECK-DAG: DemandedBits: 0xff for %2 in %3 = zext i8 %2 to i32
+; CHECK-DAG: DemandedBits: 0xffffffff for %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for %2 = trunc i32 %1 to i8
+; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = trunc i32 %1 to i8
+;
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = lshr i32 %1, %3
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
+
+define i8 @test_lshr_var_amount_exact(i32 %a, i32 %b){
+ ; CHECK-LABEL 'test_lshr_var_amount_nsw'
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %1 = add nsw i32 %a, %b
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = add nsw i32 %a, %b
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = add nsw i32 %a, %b
+ ; CHECK-DAG: DemandedBits: 0xff for %2 = trunc i32 %1 to i8
+ ; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = trunc i32 %1 to i8
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %3 = zext i8 %2 to i32
+ ; CHECK-DAG: DemandedBits: 0xff for %2 in %3 = zext i8 %2 to i32
+ ; CHECK-DAG: DemandedBits: 0xff for %4 = lshr exact i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = lshr exact i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = lshr exact i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xff for %5 = trunc i32 %4 to i8
+ ; CHECK-DAG: DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
+ ;
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = lshr exact i32 %1, %3
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
>From 9684d973e74b3ddda93cd921fee0b433c1032ace Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Sun, 8 Feb 2026 18:02:52 +0200
Subject: [PATCH 02/11] funnel shift, needs checks
---
llvm/lib/Analysis/DemandedBits.cpp | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index f3de058299292..3b7365f9a3086 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -162,6 +162,7 @@ void DemandedBits::determineLiveOperandBits(
uint64_t Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
uint64_t Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
bool IsFShl = II->getIntrinsicID() == Intrinsic::fshl;
+ bool IsFShr = II->getIntrinsicID() == Intrinsic::fshr;
bool ShiftLeft;
uint64_t SMin = Min, SMax = Max;
// fshl(a, b, k ) is defined by concatenating a . b
@@ -185,14 +186,20 @@ void DemandedBits::determineLiveOperandBits(
// a4 a3 a2 a1 b4 b3, then exracting the lower bits
// a2 a1 b4 b3
// fshr(a,b,k) = (a >> k) | (b << (BW - k))
- //
- if (OperandNo == 0) {
- // We shift left for a only for fshr
- ShiftLeft = !IsFShl;
- } else {
+
+ // Normalize to funnel shift left.
+ if (IsFShr) {
SMin = BitWidth - Max;
SMax = BitWidth - Min;
- ShiftLeft = IsFShl;
+ }
+ if (OperandNo == 0) {
+ ShiftLeft = false;
+ } else if (OperandNo == 1) {
+ ShiftLeft = true;
+ auto NewSMin = BitWidth - SMax;
+ auto NewSMax = BitWidth - SMin;
+ SMin = NewSMin;
+ SMax = NewSMax;
}
GetShiftedRange(SMin, SMax, ShiftLeft);
}
>From 60c43e15dcff90c5f70fdf28ed6c6a9ea0827735 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Mon, 9 Feb 2026 18:32:38 +0200
Subject: [PATCH 03/11] [DemandedBits] Support non constant shift amounts for
fshl/fshr
---
llvm/lib/Analysis/DemandedBits.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 3b7365f9a3086..0f56032b4cd68 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -161,7 +161,6 @@ void DemandedBits::determineLiveOperandBits(
}
uint64_t Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
uint64_t Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
- bool IsFShl = II->getIntrinsicID() == Intrinsic::fshl;
bool IsFShr = II->getIntrinsicID() == Intrinsic::fshr;
bool ShiftLeft;
uint64_t SMin = Min, SMax = Max;
>From 6db59f64aff2aa394cc78767b9f1f3b35ec51b12 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Mon, 9 Feb 2026 19:18:50 +0200
Subject: [PATCH 04/11] removed wrong tests
---
llvm/test/Analysis/DemandedBits/fshr-fshl.ll | 201 -------------------
1 file changed, 201 deletions(-)
delete mode 100644 llvm/test/Analysis/DemandedBits/fshr-fshl.ll
diff --git a/llvm/test/Analysis/DemandedBits/fshr-fshl.ll b/llvm/test/Analysis/DemandedBits/fshr-fshl.ll
deleted file mode 100644
index a8c9aba4d7bab..0000000000000
--- a/llvm/test/Analysis/DemandedBits/fshr-fshl.ll
+++ /dev/null
@@ -1,201 +0,0 @@
-; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
-declare i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
-declare i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
-
-
-define i8 @test_lshr_const_amount_4(i32 %a) {
-; CHECK-LABEL: 'test_lshr_const_amount_4'
-; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 4
-; CHECK-DAG: DemandedBits: 0xff0 for %a in %lshr = lshr i32 %a, 4
-; CHECK-DAG: DemandedBits: 0xffffffff for 4 in %lshr = lshr i32 %a, 4
-;
- %lshr = lshr i32 %a, 4
- %lshr.t = trunc i32 %lshr to i8
- ret i8 %lshr.t
-}
-
-define i8 @test_lshr_const_amount_5(i32 %a) {
-; CHECK-LABEL: 'test_lshr_const_amount_5'
-; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 5
-; CHECK-DAG: DemandedBits: 0x1fe0 for %a in %lshr = lshr i32 %a, 5
-; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %lshr = lshr i32 %a, 5
-; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
-;
- %lshr = lshr i32 %a, 5
- %lshr.t = trunc i32 %lshr to i8
- ret i8 %lshr.t
-}
-define i8 @test_lshr_const_amount_8(i32 %a) {
-; CHECK-LABEL: 'test_lshr_const_amount_8'
-; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 8
-; CHECK-DAG: DemandedBits: 0xff00 for %a in %lshr = lshr i32 %a, 8
-; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %lshr = lshr i32 %a, 8
-;
- %lshr = lshr i32 %a, 8
- %lshr.t = trunc i32 %lshr to i8
- ret i8 %lshr.t
-}
-
-define i8 @test_lshr_const_amount_9(i32 %a) {
-; CHECK-LABEL: 'test_lshr_const_amount_9'
-; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, 9
-; CHECK-DAG: DemandedBits: 0x1fe00 for %a in %lshr = lshr i32 %a, 9
-; CHECK-DAG: DemandedBits: 0xffffffff for 9 in %lshr = lshr i32 %a, 9
-;
- %lshr = lshr i32 %a, 9
- %lshr.t = trunc i32 %lshr to i8
- ret i8 %lshr.t
-}
-
-define i8 @test_lshr(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr'
-; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xff for %lshr.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr in %lshr.t = trunc i32 %lshr to i8
-;
- %lshr = lshr i32 %a, %b
- %lshr.t = trunc i32 %lshr to i8
- ret i8 %lshr.t
-}
-
-define i8 @test_lshr_range_1(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_1'
-; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr in %shl.t = trunc i32 %lshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %lshr = lshr i32 %a, %b2
-; CHECK-DAG: DemandedBits: 0x7ff for %a in %lshr = lshr i32 %a, %b2
-; CHECK-DAG: DemandedBits: 0xffffffff for %b2 in %lshr = lshr i32 %a, %b2
-; CHECK-DAG: DemandedBits: 0xffffffff for %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0xffffffff for 3 in %b2 = and i32 %b, 3
-;
- %b2 = and i32 %b, 3
- %lshr = lshr i32 %a, %b2
- %shl.t = trunc i32 %lshr to i8
- ret i8 %shl.t
-}
-
-define i32 @test_lshr_range_2(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_2'
-; CHECK-DAG: DemandedBits: 0xffffffff for %lshr = lshr i32 %a, %b2
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %lshr = lshr i32 %a, %b2
-; CHECK-DAG: DemandedBits: 0xffffffff for %b2 in %lshr = lshr i32 %a, %b2
-; CHECK-DAG: DemandedBits: 0xffffffff for %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0xffffffff for 3 in %b2 = and i32 %b, 3
-;
- %b2 = and i32 %b, 3
- %lshr = lshr i32 %a, %b2
- ret i32 %lshr
-}
-
-define i32 @test_lshr_range_3(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_3'
-; CHECK-DAG: DemandedBits: 0xffff for %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %shl = shl i32 %lshr, 16
-; CHECK-DAG: DemandedBits: 0xffff for %lshr in %shl = shl i32 %lshr, 16
-; CHECK-DAG: DemandedBits: 0xffffffff for 16 in %shl = shl i32 %lshr, 16
-;
- %lshr = lshr i32 %a, %b
- %shl = shl i32 %lshr, 16
- ret i32 %shl
-}
-
-define i32 @test_lshr_range_4(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_4'
-; CHECK-DAG: DemandedBits: 0xffffff00 for %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffff00 for %a in %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %lshr, 8
-; CHECK-DAG: DemandedBits: 0xffffff00 for %lshr in %shr = ashr i32 %lshr, 8
-; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %lshr, 8
- %lshr = lshr i32 %a, %b
- %shr = ashr i32 %lshr, 8
- ret i32 %shr
-}
-
-define i32 @test_lshr_range_5(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_5'
-; CHECK-DAG: DemandedBits: 0xff for %1 = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %2 = and i32 %1, 255
-; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = and i32 %1, 255
-; CHECK-DAG: DemandedBits: 0xffffffff for 255 in %2 = and i32 %1, 255
-;
- %1 = lshr i32 %a, %b
- %2 = and i32 %1, 255
- ret i32 %2
-}
-
-define i32 @test_lshr_range_6(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_6'
-; CHECK-DAG: DemandedBits: 0xffff0000 for %lshr.1 = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffff0000 for %a in %lshr.1 = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %b in %lshr.1 = lshr i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %lshr.2 = lshr i32 %lshr.1, 16
-; CHECK-DAG: DemandedBits: 0xffff0000 for %lshr.1 in %lshr.2 = lshr i32 %lshr.1, 16
-; CHECK-DAG: DemandedBits: 0xffffffff for 16 in %lshr.2 = lshr i32 %lshr.1, 16
-;
- %lshr.1 = lshr i32 %a, %b
- %lshr.2 = lshr i32 %lshr.1, 16
- ret i32 %lshr.2
-}
-
-
-define i8 @test_lshr_var_amount(i32 %a, i32 %b){
-; CHECK-LABEL: 'test_lshr_var_amount'
-; CHECK-DAG: DemandedBits: 0xff for %4 = lshr i32 %1, %3
-; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = lshr i32 %1, %3
-; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = lshr i32 %1, %3
-; CHECK-DAG: DemandedBits: 0xff for %5 = trunc i32 %4 to i8
-; CHECK-DAG: DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
-; CHECK-DAG: DemandedBits: 0xffffffff for %3 = zext i8 %2 to i32
-; CHECK-DAG: DemandedBits: 0xff for %2 in %3 = zext i8 %2 to i32
-; CHECK-DAG: DemandedBits: 0xffffffff for %1 = add nsw i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = add nsw i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = add nsw i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xff for %2 = trunc i32 %1 to i8
-; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = trunc i32 %1 to i8
-;
- %1 = add nsw i32 %a, %b
- %2 = trunc i32 %1 to i8
- %3 = zext i8 %2 to i32
- %4 = lshr i32 %1, %3
- %5 = trunc i32 %4 to i8
- ret i8 %5
-}
-
-define i8 @test_lshr_var_amount_exact(i32 %a, i32 %b){
- ; CHECK-LABEL 'test_lshr_var_amount_nsw'
- ; CHECK-DAG: DemandedBits: 0xffffffff for %1 = add nsw i32 %a, %b
- ; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = add nsw i32 %a, %b
- ; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = add nsw i32 %a, %b
- ; CHECK-DAG: DemandedBits: 0xff for %2 = trunc i32 %1 to i8
- ; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = trunc i32 %1 to i8
- ; CHECK-DAG: DemandedBits: 0xffffffff for %3 = zext i8 %2 to i32
- ; CHECK-DAG: DemandedBits: 0xff for %2 in %3 = zext i8 %2 to i32
- ; CHECK-DAG: DemandedBits: 0xff for %4 = lshr exact i32 %1, %3
- ; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = lshr exact i32 %1, %3
- ; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = lshr exact i32 %1, %3
- ; CHECK-DAG: DemandedBits: 0xff for %5 = trunc i32 %4 to i8
- ; CHECK-DAG: DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
- ;
- %1 = add nsw i32 %a, %b
- %2 = trunc i32 %1 to i8
- %3 = zext i8 %2 to i32
- %4 = lshr exact i32 %1, %3
- %5 = trunc i32 %4 to i8
- ret i8 %5
-}
>From 85b1e728e5a270c62ed03b5c6938118eca0fa381 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Mon, 9 Feb 2026 20:05:33 +0200
Subject: [PATCH 05/11] fixed non-initialized variable
---
llvm/lib/Analysis/DemandedBits.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 0f56032b4cd68..3d14d3b21ef74 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -162,7 +162,7 @@ void DemandedBits::determineLiveOperandBits(
uint64_t Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
uint64_t Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
bool IsFShr = II->getIntrinsicID() == Intrinsic::fshr;
- bool ShiftLeft;
+ bool ShiftLeft = false;
uint64_t SMin = Min, SMax = Max;
// fshl(a, b, k ) is defined by concatenating a . b
// then doing a left shift by k and then extracting the upper bits.
>From fa8d43ae1684e9a86847a2345d07712cc7be0850 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Mon, 9 Feb 2026 20:47:52 +0200
Subject: [PATCH 06/11] fixed wrong smin, smax calculations
---
llvm/lib/Analysis/DemandedBits.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 3d14d3b21ef74..3061f126a584e 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -188,15 +188,15 @@ void DemandedBits::determineLiveOperandBits(
// Normalize to funnel shift left.
if (IsFShr) {
- SMin = BitWidth - Max;
- SMax = BitWidth - Min;
+ SMin = BitWidth - Max - 1;
+ SMax = BitWidth - Min - 1;
}
if (OperandNo == 0) {
ShiftLeft = false;
} else if (OperandNo == 1) {
ShiftLeft = true;
- auto NewSMin = BitWidth - SMax;
- auto NewSMax = BitWidth - SMin;
+ auto NewSMin = BitWidth - SMax - 1;
+ auto NewSMax = BitWidth - SMin - 1;
SMin = NewSMin;
SMax = NewSMax;
}
>From 6836e0eec2121003d4d923855d91248eb93faa5f Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Mon, 9 Feb 2026 20:58:50 +0200
Subject: [PATCH 07/11] removed getLimitedValue, added getZExtValue
---
llvm/lib/Analysis/DemandedBits.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 3061f126a584e..09eca868f86c8 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -159,8 +159,8 @@ void DemandedBits::determineLiveOperandBits(
AB = APInt::getAllOnes(BitWidth);
return;
}
- uint64_t Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
- uint64_t Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
+ uint64_t Min = Known.getMinValue().getZExtValue();
+ uint64_t Max = Known.getMaxValue().getZExtValue();
bool IsFShr = II->getIntrinsicID() == Intrinsic::fshr;
bool ShiftLeft = false;
uint64_t SMin = Min, SMax = Max;
>From f60dcdfed44de37eb8b2a32da81dbc34a70bc5bb Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Sun, 15 Feb 2026 16:56:55 +0200
Subject: [PATCH 08/11] added extra cases and simplified logic
---
llvm/lib/Analysis/DemandedBits.cpp | 43 +++++++++++++++++++-----------
1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 09eca868f86c8..2282004c5ae2a 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -155,12 +155,13 @@ void DemandedBits::determineLiveOperandBits(
AB = AOut.shl(BitWidth - ShiftAmt);
} else {
ComputeKnownBits(BitWidth, UserI->getOperand(2), nullptr);
- if (!Known.getMaxValue().ult(BitWidth)) {
+ APInt APIntMax = Known.getMaxValue();
+ if (!APIntMax.ult(BitWidth)) {
AB = APInt::getAllOnes(BitWidth);
return;
}
uint64_t Min = Known.getMinValue().getZExtValue();
- uint64_t Max = Known.getMaxValue().getZExtValue();
+ uint64_t Max = APIntMax.getZExtValue();
bool IsFShr = II->getIntrinsicID() == Intrinsic::fshr;
bool ShiftLeft = false;
uint64_t SMin = Min, SMax = Max;
@@ -186,21 +187,33 @@ void DemandedBits::determineLiveOperandBits(
// a2 a1 b4 b3
// fshr(a,b,k) = (a >> k) | (b << (BW - k))
- // Normalize to funnel shift left.
- if (IsFShr) {
- SMin = BitWidth - Max - 1;
- SMax = BitWidth - Min - 1;
+ // Skip poison shifts.
+ if (((IsFShr && OperandNo == 0) || (!IsFShr && OperandNo == 1)) &&
+ Min == 0) {
+ AB = APInt::getAllOnes(BitWidth);
+ return;
}
- if (OperandNo == 0) {
- ShiftLeft = false;
- } else if (OperandNo == 1) {
- ShiftLeft = true;
- auto NewSMin = BitWidth - SMax - 1;
- auto NewSMax = BitWidth - SMin - 1;
- SMin = NewSMin;
- SMax = NewSMax;
+
+ // IsFSHR and Op1 == ShiftLeft: true
+ // IsFSHR and Op0 == ShiftLeft: false
+ // !IsFSHR and Op0 == ShiftLeft: false
+ // !IsFShr and Op1 == ShiftLeft: true;
+ ShiftLeft = OperandNo == 1;
+
+ // ComplementShit
+ // ISFSHR and Op0 == True.
+ // ISFSHR and Op1 == False.
+ // !ISFSHR and Op0 == False.
+ // !ISFSHR and Op1 == true;
+ bool ComplementShift = IsFShr ^ (OperandNo == 1);
+
+ if (ComplementShift) {
+ SMin = BitWidth - Max;
+ SMax = BitWidth - Min;
+ Min = SMin;
+ Max = SMax;
}
- GetShiftedRange(SMin, SMax, ShiftLeft);
+ GetShiftedRange(Min, Max, ShiftLeft);
}
break;
}
>From 94b3e423e3a5338580eac2540a92513968c2bb8e Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Sat, 7 Mar 2026 07:23:00 +0200
Subject: [PATCH 09/11] added missing tests on fshl and fshr
---
llvm/test/Analysis/DemandedBits/fshl.ll | 206 ++++++++++++++++++++++++
llvm/test/Analysis/DemandedBits/fshr.ll | 203 +++++++++++++++++++++++
2 files changed, 409 insertions(+)
create mode 100644 llvm/test/Analysis/DemandedBits/fshl.ll
create mode 100644 llvm/test/Analysis/DemandedBits/fshr.ll
diff --git a/llvm/test/Analysis/DemandedBits/fshl.ll b/llvm/test/Analysis/DemandedBits/fshl.ll
new file mode 100644
index 0000000000000..6daa9b8b3be42
--- /dev/null
+++ b/llvm/test/Analysis/DemandedBits/fshl.ll
@@ -0,0 +1,206 @@
+; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
+
+declare i32 @llvm.fshl.i32 (i32 %a, i32 %b, i32 %c)
+
+
+define i8 @test_fshl_const_amount_4(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshl_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl in %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0xf for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0xf0000000 for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0x1f for 4 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 4)
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 4)
+ %tr = trunc i32 %fshl to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshl_const_amount_5(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshl_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl in %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0x7 for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0xf8000000 for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0x1f for 5 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 5)
+ %tr = trunc i32 %fshl to i8
+ ret i8 %tr
+
+
+}
+
+define i8 @test_fshl_const_amount_8(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshl_const_amount_8'
+;
+; CHECK-DAG: DemandedBits: 0xff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0x0 for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xff000000 for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0x1f for 8 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl in %tr = trunc i32 %fshl to i8
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 8)
+ %tr = trunc i32 %fshl to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshl_const_amount_9(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshl_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl in %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 9)
+; CHECK-DAG: DemandedBits: 0x0 for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 9)
+; CHECK-DAG: DemandedBits: 0x7f800000 for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 9)
+; CHECK-DAG: DemandedBits: 0x1f for 9 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 9)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 9)
+
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 9)
+ %tr = trunc i32 %fshl to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshl(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshl'
+;
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl in %tr = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+ %tr = trunc i32 %fshl to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshl_range_1(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshl_range_1'
+; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshl in %shl.t = trunc i32 %fshl to i8
+; CHECK-DAG: DemandedBits: 0x1f for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x1f for 3 in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0xff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xff for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+;
+ %b2 = and i32 %b, 3
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+ %shl.t = trunc i32 %fshl to i8
+ ret i8 %shl.t
+}
+
+define i32 @test_fshl_range_2(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshl_range_2'
+; CHECK-DAG: DemandedBits: 0xffffffff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x1f for 3 in %b2 = and i32 %b, 3
+;
+ %b2 = and i32 %b, 3
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %b2)
+ ret i32 %fshl
+}
+
+define i32 @test_fshl_range_3(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshl_range_3'
+; CHECK-DAG: DemandedBits: 0xffff for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %shl = shl i32 %fshl, 16
+; CHECK-DAG: DemandedBits: 0xffff for %fshl in %shl = shl i32 %fshl, 16
+; CHECK-DAG: DemandedBits: 0xffffffff for 16 in %shl = shl i32 %fshl, 16
+;
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+ %shl = shl i32 %fshl, 16
+ ret i32 %shl
+}
+
+define i32 @test_fshl_range_4(i32 %a, i32 %b, i32 %c) {
+; CHECK-DAG: DemandedBits: 0xffffff00 for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %fshl, 8
+; CHECK-DAG: DemandedBits: 0xffffff00 for %fshl in %shr = ashr i32 %fshl, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %fshl, 8
+
+
+; CHECK-LABEL: 'test_fshl_range_4'
+ %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+ %shr = ashr i32 %fshl, 8
+ ret i32 %shr
+}
+
+define i32 @test_fshl_range_5(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshl_range_5'
+; CHECK-DAG: DemandedBits: 0xff for %1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %2 = and i32 %1, 255
+; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = and i32 %1, 255
+; CHECK-DAG: DemandedBits: 0xffffffff for 255 in %2 = and i32 %1, 255
+;
+ %1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+ %2 = and i32 %1, 255
+ ret i32 %2
+}
+
+define i32 @test_fshl_range_6(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshl_range_6'
+; CHECK-DAG: DemandedBits: 0xffff for %fshl.1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshl.1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl.1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshl.1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl.1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %fshl.2 = call i32 @llvm.fshl.i32(i32 %fshl.1, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0xffff for %fshl.1 in %fshl.2 = call i32 @llvm.fshl.i32(i32 %fshl.1, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0xffff0000 for %b in %fshl.2 = call i32 @llvm.fshl.i32(i32 %fshl.1, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0x1f for 16 in %fshl.2 = call i32 @llvm.fshl.i32(i32 %fshl.1, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl.2 = call i32 @llvm.fshl.i32(i32 %fshl.1, i32 %b, i32 16)
+;
+ %fshl.1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
+ %fshl.2 = call i32 @llvm.fshl.i32(i32 %fshl.1, i32 %b, i32 16)
+
+ ret i32 %fshl.2
+}
+
+define i8 @test_fshl_var_amount(i32 %a, i32 %b, i32 %c){
+; CHECK-LABEL: 'test_fshl_var_amount'
+; CHECK-DAG: DemandedBits: 0xff for %5 = trunc i32 %4 to i8
+; CHECK-DAG: DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
+; CHECK-DAG: DemandedBits: 0xff for %4 = call i32 @llvm.fshl.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %4 = call i32 @llvm.fshl.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0xffffffff for %c in %4 = call i32 @llvm.fshl.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0x1f for %3 in %4 = call i32 @llvm.fshl.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %4 = call i32 @llvm.fshl.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0x1f for %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0x1f for %a in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0x1f for %b in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0x1f for %3 = zext i8 %2 to i32
+; CHECK-DAG: DemandedBits: 0x1f for %2 in %3 = zext i8 %2 to i32
+; CHECK-DAG: DemandedBits: 0x1f for %2 = trunc i32 %1 to i8
+; CHECK-DAG: DemandedBits: 0x1f for %1 in %2 = trunc i32 %1 to i8
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = call i32 @llvm.fshl.i32(i32 %a, i32 %c, i32 %3)
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
diff --git a/llvm/test/Analysis/DemandedBits/fshr.ll b/llvm/test/Analysis/DemandedBits/fshr.ll
new file mode 100644
index 0000000000000..9a2b4509f0bd8
--- /dev/null
+++ b/llvm/test/Analysis/DemandedBits/fshr.ll
@@ -0,0 +1,203 @@
+; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
+
+declare i32 @llvm.fshl.i32 (i32 %a, i32 %b, i32 %c)
+
+declare i32 @llvm.fshr.i32 (i32 %a, i32 %b, i32 %c)
+
+
+define i8 @test_fshr_const_amount_4(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshr_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0x0 for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0xff0 for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0x1f for 4 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 4)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 4)
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 4)
+ %tr = trunc i32 %fshr to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshr_const_amount_5(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshr_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0x0 for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0x1fe0 for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0x1f for 5 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 5)
+ %tr = trunc i32 %fshr to i8
+ ret i8 %tr
+
+
+}
+
+define i8 @test_fshr_const_amount_8(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshr_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0x0 for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xff00 for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0x1f for 8 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %tr = trunc i32 %fshr to i8
+;
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+ %tr = trunc i32 %fshr to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshr_const_amount_9(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_fshr_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0x0 for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xff00 for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0x1f for 8 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+;
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 8)
+ %tr = trunc i32 %fshr to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshr(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshr'
+; CHECK-DAG: DemandedBits: 0xff for %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %tr = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+;
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+ %tr = trunc i32 %fshr to i8
+ ret i8 %tr
+}
+
+define i8 @test_fshr_range_1(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_1'
+; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %shl.t = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0x1f for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x1f for 3 in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x7ff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+;
+ %b2 = and i32 %b, 3
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+ %shl.t = trunc i32 %fshr to i8
+ ret i8 %shl.t
+}
+
+define i32 @test_lshr_range_2(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_lshr_range_2'
+; CHECK-DAG: DemandedBits: 0x1f for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x1f for 3 in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0xffffffff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+;
+ %b2 = and i32 %b, 3
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+ ret i32 %fshr
+}
+
+define i32 @test_fshr_range_3(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshr_range_3'
+; CHECK-DAG: DemandedBits: 0xffff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %shl = shl i32 %fshr, 16
+; CHECK-DAG: DemandedBits: 0xffff for %fshr in %shl = shl i32 %fshr, 16
+; CHECK-DAG: DemandedBits: 0xffffffff for 16 in %shl = shl i32 %fshr, 16
+;
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+ %shl = shl i32 %fshr, 16
+ ret i32 %shl
+}
+
+define i32 @test_fshr_range_4(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshr_range_4'
+; CHECK-DAG: DemandedBits: 0xffffff00 for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %fshr, 8
+; CHECK-DAG: DemandedBits: 0xffffff00 for %fshr in %shr = ashr i32 %fshr, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %fshr, 8
+
+ %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+ %shr = ashr i32 %fshr, 8
+ ret i32 %shr
+}
+
+define i32 @test_lshr_range_5(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_lshr_range_5'
+; CHECK-DAG: DemandedBits: 0xff for %1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0x1f for %c in %1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+; CHECK-DAG: DemandedBits: 0xffffffff for %2 = and i32 %1, 255
+; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = and i32 %1, 255
+; CHECK-DAG: DemandedBits: 0xffffffff for 255 in %2 = and i32 %1, 255
+;
+ %1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+ %2 = and i32 %1, 255
+ ret i32 %2
+}
+
+define i32 @test_fshr_range_6(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshr_range_6'
+; CHECK-DAG: DemandedBits: 0xffffffff for %fshr.2 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0xffff for %a in %fshr.2 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0xffff0000 for %b in %fshr.2 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0x1f for 16 in %fshr.2 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 16)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr.2 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 16)
+;
+ %fshr.1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %c)
+ %fshr.2 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 16)
+
+ ret i32 %fshr.2
+}
+
+define i8 @test_lshr_var_amount(i32 %a, i32 %b, i32 %c){
+; CHECK-LABEL: 'test_lshr_var_amount'
+; CHECK-DAG: DemandedBits: 0x1f for %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0x1f for %a in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0x1f for %b in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0x1f for %3 = zext i8 %2 to i32
+; CHECK-DAG: DemandedBits: 0x1f for %2 in %3 = zext i8 %2 to i32
+; CHECK-DAG: DemandedBits: 0x1f for %2 = trunc i32 %1 to i8
+; CHECK-DAG: DemandedBits: 0x1f for %1 in %2 = trunc i32 %1 to i8
+; CHECK-DAG: DemandedBits: 0xff for %5 = trunc i32 %4 to i8
+; CHECK-DAG: DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
+; CHECK-DAG: DemandedBits: 0xff for %4 = call i32 @llvm.fshr.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %4 = call i32 @llvm.fshr.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0xffffffff for %c in %4 = call i32 @llvm.fshr.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0x1f for %3 in %4 = call i32 @llvm.fshr.i32(i32 %a, i32 %c, i32 %3)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %4 = call i32 @llvm.fshr.i32(i32 %a, i32 %c, i32 %3)
+;
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = call i32 @llvm.fshr.i32(i32 %a, i32 %c, i32 %3)
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
>From ccd0b529c8fd74470cf8aa211d3cf6dbcefabfa9 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Sun, 8 Mar 2026 03:53:59 +0200
Subject: [PATCH 10/11] fixed test errors
---
llvm/test/Analysis/DemandedBits/fshl.ll | 9 +++++----
llvm/test/Analysis/DemandedBits/fshr.ll | 23 ++++++++++++-----------
2 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/llvm/test/Analysis/DemandedBits/fshl.ll b/llvm/test/Analysis/DemandedBits/fshl.ll
index 6daa9b8b3be42..34ee3ebafd478 100644
--- a/llvm/test/Analysis/DemandedBits/fshl.ll
+++ b/llvm/test/Analysis/DemandedBits/fshl.ll
@@ -129,16 +129,17 @@ define i32 @test_fshl_range_3(i32 %a, i32 %b, i32 %c) {
ret i32 %shl
}
+
+
define i32 @test_fshl_range_4(i32 %a, i32 %b, i32 %c) {
+; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %fshl, 8
+; CHECK-DAG: DemandedBits: 0xffffff00 for %fshl in %shr = ashr i32 %fshl, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %fshl, 8
; CHECK-DAG: DemandedBits: 0xffffff00 for %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
; CHECK-DAG: DemandedBits: 0xffffffff for %b in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
; CHECK-DAG: DemandedBits: 0x1f for %c in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
-; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %fshl, 8
-; CHECK-DAG: DemandedBits: 0xffffff00 for %fshl in %shr = ashr i32 %fshl, 8
-; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %fshl, 8
-
; CHECK-LABEL: 'test_fshl_range_4'
%fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
diff --git a/llvm/test/Analysis/DemandedBits/fshr.ll b/llvm/test/Analysis/DemandedBits/fshr.ll
index 9a2b4509f0bd8..ba311ee4082eb 100644
--- a/llvm/test/Analysis/DemandedBits/fshr.ll
+++ b/llvm/test/Analysis/DemandedBits/fshr.ll
@@ -81,17 +81,18 @@ define i8 @test_fshr(i32 %a, i32 %b, i32 %c) {
}
define i8 @test_fshr_range_1(i32 %a, i32 %b) {
-; CHECK-LABEL: 'test_lshr_range_1'
-; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %fshr to i8
-; CHECK-DAG: DemandedBits: 0xff for %fshr in %shl.t = trunc i32 %fshr to i8
-; CHECK-DAG: DemandedBits: 0x1f for %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0x1f for 3 in %b2 = and i32 %b, 3
-; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
-; CHECK-DAG: DemandedBits: 0x7ff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
-; CHECK-DAG: DemandedBits: 0x1f for %b2 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
-; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-LABEL: 'test_fshr_range_1'
+; CHECK-DAG: DemandedBits: 0xff for %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x7ff for %b in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshr.i32 in %fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
+; CHECK-DAG: DemandedBits: 0x1f for %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x3 for %b in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0x1f for 3 in %b2 = and i32 %b, 3
+; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %fshr to i8
+; CHECK-DAG: DemandedBits: 0xff for %fshr in %shl.t = trunc i32 %fshr to i8
+
;
%b2 = and i32 %b, 3
%fshr = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %b2)
>From 65cc5610bac847181c9157120ca152fc3fdfc3c3 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Sun, 8 Mar 2026 04:59:09 +0200
Subject: [PATCH 11/11] small test fixes
---
llvm/test/Analysis/DemandedBits/fshl.ll | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/test/Analysis/DemandedBits/fshl.ll b/llvm/test/Analysis/DemandedBits/fshl.ll
index 34ee3ebafd478..5abfd15bf62b6 100644
--- a/llvm/test/Analysis/DemandedBits/fshl.ll
+++ b/llvm/test/Analysis/DemandedBits/fshl.ll
@@ -132,6 +132,7 @@ define i32 @test_fshl_range_3(i32 %a, i32 %b, i32 %c) {
define i32 @test_fshl_range_4(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: 'test_fshl_range_4'
; CHECK-DAG: DemandedBits: 0xffffffff for %shr = ashr i32 %fshl, 8
; CHECK-DAG: DemandedBits: 0xffffff00 for %fshl in %shr = ashr i32 %fshl, 8
; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %shr = ashr i32 %fshl, 8
@@ -141,7 +142,7 @@ define i32 @test_fshl_range_4(i32 %a, i32 %b, i32 %c) {
; CHECK-DAG: DemandedBits: 0x1f for %c in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
; CHECK-DAG: DemandedBits: 0xffffffffffffffff for @llvm.fshl.i32 in %fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
-; CHECK-LABEL: 'test_fshl_range_4'
+
%fshl = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %c)
%shr = ashr i32 %fshl, 8
ret i32 %shr
More information about the llvm-commits
mailing list