Repository: llvm/llvm-project
File: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (C++)

Code before:
    if (match(&I, m_c_ICmp(CmpPred, m_Sub(m_Value(A), m_Value(B)),
                           m_c_Add(m_Deferred(A), m_Deferred(B))))) {
      auto *I0 = cast<OverflowingBinaryOperator>(Op0);
      auto *I1 = cast<OverflowingBinaryOperator>(Op1);
      bool I0NUW = I0->hasNoUnsignedWrap();
      bool I1NUW = I1->hasNoUnsignedWrap();
      bool I0NSW = I0->hasNoSignedWrap();
      bool I1NSW = I1->hasNoSignedWrap();
      if ((ICmpInst::isUnsigned(Pred) && I0NUW && I1NUW) ||
          (ICmpInst::isSigned(Pred) && I0NSW && I1NSW) ||
          (ICmpInst::isEquality(Pred) &&
           ((I0NUW || I0NSW) && (I1NUW || I1NSW)))) {
        return new ICmpInst(CmpPredicate::getSwapped(CmpPred), B,
                            ConstantInt::get(Op0->getType(), 0));
      }
    }
  }

  // icmp eq (shl (zext i1 x), (zext i1 y)), 1 --> and i1 x, (not i1 y)
  // icmp ne (shl (zext i1 x), (zext i1 y)), 1 --> or i1 (not i1 x), y
  {
    Value *A, *B;
    CmpPredicate CmpPred;

    if (match(&I,
              m_c_ICmp(CmpPred, m_Shl(m_ZExt(m_Value(A)), m_ZExt(m_Value(B))),
                       m_One())) &&
        A->getType()->isIntegerTy(1) && B->getType()->isIntegerTy(1)) {

      if (CmpPred == ICmpInst::ICMP_EQ) {
        return replaceInstUsesWith(I,
                                   Builder.CreateAnd(A, Builder.CreateNot(B)));
      }
      if (CmpPred == ICmpInst::ICMP_NE) {
        return replaceInstUsesWith(I,
                                   Builder.CreateOr(Builder.CreateNot(A), B));
      }
    }
  }

  // Try to optimize equality comparisons against alloca-based pointers.
  if (Op0->getType()->isPointerTy() && I.isEquality()) {
    assert(Op1->getType()->isPointerTy() &&
           "Comparing pointer with non-pointer?");
    if (auto *Alloca = dyn_cast<AllocaInst>(getUnderlyingObject(Op0)))
      if (foldAllocaCmp(Alloca))
        return nullptr;
    if (auto *Alloca = dyn_cast<AllocaInst>(getUnderlyingObject(Op1)))
      if (foldAllocaCmp(Alloca))
        return nullptr;
  }

Review comment (suggestion):
constant will always be second operand so no need to use commuted matcher
```suggestion
              m_ICmp(CmpPred, m_Shl(m_ZExt(m_Value(A)), m_ZExt(m_Value(B))),
```

Code after:
      bool I1NUW = I1->hasNoUnsignedWrap();
      bool I0NSW = I0->hasNoSignedWrap();
      bool I1NSW = I1->hasNoSignedWrap();
      if ((ICmpInst::isUnsigned(Pred) && I0NUW && I1NUW) ||
          (ICmpInst::isSigned(Pred) && I0NSW && I1NSW) ||
          (ICmpInst::isEquality(Pred) &&
           ((I0NUW || I0NSW) && (I1NUW || I1NSW)))) {
        return new ICmpInst(CmpPredicate::getSwapped(CmpPred), B,
                            ConstantInt::get(Op0->getType(), 0));
      }
    }
  }

  // Try to optimize equality comparisons against alloca-based pointers.
  if (Op0->getType()->isPointerTy() && I.isEquality()) {
    assert(Op1->getType()->isPointerTy() &&
           "Comparing pointer with non-pointer?");
    if (auto *Alloca = dyn_cast<AllocaInst>(getUnderlyingObject(Op0)))
      if (foldAllocaCmp(Alloca))
        return nullptr;
    if (auto *Alloca = dyn_cast<AllocaInst>(getUnderlyingObject(Op1)))
      if (foldAllocaCmp(Alloca))
        return nullptr;
  }

  if (Instruction *Res = foldICmpBitCast(I))
    return Res;

  // TODO: Hoist this above the min/max bailout.
  if (Instruction *R = foldICmpWithCastOp(I))
    return R;

  {
    Value *X, *Y;
    // Transform (X & ~Y) == 0 --> (X & Y) != 0
    // and       (X & ~Y) != 0 --> (X & Y) == 0
    // if A is a power of 2.
    if (match(Op0, m_And(m_Value(X), m_Not(m_Value(Y)))) &&
        match(Op1, m_Zero()) && isKnownToBeAPowerOfTwo(X, false, &I) &&
        I.isEquality())
      return new ICmpInst(I.getInversePredicate(), Builder.CreateAnd(X, Y),
                          Op1);

    // Op0 pred Op1 -> ~Op1 pred ~Op0, if this allows us to drop an instruction.
    if (Op0->getType()->isIntOrIntVectorTy()) {
      bool ConsumesOp0, ConsumesOp1;
      if (isFreeToInvert(Op0, Op0->hasOneUse(), ConsumesOp0) &&
          isFreeToInvert(Op1, Op1->hasOneUse(), ConsumesOp1) &&
          (ConsumesOp0 || ConsumesOp1)) {
        Value *InvOp0 = getFreelyInverted(Op0, Op0->hasOneUse(), &Builder);
        Value *InvOp1 = getFreelyInverted(Op1, Op1->hasOneUse(), &Builder);