[llvm] [InstCombine] Fold icmp (zext X), (and (trunc Y), Mask) -> icmp X, trunc Y (PR #221189)
armandeep singh via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 21:22:15 PDT 2026
================
@@ -6626,12 +6648,42 @@ Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
return new ICmpInst(ICmp.getPredicate(),
SimplifiedOp0 ? SimplifiedOp0 : ICmp.getOperand(0),
SimplifiedOp1 ? SimplifiedOp1 : ICmp.getOperand(1));
+ // Catch the mirrored operand order: icmp Pred (and (trunc Y), Mask), (zext
+ // X). Canonicalization (like ugt -> ult) often swaps operands, pushing the
+ // zext to Operand 1. We need to handle this to avoid missing optimizations.
+ {
+ Value *X, *Y;
+ const APInt *Mask;
+ // Ensure we have an unsigned compare with a zext on the right side.
+ // Then look for our one use AND with a mask on the left.
+ if (match(ICmp.getOperand(1), m_ZExt(m_Value(X))) && !ICmp.isSigned() &&
+ match(ICmp.getOperand(0),
+ m_OneUse(m_c_And(m_Trunc(m_Value(Y)), m_APInt(Mask))))) {
+
+ Type *SmallType = X->getType();
+ unsigned SmallWidth = SmallType->getScalarSizeInBits();
+
+ // If the mask exactly covers the bits of the narrower type, the higher
+ // bits are already guaranteed to be zero. We can bypass the extension and
+ // compare the truncated values directly.
+ if (*Mask == APInt::getLowBitsSet(Mask->getBitWidth(), SmallWidth)) {
----------------
armandeep23947 wrote:
Fixed.
https://github.com/llvm/llvm-project/pull/221189
More information about the llvm-commits
mailing list