[llvm] [ValueTracking] Let ComputeKnownSignBits handle (shl (zext X), C) (PR #97693)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 4 09:55:46 PDT 2024


================
@@ -3757,11 +3757,21 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
     }
     case Instruction::Shl: {
       const APInt *ShAmt;
+      Value *X = nullptr;
       if (match(U->getOperand(1), m_APInt(ShAmt))) {
         // shl destroys sign bits.
-        Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q);
-        if (ShAmt->uge(TyBits) ||   // Bad shift.
-            ShAmt->uge(Tmp)) break; // Shifted all sign bits out.
+        if (ShAmt->uge(TyBits))
+          break; // Bad shift.
+        // We can look through a zext (more or less treating it as a sext) if
+        // all extended bits are shifted out.
+        if (match(U->getOperand(0), m_ZExt(m_Value(X))) &&
+            ShAmt->uge(TyBits - X->getType()->getScalarSizeInBits())) {
+          Tmp = ComputeNumSignBits(X, Depth + 1, Q);
----------------
dtcxzyw wrote:

Regression: https://alive2.llvm.org/ce/z/tcsmgq
Now `src` cannot be folded into `tgt`.
```
define i32 @src(i32 %add.i.i370) {
   %shr.i.i = ashr i32 %add.i.i370, 5
   %conv.i.i371 = zext i32 %shr.i.i to i64
   %shl.i.i = shl i64 %conv.i.i371, 34
    %conv6.i = ashr exact i64 %shl.i.i, 32
   %conv.i41.i = trunc nsw i64 %conv6.i to i32
   ret i32 %conv.i41.i
}

define i32 @tgt(i32 %add.i.i370) {
  %121 = ashr i32 %add.i.i370, 3
   %122 = and i32 %121, -4
   ret i32 %122
}
```


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


More information about the llvm-commits mailing list