[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