[llvm] [InstCombine] Fold `lshr -> zext -> shl` patterns (PR #147737)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 11 11:19:17 PDT 2025


================
@@ -978,6 +1025,50 @@ Instruction *InstCombinerImpl::foldLShrOverflowBit(BinaryOperator &I) {
   return new ZExtInst(Overflow, Ty);
 }
 
+/// If the operand \p Op of a zext-ed left shift \p I is a logically
+/// right-shifted value, try to fold the opposing shifts.
+static Instruction *foldShrThroughZExtedShl(BinaryOperator &I, Value *Op,
+                                            unsigned ShlAmt,
+                                            InstCombinerImpl &IC,
+                                            const DataLayout &DL) {
+  Type *DestTy = I.getType();
+  const unsigned InnerBitWidth = Op->getType()->getScalarSizeInBits();
+
+  // Determine if the operand is effectively right-shifted by counting the
+  // known leading zero bits.
+  KnownBits Known = IC.computeKnownBits(Op, nullptr);
+  const unsigned MaxInnerShrAmt = Known.countMinLeadingZeros();
+  if (MaxInnerShrAmt == 0)
+    return nullptr;
+  APInt ShrMask =
+      APInt::getLowBitsSet(InnerBitWidth, std::min(MaxInnerShrAmt, ShlAmt) + 1);
+
+  // Undo the maximal inner right shift amount that simplifies the overall
+  // computation.
+  if (!refineEvaluableShiftMask(Op, ShrMask, /*IsLeftShift=*/true, IC, nullptr))
+    return nullptr;
+
----------------
dtcxzyw wrote:

I added an `if (!ShrMask.isPowerOf2()) return nullptr` check here, and all tests were still passed. I guess it may be helpful to avoid introducing new shifts in `getShiftedValue`. Not sure if it can avoid the regression in https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2662/commits/876efdaecd0a0b9b8b03b3aa83ed1568274ea511#r2267345986.

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


More information about the llvm-commits mailing list