[llvm] [LLVM] Improve the DemandedBits Analysis (PR #148880)
Panagiotis K via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 15 13:54:21 PDT 2025
https://github.com/karouzakisp updated https://github.com/llvm/llvm-project/pull/148880
>From b802455c60365faf15d2225726d8da788c982145 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Tue, 15 Jul 2025 19:06:13 +0300
Subject: [PATCH 1/2] [LLVM] Enhance shift operators in the Demanded Bits
Analysis
This is done by supporting shift operators to handle non
constant shift amount.
---
llvm/lib/Analysis/DemandedBits.cpp | 46 ++++++++++++++++++++++++
llvm/test/Analysis/DemandedBits/shl.ll | 48 +++++++++++++++++++++++++-
2 files changed, 93 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 6694d5cc06c8c..2d30575c19130 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -36,6 +36,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/KnownBits.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
@@ -183,6 +184,17 @@ void DemandedBits::determineLiveOperandBits(
AB |= APInt::getHighBitsSet(BitWidth, ShiftAmt+1);
else if (S->hasNoUnsignedWrap())
AB |= APInt::getHighBitsSet(BitWidth, ShiftAmt);
+ } else {
+ ComputeKnownBits(BitWidth, UserI->getOperand(1), nullptr);
+ unsigned Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
+ unsigned Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
+ // similar to Lshr case
+ AB = (AOut.lshr(Min) | AOut.lshr(Max));
+ const auto *S = cast<ShlOperator>(UserI);
+ if (S->hasNoSignedWrap())
+ AB |= APInt::getHighBitsSet(BitWidth, Max + 1);
+ else if (S->hasNoUnsignedWrap())
+ AB |= APInt::getHighBitsSet(BitWidth, Max);
}
}
break;
@@ -197,6 +209,19 @@ void DemandedBits::determineLiveOperandBits(
// (they must be zero).
if (cast<LShrOperator>(UserI)->isExact())
AB |= APInt::getLowBitsSet(BitWidth, ShiftAmt);
+ } else {
+ ComputeKnownBits(BitWidth, UserI->getOperand(1), nullptr);
+ unsigned Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
+ unsigned Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
+ // Suppose AOut == 0b0000 0011
+ // [min, max] = [1, 3]
+ // shift by 1 we get 0b0000 0110
+ // shift by 2 we get 0b0000 1100
+ // shift by 3 we get 0b0001 1000
+ // we take the or here because need to cover all the above possibilities
+ AB = (AOut.shl(Min) | AOut.shl(Max));
+ if (cast<LShrOperator>(UserI)->isExact())
+ AB |= APInt::getLowBitsSet(BitWidth, Max);
}
}
break;
@@ -217,6 +242,27 @@ void DemandedBits::determineLiveOperandBits(
// (they must be zero).
if (cast<AShrOperator>(UserI)->isExact())
AB |= APInt::getLowBitsSet(BitWidth, ShiftAmt);
+ } else {
+ ComputeKnownBits(BitWidth, UserI->getOperand(1), nullptr);
+ unsigned Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
+ unsigned Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
+ AB = (AOut.shl(Min) | AOut.shl(Max));
+
+ if (Max) {
+ // Suppose AOut = 0011 1100
+ // [min, max] = [1, 3]
+ // ShiftAmount = 1 : Mask is 1000 0000
+ // ShiftAmount = 2 : Mask is 1100 0000
+ // ShiftAmount = 3 : Mask is 1110 0000
+ // The Mask with Max covers every case in [min, max],
+ // so we are done
+ if ((AOut & APInt::getHighBitsSet(BitWidth, Max)).getBoolValue())
+ AB.setSignBit();
+ }
+ // If the shift is exact, then the low bits are not dead
+ // (they must be zero).
+ if (cast<AShrOperator>(UserI)->isExact())
+ AB |= APInt::getLowBitsSet(BitWidth, Max);
}
}
break;
diff --git a/llvm/test/Analysis/DemandedBits/shl.ll b/llvm/test/Analysis/DemandedBits/shl.ll
index e41f5f4107735..c3313a93c1e85 100644
--- a/llvm/test/Analysis/DemandedBits/shl.ll
+++ b/llvm/test/Analysis/DemandedBits/shl.ll
@@ -57,10 +57,56 @@ define i8 @test_shl(i32 %a, i32 %b) {
; CHECK-DAG: DemandedBits: 0xff for %shl.t = trunc i32 %shl to i8
; CHECK-DAG: DemandedBits: 0xff for %shl in %shl.t = trunc i32 %shl to i8
; CHECK-DAG: DemandedBits: 0xff for %shl = shl i32 %a, %b
-; CHECK-DAG: DemandedBits: 0xffffffff for %a in %shl = shl i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for %a in %shl = shl i32 %a, %b
; CHECK-DAG: DemandedBits: 0xffffffff for %b in %shl = shl i32 %a, %b
;
%shl = shl i32 %a, %b
%shl.t = trunc i32 %shl to i8
ret i8 %shl.t
}
+
+define i8 @test_shl_var_amount(i32 %a, i32 %b){
+; CHECK-LABEL: 'test_shl_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 = shl i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xff for %1 in %4 = shl i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = shl i32 %1, %3
+; 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 %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for %a in %1 = add nsw i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for %b in %1 = add nsw i32 %a, %b
+;
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = shl i32 %1, %3
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
+
+define i8 @test_shl_var_amount_nsw(i32 %a, i32 %b){
+ ; CHECK-LABEL 'test_shl_var_amount_nsw'
+ ; 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 = shl nsw i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = shl nsw i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = shl nsw i32 %1, %3
+ ; 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 %2 = trunc i32 %1 to i8
+ ; CHECK-DAG: DemandedBits: 0xff for %1 in %2 = trunc i32 %1 to i8
+ ; 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
+ ;
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = shl nsw i32 %1, %3
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
>From 289fb1cf05a2d3cf97099e96988459cf5e5363c1 Mon Sep 17 00:00:00 2001
From: Panagiotis Karouzakis <karouzakispan at gmail.com>
Date: Tue, 15 Jul 2025 23:54:04 +0300
Subject: [PATCH 2/2] [LLVM] created new tests for lshr and ashr, and updated
the Range handle non continued bits for AOut
---
llvm/lib/Analysis/DemandedBits.cpp | 35 +++++--
llvm/test/Analysis/DemandedBits/ashr.ll | 112 +++++++++++++++++++++
llvm/test/Analysis/DemandedBits/lshr.ll | 123 ++++++++++++++++++++++++
3 files changed, 260 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/Analysis/DemandedBits/ashr.ll
create mode 100644 llvm/test/Analysis/DemandedBits/lshr.ll
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 2d30575c19130..9c198224d0651 100644
--- a/llvm/lib/Analysis/DemandedBits.cpp
+++ b/llvm/lib/Analysis/DemandedBits.cpp
@@ -36,7 +36,6 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/KnownBits.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
@@ -77,6 +76,21 @@ void DemandedBits::determineLiveOperandBits(
computeKnownBits(V2, Known2, DL, &AC, UserI, &DT);
}
};
+ auto GetShiftedRange = [&](unsigned const Min, unsigned const Max,
+ bool ShiftLeft) {
+ APInt Range = APInt::getLowBitsSet(BitWidth, Max + 1) &
+ ~APInt::getLowBitsSet(BitWidth, Min);
+ using ShiftFn = APInt (APInt::*)(unsigned) const; // one-word shift overload
+ auto Shift = ShiftLeft ? static_cast<ShiftFn>(&APInt::shl)
+ : static_cast<ShiftFn>(&APInt::lshr);
+ AB = APInt::getZero(BitWidth);
+ APInt Bits = AOut;
+ while (Bits != 0) {
+ unsigned I = Bits.countr_zero();
+ AB |= (Range.*Shift)(I);
+ Bits.clearBit(I);
+ }
+ };
switch (UserI->getOpcode()) {
default: break;
@@ -189,7 +203,7 @@ void DemandedBits::determineLiveOperandBits(
unsigned Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
unsigned Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
// similar to Lshr case
- AB = (AOut.lshr(Min) | AOut.lshr(Max));
+ GetShiftedRange(Min, Max, false);
const auto *S = cast<ShlOperator>(UserI);
if (S->hasNoSignedWrap())
AB |= APInt::getHighBitsSet(BitWidth, Max + 1);
@@ -213,13 +227,15 @@ void DemandedBits::determineLiveOperandBits(
ComputeKnownBits(BitWidth, UserI->getOperand(1), nullptr);
unsigned Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
unsigned Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
- // Suppose AOut == 0b0000 0011
+ // Suppose AOut == 0b0000 1001
// [min, max] = [1, 3]
- // shift by 1 we get 0b0000 0110
- // shift by 2 we get 0b0000 1100
- // shift by 3 we get 0b0001 1000
- // we take the or here because need to cover all the above possibilities
- AB = (AOut.shl(Min) | AOut.shl(Max));
+ // we create the range 0b0000 1110
+ // shift by 1 we get 0b0001 1100
+ // shift by 2 we get 0b0011 1000
+ // shift by 3 we get 0b0111 0000
+ // we take the or for every shift to cover all the positions.
+ //
+ GetShiftedRange(Min, Max, true);
if (cast<LShrOperator>(UserI)->isExact())
AB |= APInt::getLowBitsSet(BitWidth, Max);
}
@@ -246,8 +262,7 @@ void DemandedBits::determineLiveOperandBits(
ComputeKnownBits(BitWidth, UserI->getOperand(1), nullptr);
unsigned Min = Known.getMinValue().getLimitedValue(BitWidth - 1);
unsigned Max = Known.getMaxValue().getLimitedValue(BitWidth - 1);
- AB = (AOut.shl(Min) | AOut.shl(Max));
-
+ GetShiftedRange(Min, Max, true);
if (Max) {
// Suppose AOut = 0011 1100
// [min, max] = [1, 3]
diff --git a/llvm/test/Analysis/DemandedBits/ashr.ll b/llvm/test/Analysis/DemandedBits/ashr.ll
new file mode 100644
index 0000000000000..79e9a8c086256
--- /dev/null
+++ b/llvm/test/Analysis/DemandedBits/ashr.ll
@@ -0,0 +1,112 @@
+; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
+
+define i8 @test_ashr_const_amount_4(i32 %a) {
+; CHECK-LABEL: 'test_ashr_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for %ashr = ashr i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xff0 for %a in %ashr = ashr i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xffffffff for 4 in %ashr = ashr i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xff for %ashr.t = trunc i32 %ashr to i8
+; CHECK-DAG: DemandedBits: 0xff for %ashr in %ashr.t = trunc i32 %ashr to i8
+;
+ %ashr = ashr i32 %a, 4
+ %ashr.t = trunc i32 %ashr to i8
+ ret i8 %ashr.t
+}
+
+define i8 @test_ashr_const_amount_5(i32 %a) {
+; CHECK-LABEL: 'test_ashr_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for %ashr = ashr i32 %a, 5
+; CHECK-DAG: DemandedBits: 0x1fe0 for %a in %ashr = ashr i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xffffffff for 5 in %ashr = ashr i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xff for %ashr.t = trunc i32 %ashr to i8
+; CHECK-DAG: DemandedBits: 0xff for %ashr in %ashr.t = trunc i32 %ashr to i8
+;
+ %ashr = ashr i32 %a, 5
+ %ashr.t = trunc i32 %ashr to i8
+ ret i8 %ashr.t
+}
+
+define i8 @test_ashr_const_amount_8(i32 %a) {
+; CHECK-LABEL: 'test_ashr_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for %ashr = ashr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff00 for %a in %ashr = ashr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %ashr = ashr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff for %ashr.t = trunc i32 %ashr to i8
+; CHECK-DAG: DemandedBits: 0xff for %ashr in %ashr.t = trunc i32 %ashr to i8
+;
+ %ashr = ashr i32 %a, 8
+ %ashr.t = trunc i32 %ashr to i8
+ ret i8 %ashr.t
+}
+
+define i8 @test_ashr_const_amount_9(i32 %a) {
+
+; CHECK-LABEL: 'test_ashr_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for %ashr.t = trunc i32 %ashr to i8
+; CHECK-DAG: DemandedBits: 0xff for %ashr in %ashr.t = trunc i32 %ashr to i8
+; CHECK-DAG: DemandedBits: 0xff for %ashr = ashr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff00 for %a in %ashr = ashr i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in %ashr = ashr i32 %a, 8
+;
+ %ashr = ashr i32 %a, 8
+ %ashr.t = trunc i32 %ashr to i8
+ ret i8 %ashr.t
+}
+
+define i8 @test_ashr(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_ashr'
+; CHECK-DAG: DemandedBits: 0xff for %ashr = ashr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in %ashr = ashr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in %ashr = ashr i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for %ashr.t = trunc i32 %ashr to i8
+; CHECK-DAG: DemandedBits: 0xff for %ashr in %ashr.t = trunc i32 %ashr to i8
+;
+ %ashr = ashr i32 %a, %b
+ %ashr.t = trunc i32 %ashr to i8
+ ret i8 %ashr.t
+}
+
+define i8 @test_ashr_var_amount(i32 %a, i32 %b){
+; CHECK-LABEL: 'test_ashr_var_amount'
+; CHECK-DAG: DemandedBits: 0xff for %4 = ashr i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = ashr i32 %1, %3
+; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = ashr i32 %1, %3
+; 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 %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: 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 %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 = ashr i32 %1, %3
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
+
+ ; CHECK-LABEL 'test_ashr_var_amount_nsw'
+ ; 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 %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 = ashr exact i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %1 in %4 = ashr exact i32 %1, %3
+ ; CHECK-DAG: DemandedBits: 0xffffffff for %3 in %4 = ashr exact i32 %1, %3
+ ;
+ %1 = add nsw i32 %a, %b
+ %2 = trunc i32 %1 to i8
+ %3 = zext i8 %2 to i32
+ %4 = ashr exact i32 %1, %3
+ %5 = trunc i32 %4 to i8
+ ret i8 %5
+}
diff --git a/llvm/test/Analysis/DemandedBits/lshr.ll b/llvm/test/Analysis/DemandedBits/lshr.ll
new file mode 100644
index 0000000000000..81c7da4ca8b38
--- /dev/null
+++ b/llvm/test/Analysis/DemandedBits/lshr.ll
@@ -0,0 +1,123 @@
+; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
+
+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
+}
+DemandedBits: 0xff for %4 = lshr i32 %1, %3
+DemandedBits: 0xffffffff for %1 in %4 = lshr i32 %1, %3
+DemandedBits: 0xffffffff for %3 in %4 = lshr i32 %1, %3
+DemandedBits: 0xff for %5 = trunc i32 %4 to i8
+DemandedBits: 0xff for %4 in %5 = trunc i32 %4 to i8
+DemandedBits: 0xffffffff for %3 = zext i8 %2 to i32
+DemandedBits: 0xff for %2 in %3 = zext i8 %2 to i32
+DemandedBits: 0xffffffff for %1 = add nsw i32 %a, %b
+DemandedBits: 0xffffffff for %a in %1 = add nsw i32 %a, %b
+DemandedBits: 0xffffffff for %b in %1 = add nsw i32 %a, %b
+DemandedBits: 0xff for %2 = trunc i32 %1 to i8
+DemandedBits: 0xff for %1 in %2 = trunc i32 %1 to i8
+
+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
+}
More information about the llvm-commits
mailing list