[llvm] [LLVM] Improve the DemandedBits Analysis (PR #148853)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 15 07:13:26 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Panagiotis K (karouzakisp)

<details>
<summary>Changes</summary>

This patch adds support for missing operators inside the DemandedBits Analysis. Those operators are SDiv, UDiv, URem, SRem. Also, other operators such as Shl and Ashr are improved to handle non constant argument shift amount. Multiplication is also improved. Comparison with the upstream version of llvm with the Oz pipeline showed up to 10% code size reduction in the llvm test suite.

---

Patch is 27.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/148853.diff


6 Files Affected:

- (modified) llvm/lib/Analysis/DemandedBits.cpp (+93-4) 
- (modified) llvm/test/Analysis/DemandedBits/basic.ll (+25) 
- (added) llvm/test/Analysis/DemandedBits/div_rem.ll (+261) 
- (modified) llvm/test/Analysis/DemandedBits/shl.ll (+47-1) 
- (modified) llvm/test/Transforms/LoopVectorize/AArch64/induction-costs-sve.ll (+19-19) 
- (modified) llvm/test/Transforms/LoopVectorize/scalable-trunc-min-bitwidth.ll (+3-3) 


``````````diff
diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp
index 6694d5cc06c8c..1fa94e95cbceb 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>
@@ -164,10 +165,24 @@ void DemandedBits::determineLiveOperandBits(
     }
     break;
   case Instruction::Mul:
-    // Find the highest live output bit. We don't need any more input
-    // bits than that (adds, and thus subtracts, ripple only to the
-    // left).
-    AB = APInt::getLowBitsSet(BitWidth, AOut.getActiveBits());
+    const APInt *C;
+    if (OperandNo == 0) {
+      // to have output bits 0...H-1 we need the input bits
+      // 0...(H - ceiling(log_2))
+      if (match(UserI->getOperand(1), m_APInt(C))) {
+        auto LogC = C->isOne() ? 0 : C->logBase2() + 1;
+        unsigned Need =
+            AOut.getActiveBits() > LogC ? AOut.getActiveBits() - LogC : 0;
+        AB = APInt::getLowBitsSet(BitWidth, Need);
+      } else { // TODO: we can possibly check for Op0 constant too
+        AB = APInt::getLowBitsSet(BitWidth, AOut.getActiveBits());
+      }
+    } else {
+      // Find the highest live output bit. We don't need any more input
+      // bits than that (adds, and thus subtracts, ripple only to the
+      // left).
+      AB = APInt::getLowBitsSet(BitWidth, AOut.getActiveBits());
+    }
     break;
   case Instruction::Shl:
     if (OperandNo == 0) {
@@ -183,6 +198,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 +223,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 +256,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;
@@ -246,6 +306,35 @@ void DemandedBits::determineLiveOperandBits(
     else
       AB &= ~(Known.One & ~Known2.One);
     break;
+  case Instruction::UDiv:
+  case Instruction::URem:
+  case Instruction::SDiv:
+  case Instruction::SRem: {
+    auto Opc = UserI->getOpcode();
+    auto IsDiv = Opc == Instruction::UDiv || Opc == Instruction::SDiv;
+    bool IsSigned = Opc == Instruction::SDiv || Opc == Instruction::SRem;
+    if (OperandNo == 0) {
+      const APInt *DivAmnt;
+      if (match(UserI->getOperand(1), m_APInt(DivAmnt))) {
+        uint64_t D = DivAmnt->getZExtValue();
+        if (isPowerOf2_64(D)) {
+          unsigned Sh = Log2_64(D);
+          if (IsDiv) {
+            AB = AOut.shl(Sh);
+          } else {
+            AB = AOut & APInt::getLowBitsSet(BitWidth, Sh);
+          }
+        } else { // Non power of 2 constant div
+          unsigned LowQ = AOut.getActiveBits();
+          unsigned Need = LowQ + Log2_64_Ceil(D);
+          if (IsSigned)
+            Need++;
+          AB = APInt::getLowBitsSet(BitWidth, std::min(BitWidth, Need));
+        }
+      }
+    }
+    break;
+  }
   case Instruction::Xor:
   case Instruction::PHI:
     AB = AOut;
diff --git a/llvm/test/Analysis/DemandedBits/basic.ll b/llvm/test/Analysis/DemandedBits/basic.ll
index 4dc59c5392935..62eba9eaa81c5 100644
--- a/llvm/test/Analysis/DemandedBits/basic.ll
+++ b/llvm/test/Analysis/DemandedBits/basic.ll
@@ -25,3 +25,28 @@ define i8 @test_mul(i32 %a, i32 %b) {
   %6 = add nsw i8 %3, %5
   ret i8 %6
 }
+; CHECK-LABEL: Printing analysis 'Demanded Bits Analysis' for function 'test_mul_constant':
+; CHECK-DAG: DemandedBits: 0xff for   %3 = trunc i32 %2 to i8
+; CHECK-DAG: DemandedBits: 0xff for %2 in   %3 = trunc i32 %2 to i8
+; CHECK-DAG: DemandedBits: 0xff for   %2 = mul nsw i32 %1, 6
+; CHECK-DAG: DemandedBits: 0x1f for %1 in   %2 = mul nsw i32 %1, 6
+; CHECK-DAG: DemandedBits: 0xff for 6 in   %2 = mul nsw i32 %1, 6
+; CHECK-DAG: DemandedBits: 0x1 for   %4 = trunc i32 %2 to i1
+; CHECK-DAG: DemandedBits: 0x1 for %2 in   %4 = trunc i32 %2 to i1
+; CHECK-DAG: DemandedBits: 0x1f for   %1 = add nsw i32 %a, 12
+; CHECK-DAG: DemandedBits: 0x1f for %a in   %1 = add nsw i32 %a, 12
+; CHECK-DAG: DemandedBits: 0x1f for 12 in   %1 = add nsw i32 %a, 12
+; CHECK-DAG: DemandedBits: 0xff for   %5 = zext i1 %4 to i8
+; CHECK-DAG: DemandedBits: 0x1 for %4 in   %5 = zext i1 %4 to i8
+; CHECK-DAG: DemandedBits: 0xff for   %6 = add nsw i8 %3, %5
+; CHECK-DAG: DemandedBits: 0xff for %3 in   %6 = add nsw i8 %3, %5
+; CHECK-DAG: DemandedBits: 0xff for %5 in   %6 = add nsw i8 %3, %5
+define i8 @test_mul_constant(i32 %a, i32 %b){
+  %1 = add nsw i32 %a, 12
+  %2 = mul nsw i32 %1, 6
+  %3 = trunc i32 %2 to i8
+  %4 = trunc i32 %2 to i1
+  %5 = zext i1 %4 to i8
+  %6 = add nsw i8 %3, %5
+  ret i8 %6
+}
diff --git a/llvm/test/Analysis/DemandedBits/div_rem.ll b/llvm/test/Analysis/DemandedBits/div_rem.ll
new file mode 100644
index 0000000000000..818cba17dc1a6
--- /dev/null
+++ b/llvm/test/Analysis/DemandedBits/div_rem.ll
@@ -0,0 +1,261 @@
+; RUN: opt -S -disable-output -passes="print<demanded-bits>" < %s 2>&1 | FileCheck %s
+
+define i8 @test_sdiv_const_amount_4(i32 %a) {
+; CHECK-LABEL: 'test_sdiv_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for   %div = sdiv i32 %a, 4
+; CHECK-DAG: DemandedBits: 0x3fc for %a in   %div = sdiv i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xffffffff for 4 in   %div = sdiv i32 %a, 4
+;
+  %div = sdiv i32 %a, 4
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_sdiv_const_amount_5(i32 %a) {
+; CHECK-LABEL: 'test_sdiv_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for   %div = sdiv i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xfff for %a in   %div = sdiv i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xffffffff for 5 in   %div = sdiv i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = sdiv i32 %a, 5
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_sdiv_const_amount_8(i32 %a) {
+; CHECK-LABEL: 'test_sdiv_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for   %div = sdiv i32 %a, 8
+; CHECK-DAG: DemandedBits: 0x7f8 for %a in   %div = sdiv i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in   %div = sdiv i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = sdiv i32 %a, 8
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_sdiv_const_amount_9(i32 %a) {
+; CHECK-LABEL: 'test_sdiv_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for   %div = udiv i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xfff for %a in   %div = udiv i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xffffffff for 9 in   %div = udiv i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = udiv i32 %a, 9
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_sdiv(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_sdiv'
+; CHECK-DAG: DemandedBits: 0xff for   %div = sdiv i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in   %div = sdiv i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in   %div = sdiv i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = sdiv i32 %a, %b
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_udiv_const_amount_4(i32 %a) {
+; CHECK-LABEL: 'test_udiv_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for   %div = udiv i32 %a, 4
+; CHECK-DAG: DemandedBits: 0x3fc for %a in   %div = udiv i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xffffffff for 4 in   %div = udiv i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = udiv i32 %a, 4
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_udiv_const_amount_5(i32 %a) {
+; CHECK-LABEL: 'test_udiv_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for   %div = udiv i32 %a, 5
+; CHECK-DAG: DemandedBits: 0x7ff for %a in   %div = udiv i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xffffffff for 5 in   %div = udiv i32 %a, 5
+;
+  %div = udiv i32 %a, 5
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_udiv_const_amount_8(i32 %a) {
+; CHECK-LABEL: 'test_udiv_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for   %div = udiv i32 %a, 8
+; CHECK-DAG: DemandedBits: 0x7f8 for %a in   %div = udiv i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in   %div = udiv i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = udiv i32 %a, 8
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_udiv_const_amount_9(i32 %a) {
+; CHECK-LABEL: 'test_udiv_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for   %div = udiv i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xfff for %a in   %div = udiv i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xffffffff for 9 in   %div = udiv i32 %a, 9
+;
+  %div = udiv i32 %a, 9
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_udiv(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_udiv'
+; CHECK-DAG: DemandedBits: 0xff for   %div = udiv i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in   %div = udiv i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in   %div = udiv i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for   %div.t = trunc i32 %div to i8
+; CHECK-DAG: DemandedBits: 0xff for %div in   %div.t = trunc i32 %div to i8
+;
+  %div = udiv i32 %a, %b
+  %div.t = trunc i32 %div to i8
+  ret i8 %div.t
+}
+
+define i8 @test_srem_const_amount_4(i32 %a) {
+; CHECK-LABEL: 'test_srem_const_amount_4'
+; CHECK-DAG:  DemandedBits: 0xff for   %rem = srem i32 %a, 4
+; CHECK-DAG:  DemandedBits: 0x3 for %a in   %rem = srem i32 %a, 4
+; CHECK-DAG:  DemandedBits: 0xffffffff for 4 in   %rem = srem i32 %a, 4
+; CHECK-DAG:  DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG:  DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+;
+  %rem = srem i32 %a, 4
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_srem_const_amount_5(i32 %a) {
+; CHECK-LABEL: 'test_srem_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for   %rem = srem i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xfff for %a in   %rem = srem i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xffffffff for 5 in   %rem = srem i32 %a, 5
+;
+  %rem = srem i32 %a, 5
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_srem_const_amount_8(i32 %a) {
+; CHECK-LABEL: 'test_srem_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for   %rem = srem i32 %a, 8
+; CHECK-DAG: DemandedBits: 0x7 for %a in   %rem = srem i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in   %rem = srem i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+;
+  %rem = srem i32 %a, 8
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_srem_const_amount_9(i32 %a) {
+; CHECK-LABEL: 'test_srem_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for   %rem = srem i32 %a, 9
+; CHECK-DAG: DemandedBits: 0x1fff for %a in   %rem = srem i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xffffffff for 9 in   %rem = srem i32 %a, 9
+;
+  %rem = srem i32 %a, 9
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_srem(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_srem'
+; CHECK-DAG: DemandedBits: 0xff for   %rem = srem i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in   %rem = srem i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in   %rem = srem i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+;
+  %rem = srem i32 %a, %b
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_urem_const_amount_4(i32 %a) {
+; CHECK-LABEL: 'test_urem_const_amount_4'
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for   %rem = urem i32 %a, 4
+; CHECK-DAG: DemandedBits: 0x3 for %a in   %rem = urem i32 %a, 4
+; CHECK-DAG: DemandedBits: 0xffffffff for 4 in   %rem = urem i32 %a, 4
+;
+  %rem = urem i32 %a, 4
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_urem_const_amount_5(i32 %a) {
+; CHECK-LABEL: 'test_urem_const_amount_5'
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for   %rem = urem i32 %a, 5
+; CHECK-DAG: DemandedBits: 0x7ff for %a in   %rem = urem i32 %a, 5
+; CHECK-DAG: DemandedBits: 0xffffffff for 5 in   %rem = urem i32 %a, 5
+;
+  %rem = urem i32 %a, 5
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_urem_const_amount_8(i32 %a) {
+; CHECK-LABEL: 'test_urem_const_amount_8'
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for   %rem = urem i32 %a, 8
+; CHECK-DAG: DemandedBits: 0x7 for %a in   %rem = urem i32 %a, 8
+; CHECK-DAG: DemandedBits: 0xffffffff for 8 in   %rem = urem i32 %a, 8
+;
+  %rem = urem i32 %a, 8
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_urem_const_amount_9(i32 %a) {
+; CHECK-LABEL: 'test_urem_const_amount_9'
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for   %rem = urem i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xfff for %a in   %rem = urem i32 %a, 9
+; CHECK-DAG: DemandedBits: 0xffffffff for 9 in   %rem = urem i32 %a, 9
+;
+  %rem = urem i32 %a, 9
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
+
+define i8 @test_urem(i32 %a, i32 %b) {
+; CHECK-LABEL: 'test_urem'
+; CHECK-DAG: DemandedBits: 0xff for   %rem = urem i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %a in   %rem = urem i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xffffffff for %b in   %rem = urem i32 %a, %b
+; CHECK-DAG: DemandedBits: 0xff for   %rem.t = trunc i32 %rem to i8
+; CHECK-DAG: DemandedBits: 0xff for %rem in   %rem.t = trunc i32 %rem to i8
+;
+  %rem = urem i32 %a, %b
+  %rem.t = trunc i32 %rem to i8
+  ret i8 %rem.t
+}
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 = ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/148853


More information about the llvm-commits mailing list