//===- InstCombineSimplifyDemanded.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains logic for simplifying instructions based on information
// about how they are used.
//
//===----------------------------------------------------------------------===//

#include "InstCombineInternal.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Transforms/InstCombine/InstCombiner.h"

using namespace llvm;
using namespace llvm::PatternMatch;

#define DEBUG_TYPE "instcombine"

static cl::opt<bool>
    VerifyKnownBits("instcombine-verify-known-bits",
                    cl::desc("Verify that computeKnownBits() and "
                             "SimplifyDemandedBits() are consistent"),
                    cl::Hidden, cl::init(false));

static cl::opt<unsigned> SimplifyDemandedVectorEltsDepthLimit(
    "instcombine-simplify-vector-elts-depth",
    cl::desc(
        "Depth limit when simplifying vector instructions and their operands"),
    cl::Hidden, cl::init(10));

/// Check to see if the specified operand of the specified instruction is a
/// constant integer. If so, check to see if there are any bits set in the
/// constant that are not demanded. If so, shrink the constant and return true.
static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo,
                                   const APInt &Demanded) {
  assert(I && "No instruction?");
  assert(OpNo < I->getNumOperands() && "Operand index too large");

  // The operand must be a constant integer or splat integer.
  Value *Op = I->getOperand(OpNo);
  const APInt *C;
  if (!match(Op, m_APInt(C)))
    return false;

  // If there are no bits set that aren't demanded, nothing to do.
  if (C->isSubsetOf(Demanded))
    return false;

  // This instruction is producing bits that are not demanded. Shrink the RHS.
  I->setOperand(OpNo, ConstantInt::get(Op->getType(), *C & Demanded));

  return true;
}

/// Let N = 2 * M.
/// Given an N-bit integer representing a pack of two M-bit integers,
/// we can select one of the packed integers by right-shifting by either
/// zero or M (which is the most straightforward to check if M is a power
/// of 2), and then isolating the lower M bits. In this case, we can
/// represent the shift as a select on whether the shr amount is nonzero.
static Value *simplifyShiftSelectingPackedElement(Instruction *I,
                                                  const APInt &DemandedMask,
                                                  InstCombinerImpl &IC,
                                                  unsigned Depth) {
  assert(I->getOpcode() == Instruction::LShr &&
         "Only lshr instruction supported");

  uint64_t ShlAmt;
  Value *Upper, *Lower;
  if (!match(I->getOperand(0),
             m_OneUse(m_c_DisjointOr(
                 m_OneUse(m_Shl(m_Value(Upper), m_ConstantInt(ShlAmt))),
                 m_Value(Lower)))))
    return nullptr;

  if (!isPowerOf2_64(ShlAmt))
    return nullptr;

  const uint64_t DemandedBitWidth = DemandedMask.getActiveBits();
  if (DemandedBitWidth > ShlAmt)
    return nullptr;

  // Check that upper demanded bits are not lost from lshift.
  if (Upper->getType()->getScalarSizeInBits() < ShlAmt + DemandedBitWidth)
    return nullptr;

  KnownBits KnownLowerBits = IC.computeKnownBits(Lower, I, Depth);
  if (!KnownLowerBits.getMaxValue().isIntN(ShlAmt))
    return nullptr;

  Value *ShrAmt = I->getOperand(1);
  KnownBits KnownShrBits = IC.computeKnownBits(ShrAmt, I, Depth);

  // Verify that ShrAmt is either exactly ShlAmt (which is a power of 2) or
  // zero.
  if (~KnownShrBits.Zero != ShlAmt)
    return nullptr;

  IRBuilderBase::InsertPointGuard Guard(IC.Builder);
  IC.Builder.SetInsertPoint(I);
  Value *ShrAmtZ =
      IC.Builder.CreateICmpEQ(ShrAmt, Constant::getNullValue(ShrAmt->getType()),
                              ShrAmt->getName() + ".z");
  // There is no existing !prof metadata we can derive the !prof metadata for
  // this select.
  Value *Select = IC.Builder.CreateSelectWithUnknownProfile(ShrAmtZ, Lower,
                                                            Upper, DEBUG_TYPE);
  Select->takeName(I);
  return Select;
}

/// Returns the bitwidth of the given scalar or pointer type. For vector types,
/// returns the element type's bitwidth.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL) {
  if (unsigned BitWidth = Ty->getScalarSizeInBits())
    return BitWidth;

  return DL.getPointerTypeSizeInBits(Ty);
}

/// Inst is an integer instruction that SimplifyDemandedBits knows about. See if
/// the instruction has any properties that allow us to simplify its operands.
bool InstCombinerImpl::SimplifyDemandedInstructionBits(Instruction &Inst,
                                                       KnownBits &Known) {
  APInt DemandedMask(APInt::getAllOnes(Known.getBitWidth()));
  Value *V = SimplifyDemandedUseBits(&Inst, DemandedMask, Known,
                                     SQ.getWithInstruction(&Inst));
  if (!V) return false;
  if (V == &Inst) return true;
  replaceInstUsesWith(Inst, V);
  return true;
}

/// Inst is an integer instruction that SimplifyDemandedBits knows about. See if
/// the instruction has any properties that allow us to simplify its operands.
bool InstCombinerImpl::SimplifyDemandedInstructionBits(Instruction &Inst) {
  KnownBits Known(getBitWidth(Inst.getType(), DL));
  return SimplifyDemandedInstructionBits(Inst, Known);
}

/// This form of SimplifyDemandedBits simplifies the specified instruction
/// operand if possible, updating it in place. It returns true if it made any
/// change and false otherwise.
bool InstCombinerImpl::SimplifyDemandedBits(Instruction *I, unsigned OpNo,
                                            const APInt &DemandedMask,
                                            KnownBits &Known,
                                            const SimplifyQuery &Q,
                                            unsigned Depth) {
  Use &U = I->getOperandUse(OpNo);
  Value *V = U.get();
  if (isa<Constant>(V)) {
    llvm::computeKnownBits(V, Known, Q, Depth);
    return false;
  }

  Known.resetAll();
  if (DemandedMask.isZero()) {
    // Not demanding any bits from V.
    replaceUse(U, UndefValue::get(V->getType()));
    return true;
  }

  Instruction *VInst = dyn_cast<Instruction>(V);
  if (!VInst) {
    llvm::computeKnownBits(V, Known, Q, Depth);
    return false;
  }

  if (Depth == MaxAnalysisRecursionDepth)
    return false;

  Value *NewVal;
  if (VInst->hasOneUse()) {
    // If the instruction has one use, we can directly simplify it.
    NewVal = SimplifyDemandedUseBits(VInst, DemandedMask, Known, Q, Depth);
  } else {
    // If there are multiple uses of this instruction, then we can simplify
    // VInst to some other value, but not modify the instruction.
    NewVal =
        SimplifyMultipleUseDemandedBits(VInst, DemandedMask, Known, Q, Depth);
  }
  if (!NewVal) return false;
  if (Instruction* OpInst = dyn_cast<Instruction>(U))
    salvageDebugInfo(*OpInst);

  replaceUse(U, NewVal);
  return true;
}

/// This function attempts to replace V with a simpler value based on the
/// demanded bits. When this function is called, it is known that only the bits
/// set in DemandedMask of the result of V are ever used downstream.
/// Consequently, depending on the mask and V, it may be possible to replace V
/// with a constant or one of its operands. In such cases, this function does
/// the replacement and returns true. In all other cases, it returns false after
/// analyzing the expression and setting KnownOne and known to be one in the
/// expression. Known.Zero contains all the bits that are known to be zero in
/// the expression. These are provided to potentially allow the caller (which
/// might recursively be SimplifyDemandedBits itself) to simplify the
/// expression.
/// Known.One and Known.Zero always follow the invariant that:
///   Known.One & Known.Zero == 0.
/// That is, a bit can't be both 1 and 0. The bits in Known.One and Known.Zero
/// are accurate even for bits not in DemandedMask. Note
/// also that the bitwidth of V, DemandedMask, Known.Zero and Known.One must all
/// be the same.
///
/// This returns null if it did not change anything and it permits no
/// simplification.  This returns V itself if it did some simplification of V's
/// operands based on the information about what bits are demanded. This returns
/// some other non-null value if it found out that V is equal to another value
/// in the context where the specified bits are demanded, but not for all users.
Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
                                                 const APInt &DemandedMask,
                                                 KnownBits &Known,
                                                 const SimplifyQuery &Q,
                                                 unsigned Depth) {
  assert(I != nullptr && "Null pointer of Value???");
  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
  uint32_t BitWidth = DemandedMask.getBitWidth();
  Type *VTy = I->getType();
  assert(
      (!VTy->isIntOrIntVectorTy() || VTy->getScalarSizeInBits() == BitWidth) &&
      Known.getBitWidth() == BitWidth &&
      "Value *V, DemandedMask and Known must have same BitWidth");

  KnownBits LHSKnown(BitWidth), RHSKnown(BitWidth);

  // Update flags after simplifying an operand based on the fact that some high
  // order bits are not demanded.
  auto disableWrapFlagsBasedOnUnusedHighBits = [](Instruction *I,
                                                  unsigned NLZ) {
    if (NLZ > 0) {
      // Disable the nsw and nuw flags here: We can no longer guarantee that
      // we won't wrap after simplification. Removing the nsw/nuw flags is
      // legal here because the top bit is not demanded.
      I->setHasNoSignedWrap(false);
      I->setHasNoUnsignedWrap(false);
    }
    return I;
  };

  // If the high-bits of an ADD/SUB/MUL are not demanded, then we do not care
  // about the high bits of the operands.
  auto simplifyOperandsBasedOnUnusedHighBits = [&](APInt &DemandedFromOps) {
    unsigned NLZ = DemandedMask.countl_zero();
    // Right fill the mask of bits for the operands to demand the most
    // significant bit and all those below it.
    DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ);
    if (ShrinkDemandedConstant(I, 0, DemandedFromOps) ||
        SimplifyDemandedBits(I, 0, DemandedFromOps, LHSKnown, Q, Depth + 1) ||
        ShrinkDemandedConstant(I, 1, DemandedFromOps) ||
        SimplifyDemandedBits(I, 1, DemandedFromOps, RHSKnown, Q, Depth + 1)) {
      disableWrapFlagsBasedOnUnusedHighBits(I, NLZ);
      return true;
    }
    return false;
  };

  switch (I->getOpcode()) {
  default:
    llvm::computeKnownBits(I, Known, Q, Depth);
    break;
  case Instruction::And: {
    // If either the LHS or the RHS are Zero, the result is zero.
    if (SimplifyDemandedBits(I, 1, DemandedMask, RHSKnown, Q, Depth + 1) ||
        SimplifyDemandedBits(I, 0, DemandedMask & ~RHSKnown.Zero, LHSKnown, Q,
                             Depth + 1))
      return I;

    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Q, Depth);

    // If the client is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(VTy, Known.One);

    // If all of the demanded bits are known 1 on one side, return the other.
    // These bits cannot contribute to the result of the 'and'.
    if (DemandedMask.isSubsetOf(LHSKnown.Zero | RHSKnown.One))
      return I->getOperand(0);
    if (DemandedMask.isSubsetOf(RHSKnown.Zero | LHSKnown.One))
      return I->getOperand(1);

    // If the RHS is a constant, see if we can simplify it.
    if (ShrinkDemandedConstant(I, 1, DemandedMask & ~LHSKnown.Zero))
      return I;

    break;
  }
  case Instruction::Or: {
    // If either the LHS or the RHS are One, the result is One.
    if (SimplifyDemandedBits(I, 1, DemandedMask, RHSKnown, Q, Depth + 1) ||
        SimplifyDemandedBits(I, 0, DemandedMask & ~RHSKnown.One, LHSKnown, Q,
                             Depth + 1)) {
      // Disjoint flag may not longer hold.
      I->dropPoisonGeneratingFlags();
      return I;
    }

    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Q, Depth);

    // If the client is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(VTy, Known.One);

    // If all of the demanded bits are known zero on one side, return the other.
    // These bits cannot contribute to the result of the 'or'.
    if (DemandedMask.isSubsetOf(LHSKnown.One | RHSKnown.Zero))
      return I->getOperand(0);
    if (DemandedMask.isSubsetOf(RHSKnown.One | LHSKnown.Zero))
      return I->getOperand(1);

    // If the RHS is a constant, see if we can simplify it.
    if (ShrinkDemandedConstant(I, 1, DemandedMask))
      return I;

    // Infer disjoint flag if no common bits are set.
    if (!cast<PossiblyDisjointInst>(I)->isDisjoint()) {
      WithCache<const Value *> LHSCache(I->getOperand(0), LHSKnown),
          RHSCache(I->getOperand(1), RHSKnown);
      if (haveNoCommonBitsSet(LHSCache, RHSCache, Q)) {
        cast<PossiblyDisjointInst>(I)->setIsDisjoint(true);
        return I;
      }
    }

    break;
  }
  case Instruction::Xor: {
    if (SimplifyDemandedBits(I, 1, DemandedMask, RHSKnown, Q, Depth + 1) ||
        SimplifyDemandedBits(I, 0, DemandedMask, LHSKnown, Q, Depth + 1))
      return I;
    Value *LHS, *RHS;
    if (DemandedMask == 1 &&
        match(I->getOperand(0), m_Intrinsic<Intrinsic::ctpop>(m_Value(LHS))) &&
        match(I->getOperand(1), m_Intrinsic<Intrinsic::ctpop>(m_Value(RHS)))) {
      // (ctpop(X) ^ ctpop(Y)) & 1 --> ctpop(X^Y) & 1
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);
      auto *Xor = Builder.CreateXor(LHS, RHS);
      return Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, Xor);
    }

    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Q, Depth);

    // If the client is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(VTy, Known.One);

    // If all of the demanded bits are known zero on one side, return the other.
    // These bits cannot contribute to the result of the 'xor'.
    if (DemandedMask.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);
    if (DemandedMask.isSubsetOf(LHSKnown.Zero))
      return I->getOperand(1);

    // If all of the demanded bits are known to be zero on one side or the
    // other, turn this into an *inclusive* or.
    //    e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0
    if (DemandedMask.isSubsetOf(RHSKnown.Zero | LHSKnown.Zero)) {
      Instruction *Or =
          BinaryOperator::CreateOr(I->getOperand(0), I->getOperand(1));
      if (DemandedMask.isAllOnes())
        cast<PossiblyDisjointInst>(Or)->setIsDisjoint(true);
      Or->takeName(I);
      return InsertNewInstWith(Or, I->getIterator());
    }

    // If all of the demanded bits on one side are known, and all of the set
    // bits on that side are also known to be set on the other side, turn this
    // into an AND, as we know the bits will be cleared.
    //    e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
    if (DemandedMask.isSubsetOf(RHSKnown.Zero|RHSKnown.One) &&
        RHSKnown.One.isSubsetOf(LHSKnown.One)) {
      Constant *AndC = Constant::getIntegerValue(VTy,
                                                 ~RHSKnown.One & DemandedMask);
      Instruction *And = BinaryOperator::CreateAnd(I->getOperand(0), AndC);
      return InsertNewInstWith(And, I->getIterator());
    }

    // If the RHS is a constant, see if we can change it. Don't alter a -1
    // constant because that's a canonical 'not' op, and that is better for
    // combining, SCEV, and codegen.
    const APInt *C;
    if (match(I->getOperand(1), m_APInt(C)) && !C->isAllOnes()) {
      if ((*C | ~DemandedMask).isAllOnes()) {
        // Force bits to 1 to create a 'not' op.
        I->setOperand(1, ConstantInt::getAllOnesValue(VTy));
        return I;
      }
      // If we can't turn this into a 'not', try to shrink the constant.
      if (ShrinkDemandedConstant(I, 1, DemandedMask))
        return I;
    }

    // If our LHS is an 'and' and if it has one use, and if any of the bits we
    // are flipping are known to be set, then the xor is just resetting those
    // bits to zero.  We can just knock out bits from the 'and' and the 'xor',
    // simplifying both of them.
    if (Instruction *LHSInst = dyn_cast<Instruction>(I->getOperand(0))) {
      ConstantInt *AndRHS, *XorRHS;
      if (LHSInst->getOpcode() == Instruction::And && LHSInst->hasOneUse() &&
          match(I->getOperand(1), m_ConstantInt(XorRHS)) &&
          match(LHSInst->getOperand(1), m_ConstantInt(AndRHS)) &&
          (LHSKnown.One & RHSKnown.One & DemandedMask) != 0) {
        APInt NewMask = ~(LHSKnown.One & RHSKnown.One & DemandedMask);

        Constant *AndC = ConstantInt::get(VTy, NewMask & AndRHS->getValue());
        Instruction *NewAnd = BinaryOperator::CreateAnd(I->getOperand(0), AndC);
        InsertNewInstWith(NewAnd, I->getIterator());

        Constant *XorC = ConstantInt::get(VTy, NewMask & XorRHS->getValue());
        Instruction *NewXor = BinaryOperator::CreateXor(NewAnd, XorC);
        return InsertNewInstWith(NewXor, I->getIterator());
      }
    }
    break;
  }
  case Instruction::Select: {
    if (SimplifyDemandedBits(I, 2, DemandedMask, RHSKnown, Q, Depth + 1) ||
        SimplifyDemandedBits(I, 1, DemandedMask, LHSKnown, Q, Depth + 1))
      return I;

    // If the operands are constants, see if we can simplify them.
    // This is similar to ShrinkDemandedConstant, but for a select we want to
    // try to keep the selected constants the same as icmp value constants, if
    // we can. This helps not break apart (or helps put back together)
    // canonical patterns like min and max.
    auto CanonicalizeSelectConstant = [](Instruction *I, unsigned OpNo,
                                         const APInt &DemandedMask) {
      const APInt *SelC;
      if (!match(I->getOperand(OpNo), m_APInt(SelC)))
        return false;

      // Get the constant out of the ICmp, if there is one.
      // Only try this when exactly 1 operand is a constant (if both operands
      // are constant, the icmp should eventually simplify). Otherwise, we may
      // invert the transform that reduces set bits and infinite-loop.
      Value *X;
      const APInt *CmpC;
      if (!match(I->getOperand(0), m_ICmp(m_Value(X), m_APInt(CmpC))) ||
          isa<Constant>(X) || CmpC->getBitWidth() != SelC->getBitWidth())
        return ShrinkDemandedConstant(I, OpNo, DemandedMask);

      // If the constant is already the same as the ICmp, leave it as-is.
      if (*CmpC == *SelC)
        return false;
      // If the constants are not already the same, but can be with the demand
      // mask, use the constant value from the ICmp.
      if ((*CmpC & DemandedMask) == (*SelC & DemandedMask)) {
        I->setOperand(OpNo, ConstantInt::get(I->getType(), *CmpC));
        return true;
      }
      return ShrinkDemandedConstant(I, OpNo, DemandedMask);
    };
    if (CanonicalizeSelectConstant(I, 1, DemandedMask) ||
        CanonicalizeSelectConstant(I, 2, DemandedMask))
      return I;

    // Only known if known in both the LHS and RHS.
    adjustKnownBitsForSelectArm(LHSKnown, I->getOperand(0), I->getOperand(1),
                                /*Invert=*/false, Q, Depth);
    adjustKnownBitsForSelectArm(RHSKnown, I->getOperand(0), I->getOperand(2),
                                /*Invert=*/true, Q, Depth);
    Known = LHSKnown.intersectWith(RHSKnown);
    break;
  }
  case Instruction::Trunc: {
    // If we do not demand the high bits of a right-shifted and truncated value,
    // then we may be able to truncate it before the shift.
    Value *X;
    const APInt *C;
    if (match(I->getOperand(0), m_OneUse(m_LShr(m_Value(X), m_APInt(C))))) {
      // The shift amount must be valid (not poison) in the narrow type, and
      // it must not be greater than the high bits demanded of the result.
      if (C->ult(VTy->getScalarSizeInBits()) &&
          C->ule(DemandedMask.countl_zero())) {
        // trunc (lshr X, C) --> lshr (trunc X), C
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(I);
        Value *Trunc = Builder.CreateTrunc(X, VTy);
        return Builder.CreateLShr(Trunc, C->getZExtValue());
      }
    }
  }
    [[fallthrough]];
  case Instruction::ZExt: {
    unsigned SrcBitWidth = I->getOperand(0)->getType()->getScalarSizeInBits();

    APInt InputDemandedMask = DemandedMask.zextOrTrunc(SrcBitWidth);
    KnownBits InputKnown(SrcBitWidth);
    if (SimplifyDemandedBits(I, 0, InputDemandedMask, InputKnown, Q,
                             Depth + 1)) {
      // For zext nneg, we may have dropped the instruction which made the
      // input non-negative.
      I->dropPoisonGeneratingFlags();
      return I;
    }
    assert(InputKnown.getBitWidth() == SrcBitWidth && "Src width changed?");
    if (I->getOpcode() == Instruction::ZExt && I->hasNonNeg() &&
        !InputKnown.isNegative())
      InputKnown.makeNonNegative();
    Known = InputKnown.zextOrTrunc(BitWidth);

    break;
  }
  case Instruction::SExt: {
    // Compute the bits in the result that are not present in the input.
    unsigned SrcBitWidth = I->getOperand(0)->getType()->getScalarSizeInBits();

    APInt InputDemandedBits = DemandedMask.trunc(SrcBitWidth);

    // If any of the sign extended bits are demanded, we know that the sign
    // bit is demanded.
    if (DemandedMask.getActiveBits() > SrcBitWidth)
      InputDemandedBits.setBit(SrcBitWidth-1);

    KnownBits InputKnown(SrcBitWidth);
    if (SimplifyDemandedBits(I, 0, InputDemandedBits, InputKnown, Q, Depth + 1))
      return I;

    // If the input sign bit is known zero, or if the NewBits are not demanded
    // convert this into a zero extension.
    if (InputKnown.isNonNegative() ||
        DemandedMask.getActiveBits() <= SrcBitWidth) {
      // Convert to ZExt cast.
      CastInst *NewCast = new ZExtInst(I->getOperand(0), VTy);
      NewCast->takeName(I);
      return InsertNewInstWith(NewCast, I->getIterator());
    }

    // If the sign bit of the input is known set or clear, then we know the
    // top bits of the result.
    Known = InputKnown.sext(BitWidth);
    break;
  }
  case Instruction::Add: {
    if ((DemandedMask & 1) == 0) {
      // If we do not need the low bit, try to convert bool math to logic:
      // add iN (zext i1 X), (sext i1 Y) --> sext (~X & Y) to iN
      Value *X, *Y;
      if (match(I, m_c_Add(m_OneUse(m_ZExt(m_Value(X))),
                           m_OneUse(m_SExt(m_Value(Y))))) &&
          X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType()) {
        // Truth table for inputs and output signbits:
        //       X:0 | X:1
        //      ----------
        // Y:0  |  0 | 0 |
        // Y:1  | -1 | 0 |
        //      ----------
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(I);
        Value *AndNot = Builder.CreateAnd(Builder.CreateNot(X), Y);
        return Builder.CreateSExt(AndNot, VTy);
      }

      // add iN (sext i1 X), (sext i1 Y) --> sext (X | Y) to iN
      if (match(I, m_Add(m_SExt(m_Value(X)), m_SExt(m_Value(Y)))) &&
          X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() &&
          (I->getOperand(0)->hasOneUse() || I->getOperand(1)->hasOneUse())) {

        // Truth table for inputs and output signbits:
        //       X:0 | X:1
        //      -----------
        // Y:0  | -1 | -1 |
        // Y:1  | -1 |  0 |
        //      -----------
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(I);
        Value *Or = Builder.CreateOr(X, Y);
        return Builder.CreateSExt(Or, VTy);
      }
    }

    // Right fill the mask of bits for the operands to demand the most
    // significant bit and all those below it.
    unsigned NLZ = DemandedMask.countl_zero();
    APInt DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ);
    if (ShrinkDemandedConstant(I, 1, DemandedFromOps) ||
        SimplifyDemandedBits(I, 1, DemandedFromOps, RHSKnown, Q, Depth + 1))
      return disableWrapFlagsBasedOnUnusedHighBits(I, NLZ);

    // If low order bits are not demanded and known to be zero in one operand,
    // then we don't need to demand them from the other operand, since they
    // can't cause overflow into any bits that are demanded in the result.
    unsigned NTZ = (~DemandedMask & RHSKnown.Zero).countr_one();
    APInt DemandedFromLHS = DemandedFromOps;
    DemandedFromLHS.clearLowBits(NTZ);
    if (ShrinkDemandedConstant(I, 0, DemandedFromLHS) ||
        SimplifyDemandedBits(I, 0, DemandedFromLHS, LHSKnown, Q, Depth + 1))
      return disableWrapFlagsBasedOnUnusedHighBits(I, NLZ);

    // If we are known to be adding zeros to every bit below
    // the highest demanded bit, we just return the other side.
    if (DemandedFromOps.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);
    if (DemandedFromOps.isSubsetOf(LHSKnown.Zero))
      return I->getOperand(1);

    // (add X, C) --> (xor X, C) IFF C is equal to the top bit of the DemandMask
    {
      const APInt *C;
      if (match(I->getOperand(1), m_APInt(C)) &&
          C->isOneBitSet(DemandedMask.getActiveBits() - 1)) {
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(I);
        return Builder.CreateXor(I->getOperand(0), ConstantInt::get(VTy, *C));
      }
    }

    // Otherwise just compute the known bits of the result.
    bool NSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
    bool NUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
    Known = KnownBits::add(LHSKnown, RHSKnown, NSW, NUW);
    break;
  }
  case Instruction::Sub: {
    // Right fill the mask of bits for the operands to demand the most
    // significant bit and all those below it.
    unsigned NLZ = DemandedMask.countl_zero();
    APInt DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ);
    if (ShrinkDemandedConstant(I, 1, DemandedFromOps) ||
        SimplifyDemandedBits(I, 1, DemandedFromOps, RHSKnown, Q, Depth + 1))
      return disableWrapFlagsBasedOnUnusedHighBits(I, NLZ);

    // If low order bits are not demanded and are known to be zero in RHS,
    // then we don't need to demand them from LHS, since they can't cause a
    // borrow from any bits that are demanded in the result.
    unsigned NTZ = (~DemandedMask & RHSKnown.Zero).countr_one();
    APInt DemandedFromLHS = DemandedFromOps;
    DemandedFromLHS.clearLowBits(NTZ);
    if (ShrinkDemandedConstant(I, 0, DemandedFromLHS) ||
        SimplifyDemandedBits(I, 0, DemandedFromLHS, LHSKnown, Q, Depth + 1))
      return disableWrapFlagsBasedOnUnusedHighBits(I, NLZ);

    // If we are known to be subtracting zeros from every bit below
    // the highest demanded bit, we just return the other side.
    if (DemandedFromOps.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);
    // We can't do this with the LHS for subtraction, unless we are only
    // demanding the LSB.
    if (DemandedFromOps.isOne() && DemandedFromOps.isSubsetOf(LHSKnown.Zero))
      return I->getOperand(1);

    // Canonicalize sub mask, X -> ~X
    const APInt *LHSC;
    if (match(I->getOperand(0), m_LowBitMask(LHSC)) &&
        DemandedFromOps.isSubsetOf(*LHSC)) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);
      return Builder.CreateNot(I->getOperand(1));
    }

    // Otherwise just compute the known bits of the result.
    bool NSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
    bool NUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
    Known = KnownBits::sub(LHSKnown, RHSKnown, NSW, NUW);
    break;
  }
  case Instruction::Mul: {
    APInt DemandedFromOps;
    if (simplifyOperandsBasedOnUnusedHighBits(DemandedFromOps))
      return I;

    if (DemandedMask.isPowerOf2()) {
      // The LSB of X*Y is set only if (X & 1) == 1 and (Y & 1) == 1.
      // If we demand exactly one bit N and we have "X * (C' << N)" where C' is
      // odd (has LSB set), then the left-shifted low bit of X is the answer.
      unsigned CTZ = DemandedMask.countr_zero();
      const APInt *C;
      if (match(I->getOperand(1), m_APInt(C)) && C->countr_zero() == CTZ) {
        Constant *ShiftC = ConstantInt::get(VTy, CTZ);
        Instruction *Shl = BinaryOperator::CreateShl(I->getOperand(0), ShiftC);
        return InsertNewInstWith(Shl, I->getIterator());
      }
    }
    // For a squared value "X * X", the bottom 2 bits are 0 and X[0] because:
    // X * X is odd iff X is odd.
    // 'Quadratic Reciprocity': X * X -> 0 for bit[1]
    if (I->getOperand(0) == I->getOperand(1) && DemandedMask.ult(4)) {
      Constant *One = ConstantInt::get(VTy, 1);
      Instruction *And1 = BinaryOperator::CreateAnd(I->getOperand(0), One);
      return InsertNewInstWith(And1, I->getIterator());
    }

    llvm::computeKnownBits(I, Known, Q, Depth);
    break;
  }
  case Instruction::Shl: {
    const APInt *SA;
    if (match(I->getOperand(1), m_APInt(SA))) {
      const APInt *ShrAmt;
      if (match(I->getOperand(0), m_Shr(m_Value(), m_APInt(ShrAmt))))
        if (Instruction *Shr = dyn_cast<Instruction>(I->getOperand(0)))
          if (Value *R = simplifyShrShlDemandedBits(Shr, *ShrAmt, I, *SA,
                                                    DemandedMask, Known))
            return R;

      // Do not simplify if shl is part of funnel-shift pattern
      if (I->hasOneUse()) {
        auto *Inst = dyn_cast<Instruction>(I->user_back());
        if (Inst && Inst->getOpcode() == BinaryOperator::Or) {
          if (auto Opt = convertOrOfShiftsToFunnelShift(*Inst)) {
            auto [IID, FShiftArgs] = *Opt;
            if ((IID == Intrinsic::fshl || IID == Intrinsic::fshr) &&
                FShiftArgs[0] == FShiftArgs[1]) {
              llvm::computeKnownBits(I, Known, Q, Depth);
              break;
            }
          }
        }
      }

      // We only want bits that already match the signbit then we don't
      // need to shift.
      uint64_t ShiftAmt = SA->getLimitedValue(BitWidth - 1);
      if (DemandedMask.countr_zero() >= ShiftAmt) {
        if (I->hasNoSignedWrap()) {
          unsigned NumHiDemandedBits = BitWidth - DemandedMask.countr_zero();
          unsigned SignBits =
              ComputeNumSignBits(I->getOperand(0), Q.CxtI, Depth + 1);
          if (SignBits > ShiftAmt && SignBits - ShiftAmt >= NumHiDemandedBits)
            return I->getOperand(0);
        }

        // If we can pre-shift a right-shifted constant to the left without
        // losing any high bits and we don't demand the low bits, then eliminate
        // the left-shift:
        // (C >> X) << LeftShiftAmtC --> (C << LeftShiftAmtC) >> X
        Value *X;
        Constant *C;
        if (match(I->getOperand(0), m_LShr(m_ImmConstant(C), m_Value(X)))) {
          Constant *LeftShiftAmtC = ConstantInt::get(VTy, ShiftAmt);
          Constant *NewC = ConstantFoldBinaryOpOperands(Instruction::Shl, C,
                                                        LeftShiftAmtC, DL);
          if (ConstantFoldBinaryOpOperands(Instruction::LShr, NewC,
                                           LeftShiftAmtC, DL) == C) {
            Instruction *Lshr = BinaryOperator::CreateLShr(NewC, X);
            return InsertNewInstWith(Lshr, I->getIterator());
          }
        }
      }

      APInt DemandedMaskIn(DemandedMask.lshr(ShiftAmt));

      // If the shift is NUW/NSW, then it does demand the high bits.
      ShlOperator *IOp = cast<ShlOperator>(I);
      if (IOp->hasNoSignedWrap())
        DemandedMaskIn.setHighBits(ShiftAmt+1);
      else if (IOp->hasNoUnsignedWrap())
        DemandedMaskIn.setHighBits(ShiftAmt);

      if (SimplifyDemandedBits(I, 0, DemandedMaskIn, Known, Q, Depth + 1))
        return I;

      Known = KnownBits::shl(Known,
                             KnownBits::makeConstant(APInt(BitWidth, ShiftAmt)),
                             /* NUW */ IOp->hasNoUnsignedWrap(),
                             /* NSW */ IOp->hasNoSignedWrap());
    } else {
      // This is a variable shift, so we can't shift the demand mask by a known
      // amount. But if we are not demanding high bits, then we are not
      // demanding those bits from the pre-shifted operand either.
      if (unsigned CTLZ = DemandedMask.countl_zero()) {
        APInt DemandedFromOp(APInt::getLowBitsSet(BitWidth, BitWidth - CTLZ));
        if (SimplifyDemandedBits(I, 0, DemandedFromOp, Known, Q, Depth + 1)) {
          // We can't guarantee that nsw/nuw hold after simplifying the operand.
          I->dropPoisonGeneratingFlags();
          return I;
        }
      }
      llvm::computeKnownBits(I, Known, Q, Depth);
    }
    break;
  }
  case Instruction::LShr: {
    const APInt *SA;
    if (match(I->getOperand(1), m_APInt(SA))) {
      uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1);

      // Do not simplify if lshr is part of funnel-shift pattern
      if (I->hasOneUse()) {
        auto *Inst = dyn_cast<Instruction>(I->user_back());
        if (Inst && Inst->getOpcode() == BinaryOperator::Or) {
          if (auto Opt = convertOrOfShiftsToFunnelShift(*Inst)) {
            auto [IID, FShiftArgs] = *Opt;
            if ((IID == Intrinsic::fshl || IID == Intrinsic::fshr) &&
                FShiftArgs[0] == FShiftArgs[1]) {
              llvm::computeKnownBits(I, Known, Q, Depth);
              break;
            }
          }
        }
      }

      // If we are just demanding the shifted sign bit and below, then this can
      // be treated as an ASHR in disguise.
      if (DemandedMask.countl_zero() >= ShiftAmt) {
        // If we only want bits that already match the signbit then we don't
        // need to shift.
        unsigned NumHiDemandedBits = BitWidth - DemandedMask.countr_zero();
        unsigned SignBits =
            ComputeNumSignBits(I->getOperand(0), Q.CxtI, Depth + 1);
        if (SignBits >= NumHiDemandedBits)
          return I->getOperand(0);

        // If we can pre-shift a left-shifted constant to the right without
        // losing any low bits (we already know we don't demand the high bits),
        // then eliminate the right-shift:
        // (C << X) >> RightShiftAmtC --> (C >> RightShiftAmtC) << X
        Value *X;
        Constant *C;
        if (match(I->getOperand(0), m_Shl(m_ImmConstant(C), m_Value(X)))) {
          Constant *RightShiftAmtC = ConstantInt::get(VTy, ShiftAmt);
          Constant *NewC = ConstantFoldBinaryOpOperands(Instruction::LShr, C,
                                                        RightShiftAmtC, DL);
          if (ConstantFoldBinaryOpOperands(Instruction::Shl, NewC,
                                           RightShiftAmtC, DL) == C) {
            Instruction *Shl = BinaryOperator::CreateShl(NewC, X);
            return InsertNewInstWith(Shl, I->getIterator());
          }
        }

        const APInt *Factor;
        if (match(I->getOperand(0),
                  m_OneUse(m_Mul(m_Value(X), m_APInt(Factor)))) &&
            Factor->countr_zero() >= ShiftAmt) {
          BinaryOperator *Mul = BinaryOperator::CreateMul(
              X, ConstantInt::get(X->getType(), Factor->lshr(ShiftAmt)));
          return InsertNewInstWith(Mul, I->getIterator());
        }
      }

      // Unsigned shift right.
      APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt));
      if (SimplifyDemandedBits(I, 0, DemandedMaskIn, Known, Q, Depth + 1)) {
        // exact flag may not longer hold.
        I->dropPoisonGeneratingFlags();
        return I;
      }
      Known >>= ShiftAmt;
      if (ShiftAmt)
        Known.Zero.setHighBits(ShiftAmt);  // high bits known zero.
      break;
    }
    if (Value *V =
            simplifyShiftSelectingPackedElement(I, DemandedMask, *this, Depth))
      return V;

    llvm::computeKnownBits(I, Known, Q, Depth);
    break;
  }
  case Instruction::AShr: {
    unsigned SignBits = ComputeNumSignBits(I->getOperand(0), Q.CxtI, Depth + 1);

    // If we only want bits that already match the signbit then we don't need
    // to shift.
    unsigned NumHiDemandedBits = BitWidth - DemandedMask.countr_zero();
    if (SignBits >= NumHiDemandedBits)
      return I->getOperand(0);

    // If this is an arithmetic shift right and only the low-bit is set, we can
    // always convert this into a logical shr, even if the shift amount is
    // variable.  The low bit of the shift cannot be an input sign bit unless
    // the shift amount is >= the size of the datatype, which is undefined.
    if (DemandedMask.isOne()) {
      // Perform the logical shift right.
      Instruction *NewVal = BinaryOperator::CreateLShr(
                        I->getOperand(0), I->getOperand(1), I->getName());
      return InsertNewInstWith(NewVal, I->getIterator());
    }

    const APInt *SA;
    if (match(I->getOperand(1), m_APInt(SA))) {
      uint32_t ShiftAmt = SA->getLimitedValue(BitWidth-1);

      // Signed shift right.
      APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt));
      // If any of the bits being shifted in are demanded, then we should set
      // the sign bit as demanded.
      bool ShiftedInBitsDemanded = DemandedMask.countl_zero() < ShiftAmt;
      if (ShiftedInBitsDemanded)
        DemandedMaskIn.setSignBit();
      if (SimplifyDemandedBits(I, 0, DemandedMaskIn, Known, Q, Depth + 1)) {
        // exact flag may not longer hold.
        I->dropPoisonGeneratingFlags();
        return I;
      }

      // If the input sign bit is known to be zero, or if none of the shifted in
      // bits are demanded, turn this into an unsigned shift right.
      if (Known.Zero[BitWidth - 1] || !ShiftedInBitsDemanded) {
        BinaryOperator *LShr = BinaryOperator::CreateLShr(I->getOperand(0),
                                                          I->getOperand(1));
        LShr->setIsExact(cast<BinaryOperator>(I)->isExact());
        LShr->takeName(I);
        return InsertNewInstWith(LShr, I->getIterator());
      }

      Known = KnownBits::ashr(
          Known, KnownBits::makeConstant(APInt(BitWidth, ShiftAmt)),
          ShiftAmt != 0, I->isExact());
    } else {
      llvm::computeKnownBits(I, Known, Q, Depth);
    }
    break;
  }
  case Instruction::UDiv: {
    // UDiv doesn't demand low bits that are zero in the divisor.
    const APInt *SA;
    if (match(I->getOperand(1), m_APInt(SA))) {
      // TODO: Take the demanded mask of the result into account.
      unsigned RHSTrailingZeros = SA->countr_zero();
      APInt DemandedMaskIn =
          APInt::getHighBitsSet(BitWidth, BitWidth - RHSTrailingZeros);
      if (SimplifyDemandedBits(I, 0, DemandedMaskIn, LHSKnown, Q, Depth + 1)) {
        // We can't guarantee that "exact" is still true after changing the
        // the dividend.
        I->dropPoisonGeneratingFlags();
        return I;
      }

      Known = KnownBits::udiv(LHSKnown, KnownBits::makeConstant(*SA),
                              cast<BinaryOperator>(I)->isExact());
    } else {
      llvm::computeKnownBits(I, Known, Q, Depth);
    }
    break;
  }
  case Instruction::SRem: {
    const APInt *Rem;
    if (match(I->getOperand(1), m_APInt(Rem)) && Rem->isPowerOf2()) {
      if (DemandedMask.ult(*Rem)) // srem won't affect demanded bits
        return I->getOperand(0);

      APInt LowBits = *Rem - 1;
      APInt Mask2 = LowBits | APInt::getSignMask(BitWidth);
      if (SimplifyDemandedBits(I, 0, Mask2, LHSKnown, Q, Depth + 1))
        return I;
      Known = KnownBits::srem(LHSKnown, KnownBits::makeConstant(*Rem));
      break;
    }

    llvm::computeKnownBits(I, Known, Q, Depth);
    break;
  }
  case Instruction::Call: {
    bool KnownBitsComputed = false;
    if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
      switch (II->getIntrinsicID()) {
      case Intrinsic::abs: {
        if (DemandedMask == 1)
          return II->getArgOperand(0);
        break;
      }
      case Intrinsic::ctpop: {
        // Checking if the number of clear bits is odd (parity)? If the type has
        // an even number of bits, that's the same as checking if the number of
        // set bits is odd, so we can eliminate the 'not' op.
        Value *X;
        if (DemandedMask == 1 && VTy->getScalarSizeInBits() % 2 == 0 &&
            match(II->getArgOperand(0), m_Not(m_Value(X)))) {
          Function *Ctpop = Intrinsic::getOrInsertDeclaration(
              II->getModule(), Intrinsic::ctpop, VTy);
          return InsertNewInstWith(CallInst::Create(Ctpop, {X}), I->getIterator());
        }
        break;
      }
      case Intrinsic::bswap: {
        // If the only bits demanded come from one byte of the bswap result,
        // just shift the input byte into position to eliminate the bswap.
        unsigned NLZ = DemandedMask.countl_zero();
        unsigned NTZ = DemandedMask.countr_zero();

        // Round NTZ down to the next byte.  If we have 11 trailing zeros, then
        // we need all the bits down to bit 8.  Likewise, round NLZ.  If we
        // have 14 leading zeros, round to 8.
        NLZ = alignDown(NLZ, 8);
        NTZ = alignDown(NTZ, 8);
        // If we need exactly one byte, we can do this transformation.
        if (BitWidth - NLZ - NTZ == 8) {
          // Replace this with either a left or right shift to get the byte into
          // the right place.
          Instruction *NewVal;
          if (NLZ > NTZ)
            NewVal = BinaryOperator::CreateLShr(
                II->getArgOperand(0), ConstantInt::get(VTy, NLZ - NTZ));
          else
            NewVal = BinaryOperator::CreateShl(
                II->getArgOperand(0), ConstantInt::get(VTy, NTZ - NLZ));
          NewVal->takeName(I);
          return InsertNewInstWith(NewVal, I->getIterator());
        }
        break;
      }
      case Intrinsic::ptrmask: {
        unsigned MaskWidth = I->getOperand(1)->getType()->getScalarSizeInBits();
        RHSKnown = KnownBits(MaskWidth);
        // If either the LHS or the RHS are Zero, the result is zero.
        if (SimplifyDemandedBits(I, 0, DemandedMask, LHSKnown, Q, Depth + 1) ||
            SimplifyDemandedBits(
                I, 1, (DemandedMask & ~LHSKnown.Zero).zextOrTrunc(MaskWidth),
                RHSKnown, Q, Depth + 1))
          return I;

        // TODO: Should be 1-extend
        RHSKnown = RHSKnown.anyextOrTrunc(BitWidth);

        Known = LHSKnown & RHSKnown;
        KnownBitsComputed = true;

        // If the client is only demanding bits we know to be zero, return
        // `llvm.ptrmask(p, 0)`. We can't return `null` here due to pointer
        // provenance, but making the mask zero will be easily optimizable in
        // the backend.
        if (DemandedMask.isSubsetOf(Known.Zero) &&
            !match(I->getOperand(1), m_Zero()))
          return replaceOperand(
              *I, 1, Constant::getNullValue(I->getOperand(1)->getType()));

        // Mask in demanded space does nothing.
        // NOTE: We may have attributes associated with the return value of the
        // llvm.ptrmask intrinsic that will be lost when we just return the
        // operand. We should try to preserve them.
        if (DemandedMask.isSubsetOf(RHSKnown.One | LHSKnown.Zero))
          return I->getOperand(0);

        // If the RHS is a constant, see if we can simplify it.
        if (ShrinkDemandedConstant(
                I, 1, (DemandedMask & ~LHSKnown.Zero).zextOrTrunc(MaskWidth)))
          return I;

        // Combine:
        // (ptrmask (getelementptr i8, ptr p, imm i), imm mask)
        //   -> (ptrmask (getelementptr i8, ptr p, imm (i & mask)), imm mask)
        // where only the low bits known to be zero in the pointer are changed
        Value *InnerPtr;
        uint64_t GEPIndex;
        uint64_t PtrMaskImmediate;
        if (match(I, m_Intrinsic<Intrinsic::ptrmask>(
                         m_PtrAdd(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
                         m_ConstantInt(PtrMaskImmediate)))) {

          LHSKnown = computeKnownBits(InnerPtr, I, Depth + 1);
          if (!LHSKnown.isZero()) {
            const unsigned trailingZeros = LHSKnown.countMinTrailingZeros();
            uint64_t PointerAlignBits = (uint64_t(1) << trailingZeros) - 1;

            uint64_t HighBitsGEPIndex = GEPIndex & ~PointerAlignBits;
            uint64_t MaskedLowBitsGEPIndex =
                GEPIndex & PointerAlignBits & PtrMaskImmediate;

            uint64_t MaskedGEPIndex = HighBitsGEPIndex | MaskedLowBitsGEPIndex;

            if (MaskedGEPIndex != GEPIndex) {
              auto *GEP = cast<GEPOperator>(II->getArgOperand(0));
              Builder.SetInsertPoint(I);
              Type *GEPIndexType =
                  DL.getIndexType(GEP->getPointerOperand()->getType());
              Value *MaskedGEP = Builder.CreateGEP(
                  GEP->getSourceElementType(), InnerPtr,
                  ConstantInt::get(GEPIndexType, MaskedGEPIndex),
                  GEP->getName(), GEP->isInBounds());

              replaceOperand(*I, 0, MaskedGEP);
              return I;
            }
          }
        }

        break;
      }

      case Intrinsic::fshr:
      case Intrinsic::fshl: {
        const APInt *SA;
        if (!match(I->getOperand(2), m_APInt(SA)))
          break;

        // Normalize to funnel shift left. APInt shifts of BitWidth are well-
        // defined, so no need to special-case zero shifts here.
        uint64_t ShiftAmt = SA->urem(BitWidth);
        if (II->getIntrinsicID() == Intrinsic::fshr)
          ShiftAmt = BitWidth - ShiftAmt;

        APInt DemandedMaskLHS(DemandedMask.lshr(ShiftAmt));
        APInt DemandedMaskRHS(DemandedMask.shl(BitWidth - ShiftAmt));
        if (I->getOperand(0) != I->getOperand(1)) {
          if (SimplifyDemandedBits(I, 0, DemandedMaskLHS, LHSKnown, Q,
                                   Depth + 1) ||
              SimplifyDemandedBits(I, 1, DemandedMaskRHS, RHSKnown, Q,
                                   Depth + 1)) {
            // Range attribute or metadata may no longer hold.
            I->dropPoisonGeneratingAnnotations();
            return I;
          }
        } else { // fshl is a rotate
          // Avoid converting rotate into funnel shift.
          // Only simplify if one operand is constant.
          LHSKnown = computeKnownBits(I->getOperand(0), I, Depth + 1);
          if (DemandedMaskLHS.isSubsetOf(LHSKnown.Zero | LHSKnown.One) &&
              !match(I->getOperand(0), m_SpecificInt(LHSKnown.One))) {
            replaceOperand(*I, 0, Constant::getIntegerValue(VTy, LHSKnown.One));
            return I;
          }

          RHSKnown = computeKnownBits(I->getOperand(1), I, Depth + 1);
          if (DemandedMaskRHS.isSubsetOf(RHSKnown.Zero | RHSKnown.One) &&
              !match(I->getOperand(1), m_SpecificInt(RHSKnown.One))) {
            replaceOperand(*I, 1, Constant::getIntegerValue(VTy, RHSKnown.One));
            return I;
          }
        }

        LHSKnown <<= ShiftAmt;
        RHSKnown >>= BitWidth - ShiftAmt;
        Known = LHSKnown.unionWith(RHSKnown);
        KnownBitsComputed = true;
        break;
      }
      case Intrinsic::umax: {
        // UMax(A, C) == A if ...
        // The lowest non-zero bit of DemandMask is higher than the highest
        // non-zero bit of C.
        const APInt *C;
        unsigned CTZ = DemandedMask.countr_zero();
        if (match(II->getArgOperand(1), m_APInt(C)) &&
            CTZ >= C->getActiveBits())
          return II->getArgOperand(0);
        break;
      }
      case Intrinsic::umin: {
        // UMin(A, C) == A if ...
        // The lowest non-zero bit of DemandMask is higher than the highest
        // non-one bit of C.
        // This comes from using DeMorgans on the above umax example.
        const APInt *C;
        unsigned CTZ = DemandedMask.countr_zero();
        if (match(II->getArgOperand(1), m_APInt(C)) &&
            CTZ >= C->getBitWidth() - C->countl_one())
          return II->getArgOperand(0);
        break;
      }
      default: {
        // Handle target specific intrinsics
        std::optional<Value *> V = targetSimplifyDemandedUseBitsIntrinsic(
            *II, DemandedMask, Known, KnownBitsComputed);
        if (V)
          return *V;
        break;
      }
      }
    }

    if (!KnownBitsComputed)
      llvm::computeKnownBits(I, Known, Q, Depth);
    break;
  }
  }

  if (I->getType()->isPointerTy()) {
    Align Alignment = I->getPointerAlignment(DL);
    Known.Zero.setLowBits(Log2(Alignment));
  }

  // If the client is only demanding bits that we know, return the known
  // constant. We can't directly simplify pointers as a constant because of
  // pointer provenance.
  // TODO: We could return `(inttoptr const)` for pointers.
  if (!I->getType()->isPointerTy() &&
      DemandedMask.isSubsetOf(Known.Zero | Known.One))
    return Constant::getIntegerValue(VTy, Known.One);

  if (VerifyKnownBits) {
    KnownBits ReferenceKnown = llvm::computeKnownBits(I, Q, Depth);
    if (Known != ReferenceKnown) {
      errs() << "Mismatched known bits for " << *I << " in "
             << I->getFunction()->getName() << "\n";
      errs() << "computeKnownBits(): " << ReferenceKnown << "\n";
      errs() << "SimplifyDemandedBits(): " << Known << "\n";
      std::abort();
    }
  }

  return nullptr;
}

/// Helper routine of SimplifyDemandedUseBits. It computes Known
/// bits. It also tries to handle simplifications that can be done based on
/// DemandedMask, but without modifying the Instruction.
Value *InstCombinerImpl::SimplifyMultipleUseDemandedBits(
    Instruction *I, const APInt &DemandedMask, KnownBits &Known,
    const SimplifyQuery &Q, unsigned Depth) {
  unsigned BitWidth = DemandedMask.getBitWidth();
  Type *ITy = I->getType();

  KnownBits LHSKnown(BitWidth);
  KnownBits RHSKnown(BitWidth);

  // Despite the fact that we can't simplify this instruction in all User's
  // context, we can at least compute the known bits, and we can
  // do simplifications that apply to *just* the one user if we know that
  // this instruction has a simpler value in that context.
  switch (I->getOpcode()) {
  case Instruction::And: {
    llvm::computeKnownBits(I->getOperand(1), RHSKnown, Q, Depth + 1);
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Q, Depth + 1);
    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Q, Depth);
    computeKnownBitsFromContext(I, Known, Q, Depth);

    // If the client is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(ITy, Known.One);

    // If all of the demanded bits are known 1 on one side, return the other.
    // These bits cannot contribute to the result of the 'and' in this context.
    if (DemandedMask.isSubsetOf(LHSKnown.Zero | RHSKnown.One))
      return I->getOperand(0);
    if (DemandedMask.isSubsetOf(RHSKnown.Zero | LHSKnown.One))
      return I->getOperand(1);

    break;
  }
  case Instruction::Or: {
    llvm::computeKnownBits(I->getOperand(1), RHSKnown, Q, Depth + 1);
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Q, Depth + 1);
    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Q, Depth);
    computeKnownBitsFromContext(I, Known, Q, Depth);

    // If the client is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(ITy, Known.One);

    // We can simplify (X|Y) -> X or Y in the user's context if we know that
    // only bits from X or Y are demanded.
    // If all of the demanded bits are known zero on one side, return the other.
    // These bits cannot contribute to the result of the 'or' in this context.
    if (DemandedMask.isSubsetOf(LHSKnown.One | RHSKnown.Zero))
      return I->getOperand(0);
    if (DemandedMask.isSubsetOf(RHSKnown.One | LHSKnown.Zero))
      return I->getOperand(1);

    break;
  }
  case Instruction::Xor: {
    llvm::computeKnownBits(I->getOperand(1), RHSKnown, Q, Depth + 1);
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Q, Depth + 1);
    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Q, Depth);
    computeKnownBitsFromContext(I, Known, Q, Depth);

    // If the client is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(ITy, Known.One);

    // We can simplify (X^Y) -> X or Y in the user's context if we know that
    // only bits from X or Y are demanded.
    // If all of the demanded bits are known zero on one side, return the other.
    if (DemandedMask.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);
    if (DemandedMask.isSubsetOf(LHSKnown.Zero))
      return I->getOperand(1);

    break;
  }
  case Instruction::Add: {
    unsigned NLZ = DemandedMask.countl_zero();
    APInt DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ);

    // If an operand adds zeros to every bit below the highest demanded bit,
    // that operand doesn't change the result. Return the other side.
    llvm::computeKnownBits(I->getOperand(1), RHSKnown, Q, Depth + 1);
    if (DemandedFromOps.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);

    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Q, Depth + 1);
    if (DemandedFromOps.isSubsetOf(LHSKnown.Zero))
      return I->getOperand(1);

    bool NSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
    bool NUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
    Known = KnownBits::add(LHSKnown, RHSKnown, NSW, NUW);
    computeKnownBitsFromContext(I, Known, Q, Depth);
    break;
  }
  case Instruction::Sub: {
    unsigned NLZ = DemandedMask.countl_zero();
    APInt DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ);

    // If an operand subtracts zeros from every bit below the highest demanded
    // bit, that operand doesn't change the result. Return the other side.
    llvm::computeKnownBits(I->getOperand(1), RHSKnown, Q, Depth + 1);
    if (DemandedFromOps.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);

    bool NSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
    bool NUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Q, Depth + 1);
    Known = KnownBits::sub(LHSKnown, RHSKnown, NSW, NUW);
    computeKnownBitsFromContext(I, Known, Q, Depth);
    break;
  }
  case Instruction::AShr: {
    // Compute the Known bits to simplify things downstream.
    llvm::computeKnownBits(I, Known, Q, Depth);

    // If this user is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
      return Constant::getIntegerValue(ITy, Known.One);

    // If the right shift operand 0 is a result of a left shift by the same
    // amount, this is probably a zero/sign extension, which may be unnecessary,
    // if we do not demand any of the new sign bits. So, return the original
    // operand instead.
    const APInt *ShiftRC;
    const APInt *ShiftLC;
    Value *X;
    unsigned BitWidth = DemandedMask.getBitWidth();
    if (match(I,
              m_AShr(m_Shl(m_Value(X), m_APInt(ShiftLC)), m_APInt(ShiftRC))) &&
        ShiftLC == ShiftRC && ShiftLC->ult(BitWidth) &&
        DemandedMask.isSubsetOf(APInt::getLowBitsSet(
            BitWidth, BitWidth - ShiftRC->getZExtValue()))) {
      return X;
    }

    break;
  }
  default:
    // Compute the Known bits to simplify things downstream.
    llvm::computeKnownBits(I, Known, Q, Depth);

    // If this user is only demanding bits that we know, return the known
    // constant.
    if (DemandedMask.isSubsetOf(Known.Zero|Known.One))
      return Constant::getIntegerValue(ITy, Known.One);

    break;
  }

  return nullptr;
}

/// Helper routine of SimplifyDemandedUseBits. It tries to simplify
/// "E1 = (X lsr C1) << C2", where the C1 and C2 are constant, into
/// "E2 = X << (C2 - C1)" or "E2 = X >> (C1 - C2)", depending on the sign
/// of "C2-C1".
///
/// Suppose E1 and E2 are generally different in bits S={bm, bm+1,
/// ..., bn}, without considering the specific value X is holding.
/// This transformation is legal iff one of following conditions is hold:
///  1) All the bit in S are 0, in this case E1 == E2.
///  2) We don't care those bits in S, per the input DemandedMask.
///  3) Combination of 1) and 2). Some bits in S are 0, and we don't care the
///     rest bits.
///
/// Currently we only test condition 2).
///
/// As with SimplifyDemandedUseBits, it returns NULL if the simplification was
/// not successful.
Value *InstCombinerImpl::simplifyShrShlDemandedBits(
    Instruction *Shr, const APInt &ShrOp1, Instruction *Shl,
    const APInt &ShlOp1, const APInt &DemandedMask, KnownBits &Known) {
  if (!ShlOp1 || !ShrOp1)
    return nullptr; // No-op.

  Value *VarX = Shr->getOperand(0);
  Type *Ty = VarX->getType();
  unsigned BitWidth = Ty->getScalarSizeInBits();
  if (ShlOp1.uge(BitWidth) || ShrOp1.uge(BitWidth))
    return nullptr; // Undef.

  unsigned ShlAmt = ShlOp1.getZExtValue();
  unsigned ShrAmt = ShrOp1.getZExtValue();

  Known.One.clearAllBits();
  Known.Zero.setLowBits(ShlAmt - 1);
  Known.Zero &= DemandedMask;

  APInt BitMask1(APInt::getAllOnes(BitWidth));
  APInt BitMask2(APInt::getAllOnes(BitWidth));

  bool isLshr = (Shr->getOpcode() == Instruction::LShr);
  BitMask1 = isLshr ? (BitMask1.lshr(ShrAmt) << ShlAmt) :
                      (BitMask1.ashr(ShrAmt) << ShlAmt);

  if (ShrAmt <= ShlAmt) {
    BitMask2 <<= (ShlAmt - ShrAmt);
  } else {
    BitMask2 = isLshr ? BitMask2.lshr(ShrAmt - ShlAmt):
                        BitMask2.ashr(ShrAmt - ShlAmt);
  }

  // Check if condition-2 (see the comment to this function) is satified.
  if ((BitMask1 & DemandedMask) == (BitMask2 & DemandedMask)) {
    if (ShrAmt == ShlAmt)
      return VarX;

    if (!Shr->hasOneUse())
      return nullptr;

    BinaryOperator *New;
    if (ShrAmt < ShlAmt) {
      Constant *Amt = ConstantInt::get(VarX->getType(), ShlAmt - ShrAmt);
      New = BinaryOperator::CreateShl(VarX, Amt);
      BinaryOperator *Orig = cast<BinaryOperator>(Shl);
      New->setHasNoSignedWrap(Orig->hasNoSignedWrap());
      New->setHasNoUnsignedWrap(Orig->hasNoUnsignedWrap());
    } else {
      Constant *Amt = ConstantInt::get(VarX->getType(), ShrAmt - ShlAmt);
      New = isLshr ? BinaryOperator::CreateLShr(VarX, Amt) :
                     BinaryOperator::CreateAShr(VarX, Amt);
      if (cast<BinaryOperator>(Shr)->isExact())
        New->setIsExact(true);
    }

    return InsertNewInstWith(New, Shl->getIterator());
  }

  return nullptr;
}

/// The specified value produces a vector with any number of elements.
/// This method analyzes which elements of the operand are poison and
/// returns that information in PoisonElts.
///
/// DemandedElts contains the set of elements that are actually used by the
/// caller, and by default (AllowMultipleUsers equals false) the value is
/// simplified only if it has a single caller. If AllowMultipleUsers is set
/// to true, DemandedElts refers to the union of sets of elements that are
/// used by all callers.
///
/// If the information about demanded elements can be used to simplify the
/// operation, the operation is simplified, then the resultant value is
/// returned.  This returns null if no change was made.
Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
                                                    APInt DemandedElts,
                                                    APInt &PoisonElts,
                                                    unsigned Depth,
                                                    bool AllowMultipleUsers) {
  // Cannot analyze scalable type. The number of vector elements is not a
  // compile-time constant.
  if (isa<ScalableVectorType>(V->getType()))
    return nullptr;

  unsigned VWidth = cast<FixedVectorType>(V->getType())->getNumElements();
  APInt EltMask(APInt::getAllOnes(VWidth));
  assert((DemandedElts & ~EltMask) == 0 && "Invalid DemandedElts!");

  if (match(V, m_Poison())) {
    // If the entire vector is poison, just return this info.
    PoisonElts = EltMask;
    return nullptr;
  }

  if (DemandedElts.isZero()) { // If nothing is demanded, provide poison.
    PoisonElts = EltMask;
    return PoisonValue::get(V->getType());
  }

  PoisonElts = 0;

  if (auto *C = dyn_cast<Constant>(V)) {
    // Check if this is identity. If so, return 0 since we are not simplifying
    // anything.
    if (DemandedElts.isAllOnes())
      return nullptr;

    Type *EltTy = cast<VectorType>(V->getType())->getElementType();
    Constant *Poison = PoisonValue::get(EltTy);
    SmallVector<Constant*, 16> Elts;
    for (unsigned i = 0; i != VWidth; ++i) {
      if (!DemandedElts[i]) {   // If not demanded, set to poison.
        Elts.push_back(Poison);
        PoisonElts.setBit(i);
        continue;
      }

      Constant *Elt = C->getAggregateElement(i);
      if (!Elt) return nullptr;

      Elts.push_back(Elt);
      if (isa<PoisonValue>(Elt)) // Already poison.
        PoisonElts.setBit(i);
    }

    // If we changed the constant, return it.
    Constant *NewCV = ConstantVector::get(Elts);
    return NewCV != C ? NewCV : nullptr;
  }

  // Limit search depth.
  if (Depth == SimplifyDemandedVectorEltsDepthLimit)
    return nullptr;

  if (!AllowMultipleUsers) {
    // If multiple users are using the root value, proceed with
    // simplification conservatively assuming that all elements
    // are needed.
    if (!V->hasOneUse()) {
      // Quit if we find multiple users of a non-root value though.
      // They'll be handled when it's their turn to be visited by
      // the main instcombine process.
      if (Depth != 0)
        // TODO: Just compute the PoisonElts information recursively.
        return nullptr;

      // Conservatively assume that all elements are needed.
      DemandedElts = EltMask;
    }
  }

  Instruction *I = dyn_cast<Instruction>(V);
  if (!I) return nullptr;        // Only analyze instructions.

  bool MadeChange = false;
  auto simplifyAndSetOp = [&](Instruction *Inst, unsigned OpNum,
                              APInt Demanded, APInt &Undef) {
    auto *II = dyn_cast<IntrinsicInst>(Inst);
    Value *Op = II ? II->getArgOperand(OpNum) : Inst->getOperand(OpNum);
    if (Value *V = SimplifyDemandedVectorElts(Op, Demanded, Undef, Depth + 1)) {
      replaceOperand(*Inst, OpNum, V);
      MadeChange = true;
    }
  };

  APInt PoisonElts2(VWidth, 0);
  APInt PoisonElts3(VWidth, 0);
  switch (I->getOpcode()) {
  default: break;

  case Instruction::GetElementPtr: {
    // The LangRef requires that struct geps have all constant indices.  As
    // such, we can't convert any operand to partial undef.
    auto mayIndexStructType = [](GetElementPtrInst &GEP) {
      for (auto I = gep_type_begin(GEP), E = gep_type_end(GEP);
           I != E; I++)
        if (I.isStruct())
          return true;
      return false;
    };
    if (mayIndexStructType(cast<GetElementPtrInst>(*I)))
      break;

    // Conservatively track the demanded elements back through any vector
    // operands we may have.  We know there must be at least one, or we
    // wouldn't have a vector result to get here. Note that we intentionally
    // merge the undef bits here since gepping with either an poison base or
    // index results in poison.
    for (unsigned i = 0; i < I->getNumOperands(); i++) {
      if (i == 0 ? match(I->getOperand(i), m_Undef())
                 : match(I->getOperand(i), m_Poison())) {
        // If the entire vector is undefined, just return this info.
        PoisonElts = EltMask;
        return nullptr;
      }
      if (I->getOperand(i)->getType()->isVectorTy()) {
        APInt PoisonEltsOp(VWidth, 0);
        simplifyAndSetOp(I, i, DemandedElts, PoisonEltsOp);
        // gep(x, undef) is not undef, so skip considering idx ops here
        // Note that we could propagate poison, but we can't distinguish between
        // undef & poison bits ATM
        if (i == 0)
          PoisonElts |= PoisonEltsOp;
      }
    }

    break;
  }
  case Instruction::InsertElement: {
    // If this is a variable index, we don't know which element it overwrites.
    // demand exactly the same input as we produce.
    ConstantInt *Idx = dyn_cast<ConstantInt>(I->getOperand(2));
    if (!Idx) {
      // Note that we can't propagate undef elt info, because we don't know
      // which elt is getting updated.
      simplifyAndSetOp(I, 0, DemandedElts, PoisonElts2);
      break;
    }

    // The element inserted overwrites whatever was there, so the input demanded
    // set is simpler than the output set.
    unsigned IdxNo = Idx->getZExtValue();
    APInt PreInsertDemandedElts = DemandedElts;
    if (IdxNo < VWidth)
      PreInsertDemandedElts.clearBit(IdxNo);

    // If we only demand the element that is being inserted and that element
    // was extracted from the same index in another vector with the same type,
    // replace this insert with that other vector.
    // Note: This is attempted before the call to simplifyAndSetOp because that
    //       may change PoisonElts to a value that does not match with Vec.
    Value *Vec;
    if (PreInsertDemandedElts == 0 &&
        match(I->getOperand(1),
              m_ExtractElt(m_Value(Vec), m_SpecificInt(IdxNo))) &&
        Vec->getType() == I->getType()) {
      return Vec;
    }

    simplifyAndSetOp(I, 0, PreInsertDemandedElts, PoisonElts);

    // If this is inserting an element that isn't demanded, remove this
    // insertelement.
    if (IdxNo >= VWidth || !DemandedElts[IdxNo]) {
      Worklist.push(I);
      return I->getOperand(0);
    }

    // The inserted element is defined.
    PoisonElts.clearBit(IdxNo);
    break;
  }
  case Instruction::ShuffleVector: {
    auto *Shuffle = cast<ShuffleVectorInst>(I);
    assert(Shuffle->getOperand(0)->getType() ==
           Shuffle->getOperand(1)->getType() &&
           "Expected shuffle operands to have same type");
    unsigned OpWidth = cast<FixedVectorType>(Shuffle->getOperand(0)->getType())
                           ->getNumElements();
    // Handle trivial case of a splat. Only check the first element of LHS
    // operand.
    if (all_of(Shuffle->getShuffleMask(), [](int Elt) { return Elt == 0; }) &&
        DemandedElts.isAllOnes()) {
      if (!isa<PoisonValue>(I->getOperand(1))) {
        I->setOperand(1, PoisonValue::get(I->getOperand(1)->getType()));
        MadeChange = true;
      }
      APInt LeftDemanded(OpWidth, 1);
      APInt LHSPoisonElts(OpWidth, 0);
      simplifyAndSetOp(I, 0, LeftDemanded, LHSPoisonElts);
      if (LHSPoisonElts[0])
        PoisonElts = EltMask;
      else
        PoisonElts.clearAllBits();
      break;
    }

    APInt LeftDemanded(OpWidth, 0), RightDemanded(OpWidth, 0);
    for (unsigned i = 0; i < VWidth; i++) {
      if (DemandedElts[i]) {
        unsigned MaskVal = Shuffle->getMaskValue(i);
        if (MaskVal != -1u) {
          assert(MaskVal < OpWidth * 2 &&
                 "shufflevector mask index out of range!");
          if (MaskVal < OpWidth)
            LeftDemanded.setBit(MaskVal);
          else
            RightDemanded.setBit(MaskVal - OpWidth);
        }
      }
    }

    APInt LHSPoisonElts(OpWidth, 0);
    simplifyAndSetOp(I, 0, LeftDemanded, LHSPoisonElts);

    APInt RHSPoisonElts(OpWidth, 0);
    simplifyAndSetOp(I, 1, RightDemanded, RHSPoisonElts);

    // If this shuffle does not change the vector length and the elements
    // demanded by this shuffle are an identity mask, then this shuffle is
    // unnecessary.
    //
    // We are assuming canonical form for the mask, so the source vector is
    // operand 0 and operand 1 is not used.
    //
    // Note that if an element is demanded and this shuffle mask is undefined
    // for that element, then the shuffle is not considered an identity
    // operation. The shuffle prevents poison from the operand vector from
    // leaking to the result by replacing poison with an undefined value.
    if (VWidth == OpWidth) {
      bool IsIdentityShuffle = true;
      for (unsigned i = 0; i < VWidth; i++) {
        unsigned MaskVal = Shuffle->getMaskValue(i);
        if (DemandedElts[i] && i != MaskVal) {
          IsIdentityShuffle = false;
          break;
        }
      }
      if (IsIdentityShuffle)
        return Shuffle->getOperand(0);
    }

    bool NewPoisonElts = false;
    unsigned LHSIdx = -1u, LHSValIdx = -1u;
    unsigned RHSIdx = -1u, RHSValIdx = -1u;
    bool LHSUniform = true;
    bool RHSUniform = true;
    for (unsigned i = 0; i < VWidth; i++) {
      unsigned MaskVal = Shuffle->getMaskValue(i);
      if (MaskVal == -1u) {
        PoisonElts.setBit(i);
      } else if (!DemandedElts[i]) {
        NewPoisonElts = true;
        PoisonElts.setBit(i);
      } else if (MaskVal < OpWidth) {
        if (LHSPoisonElts[MaskVal]) {
          NewPoisonElts = true;
          PoisonElts.setBit(i);
        } else {
          LHSIdx = LHSIdx == -1u ? i : OpWidth;
          LHSValIdx = LHSValIdx == -1u ? MaskVal : OpWidth;
          LHSUniform = LHSUniform && (MaskVal == i);
        }
      } else {
        if (RHSPoisonElts[MaskVal - OpWidth]) {
          NewPoisonElts = true;
          PoisonElts.setBit(i);
        } else {
          RHSIdx = RHSIdx == -1u ? i : OpWidth;
          RHSValIdx = RHSValIdx == -1u ? MaskVal - OpWidth : OpWidth;
          RHSUniform = RHSUniform && (MaskVal - OpWidth == i);
        }
      }
    }

    // Try to transform shuffle with constant vector and single element from
    // this constant vector to single insertelement instruction.
    // shufflevector V, C, <v1, v2, .., ci, .., vm> ->
    // insertelement V, C[ci], ci-n
    if (OpWidth ==
        cast<FixedVectorType>(Shuffle->getType())->getNumElements()) {
      Value *Op = nullptr;
      Constant *Value = nullptr;
      unsigned Idx = -1u;

      // Find constant vector with the single element in shuffle (LHS or RHS).
      if (LHSIdx < OpWidth && RHSUniform) {
        if (auto *CV = dyn_cast<ConstantVector>(Shuffle->getOperand(0))) {
          Op = Shuffle->getOperand(1);
          Value = CV->getOperand(LHSValIdx);
          Idx = LHSIdx;
        }
      }
      if (RHSIdx < OpWidth && LHSUniform) {
        if (auto *CV = dyn_cast<ConstantVector>(Shuffle->getOperand(1))) {
          Op = Shuffle->getOperand(0);
          Value = CV->getOperand(RHSValIdx);
          Idx = RHSIdx;
        }
      }
      // Found constant vector with single element - convert to insertelement.
      if (Op && Value) {
        Instruction *New = InsertElementInst::Create(
            Op, Value, ConstantInt::get(Type::getInt64Ty(I->getContext()), Idx),
            Shuffle->getName());
        InsertNewInstWith(New, Shuffle->getIterator());
        return New;
      }
    }
    if (NewPoisonElts) {
      // Add additional discovered undefs.
      SmallVector<int, 16> Elts;
      for (unsigned i = 0; i < VWidth; ++i) {
        if (PoisonElts[i])
          Elts.push_back(PoisonMaskElem);
        else
          Elts.push_back(Shuffle->getMaskValue(i));
      }
      Shuffle->setShuffleMask(Elts);
      MadeChange = true;
    }
    break;
  }
  case Instruction::Select: {
    // If this is a vector select, try to transform the select condition based
    // on the current demanded elements.
    SelectInst *Sel = cast<SelectInst>(I);
    if (Sel->getCondition()->getType()->isVectorTy()) {
      // TODO: We are not doing anything with PoisonElts based on this call.
      // It is overwritten below based on the other select operands. If an
      // element of the select condition is known undef, then we are free to
      // choose the output value from either arm of the select. If we know that
      // one of those values is undef, then the output can be undef.
      simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
    }

    // Next, see if we can transform the arms of the select.
    APInt DemandedLHS(DemandedElts), DemandedRHS(DemandedElts);
    if (auto *CV = dyn_cast<ConstantVector>(Sel->getCondition())) {
      for (unsigned i = 0; i < VWidth; i++) {
        Constant *CElt = CV->getAggregateElement(i);

        // isNullValue() always returns false when called on a ConstantExpr.
        if (CElt->isNullValue())
          DemandedLHS.clearBit(i);
        else if (CElt->isOneValue())
          DemandedRHS.clearBit(i);
      }
    }

    simplifyAndSetOp(I, 1, DemandedLHS, PoisonElts2);
    simplifyAndSetOp(I, 2, DemandedRHS, PoisonElts3);

    // Output elements are undefined if the element from each arm is undefined.
    // TODO: This can be improved. See comment in select condition handling.
    PoisonElts = PoisonElts2 & PoisonElts3;
    break;
  }
  case Instruction::BitCast: {
    // Vector->vector casts only.
    VectorType *VTy = dyn_cast<VectorType>(I->getOperand(0)->getType());
    if (!VTy) break;
    unsigned InVWidth = cast<FixedVectorType>(VTy)->getNumElements();
    APInt InputDemandedElts(InVWidth, 0);
    PoisonElts2 = APInt(InVWidth, 0);
    unsigned Ratio;

    if (VWidth == InVWidth) {
      // If we are converting from <4 x i32> -> <4 x f32>, we demand the same
      // elements as are demanded of us.
      Ratio = 1;
      InputDemandedElts = DemandedElts;
    } else if ((VWidth % InVWidth) == 0) {
      // If the number of elements in the output is a multiple of the number of
      // elements in the input then an input element is live if any of the
      // corresponding output elements are live.
      Ratio = VWidth / InVWidth;
      for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx)
        if (DemandedElts[OutIdx])
          InputDemandedElts.setBit(OutIdx / Ratio);
    } else if ((InVWidth % VWidth) == 0) {
      // If the number of elements in the input is a multiple of the number of
      // elements in the output then an input element is live if the
      // corresponding output element is live.
      Ratio = InVWidth / VWidth;
      for (unsigned InIdx = 0; InIdx != InVWidth; ++InIdx)
        if (DemandedElts[InIdx / Ratio])
          InputDemandedElts.setBit(InIdx);
    } else {
      // Unsupported so far.
      break;
    }

    simplifyAndSetOp(I, 0, InputDemandedElts, PoisonElts2);

    if (VWidth == InVWidth) {
      PoisonElts = PoisonElts2;
    } else if ((VWidth % InVWidth) == 0) {
      // If the number of elements in the output is a multiple of the number of
      // elements in the input then an output element is undef if the
      // corresponding input element is undef.
      for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx)
        if (PoisonElts2[OutIdx / Ratio])
          PoisonElts.setBit(OutIdx);
    } else if ((InVWidth % VWidth) == 0) {
      // If the number of elements in the input is a multiple of the number of
      // elements in the output then an output element is undef if all of the
      // corresponding input elements are undef.
      for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx) {
        APInt SubUndef = PoisonElts2.lshr(OutIdx * Ratio).zextOrTrunc(Ratio);
        if (SubUndef.popcount() == Ratio)
          PoisonElts.setBit(OutIdx);
      }
    } else {
      llvm_unreachable("Unimp");
    }
    break;
  }
  case Instruction::FPTrunc:
  case Instruction::FPExt:
    simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
    break;

  case Instruction::Call: {
    IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
    if (!II) break;
    switch (II->getIntrinsicID()) {
    case Intrinsic::masked_gather: // fallthrough
    case Intrinsic::masked_load: {
      // Subtlety: If we load from a pointer, the pointer must be valid
      // regardless of whether the element is demanded.  Doing otherwise risks
      // segfaults which didn't exist in the original program.
      APInt DemandedPtrs(APInt::getAllOnes(VWidth)),
          DemandedPassThrough(DemandedElts);
      if (auto *CMask = dyn_cast<Constant>(II->getOperand(1))) {
        for (unsigned i = 0; i < VWidth; i++) {
          if (Constant *CElt = CMask->getAggregateElement(i)) {
            if (CElt->isNullValue())
              DemandedPtrs.clearBit(i);
            else if (CElt->isAllOnesValue())
              DemandedPassThrough.clearBit(i);
          }
        }
      }

      if (II->getIntrinsicID() == Intrinsic::masked_gather)
        simplifyAndSetOp(II, 0, DemandedPtrs, PoisonElts2);
      simplifyAndSetOp(II, 2, DemandedPassThrough, PoisonElts3);

      // Output elements are undefined if the element from both sources are.
      // TODO: can strengthen via mask as well.
      PoisonElts = PoisonElts2 & PoisonElts3;
      break;
    }
    default: {
      // Handle target specific intrinsics
      std::optional<Value *> V = targetSimplifyDemandedVectorEltsIntrinsic(
          *II, DemandedElts, PoisonElts, PoisonElts2, PoisonElts3,
          simplifyAndSetOp);
      if (V)
        return *V;
      break;
    }
    } // switch on IntrinsicID
    break;
  } // case Call
  } // switch on Opcode

  // TODO: We bail completely on integer div/rem and shifts because they have
  // UB/poison potential, but that should be refined.
  BinaryOperator *BO;
  if (match(I, m_BinOp(BO)) && !BO->isIntDivRem() && !BO->isShift()) {
    Value *X = BO->getOperand(0);
    Value *Y = BO->getOperand(1);

    // Look for an equivalent binop except that one operand has been shuffled.
    // If the demand for this binop only includes elements that are the same as
    // the other binop, then we may be able to replace this binop with a use of
    // the earlier one.
    //
    // Example:
    // %other_bo = bo (shuf X, {0}), Y
    // %this_extracted_bo = extelt (bo X, Y), 0
    // -->
    // %other_bo = bo (shuf X, {0}), Y
    // %this_extracted_bo = extelt %other_bo, 0
    //
    // TODO: Handle demand of an arbitrary single element or more than one
    //       element instead of just element 0.
    // TODO: Unlike general demanded elements transforms, this should be safe
    //       for any (div/rem/shift) opcode too.
    if (DemandedElts == 1 && !X->hasOneUse() && !Y->hasOneUse() &&
        BO->hasOneUse() ) {

      auto findShufBO = [&](bool MatchShufAsOp0) -> User * {
        // Try to use shuffle-of-operand in place of an operand:
        // bo X, Y --> bo (shuf X), Y
        // bo X, Y --> bo X, (shuf Y)

        Value *OtherOp = MatchShufAsOp0 ? Y : X;
        if (!OtherOp->hasUseList())
          return nullptr;

        BinaryOperator::BinaryOps Opcode = BO->getOpcode();
        Value *ShufOp = MatchShufAsOp0 ? X : Y;

        for (User *U : OtherOp->users()) {
          ArrayRef<int> Mask;
          auto Shuf = m_Shuffle(m_Specific(ShufOp), m_Value(), m_Mask(Mask));
          if (BO->isCommutative()
                  ? match(U, m_c_BinOp(Opcode, Shuf, m_Specific(OtherOp)))
                  : MatchShufAsOp0
                        ? match(U, m_BinOp(Opcode, Shuf, m_Specific(OtherOp)))
                        : match(U, m_BinOp(Opcode, m_Specific(OtherOp), Shuf)))
            if (match(Mask, m_ZeroMask()) && Mask[0] != PoisonMaskElem)
              if (DT.dominates(U, I))
                return U;
        }
        return nullptr;
      };

      if (User *ShufBO = findShufBO(/* MatchShufAsOp0 */ true))
        return ShufBO;
      if (User *ShufBO = findShufBO(/* MatchShufAsOp0 */ false))
        return ShufBO;
    }

    simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
    simplifyAndSetOp(I, 1, DemandedElts, PoisonElts2);

    // Output elements are undefined if both are undefined. Consider things
    // like undef & 0. The result is known zero, not undef.
    PoisonElts &= PoisonElts2;
  }

  // If we've proven all of the lanes poison, return a poison value.
  // TODO: Intersect w/demanded lanes
  if (PoisonElts.isAllOnes())
    return PoisonValue::get(I->getType());

  return MadeChange ? I : nullptr;
}

/// For floating-point classes that resolve to a single bit pattern, return that
/// value.
static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask,
                                    bool IsCanonicalizing = false) {
  if (Mask == fcNone)
    return PoisonValue::get(Ty);

  if (Mask == fcPosZero)
    return Constant::getNullValue(Ty);

  // Turn any possible snans into quiet if we can.
  if (Mask == fcNan && IsCanonicalizing)
    return ConstantFP::getQNaN(Ty);

  // TODO: Support aggregate types that are allowed by FPMathOperator.
  if (Ty->isAggregateType())
    return nullptr;

  switch (Mask) {
  case fcNegZero:
    return ConstantFP::getZero(Ty, true);
  case fcPosInf:
    return ConstantFP::getInfinity(Ty);
  case fcNegInf:
    return ConstantFP::getInfinity(Ty, true);
  default:
    return nullptr;
  }
}

Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
                                                    FPClassTest DemandedMask,
                                                    KnownFPClass &Known,
                                                    Instruction *CxtI,
                                                    unsigned Depth) {
  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
  assert(Known == KnownFPClass() && "expected uninitialized state");
  assert(I->hasOneUse() && "wrong version called");

  Type *VTy = I->getType();

  FastMathFlags FMF;
  if (auto *FPOp = dyn_cast<FPMathOperator>(I)) {
    FMF = FPOp->getFastMathFlags();
    if (FMF.noNaNs())
      DemandedMask &= ~fcNan;

    if (FMF.noInfs())
      DemandedMask &= ~fcInf;
  }

  switch (I->getOpcode()) {
  case Instruction::FNeg: {
    if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
                                Depth + 1))
      return I;
    Known.fneg();
    break;
  }
  case Instruction::FMul: {
    KnownFPClass KnownLHS, KnownRHS;

    Value *X = I->getOperand(0);
    Value *Y = I->getOperand(1);

    FPClassTest SrcDemandedMask =
        DemandedMask & (fcNan | fcZero | fcSubnormal | fcNormal);

    if (DemandedMask & fcInf) {
      // mul x, inf = inf
      // mul large_x, large_y = inf
      SrcDemandedMask |= fcSubnormal | fcNormal | fcInf;
    }

    if (DemandedMask & fcNan) {
      // mul +/-inf, 0 => nan
      SrcDemandedMask |= fcZero | fcInf;

      // TODO: Mode check
      // mul +/-inf, sub => nan if daz
      SrcDemandedMask |= fcSubnormal;
    }

    // mul normal, subnormal = normal
    // Normal inputs may result in underflow.
    if (DemandedMask & (fcNormal | fcSubnormal))
      SrcDemandedMask |= fcNormal | fcSubnormal;

    if (DemandedMask & fcZero)
      SrcDemandedMask |= fcNormal | fcSubnormal;

    const SimplifyQuery &SQ = getSimplifyQuery();
    if (X == Y && isGuaranteedNotToBeUndef(X, SQ.AC, CxtI, SQ.DT, Depth + 1)) {
      if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1))
        return I;
      Type *EltTy = VTy->getScalarType();

      DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
      Known = KnownFPClass::square(KnownLHS, Mode);

      // Propagate known result to simplify edge case checks.
      if ((DemandedMask & fcNan) == fcNone)
        Known.knownNot(fcNan);
      if ((DemandedMask & fcPosInf) == fcNone)
        Known.knownNot(fcInf);

      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
      if (Constant *Folded =
              getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
        return Folded;

      if (Known.isKnownAlways(fcPosZero | fcPosInf | fcNan)) {
        assert(KnownLHS.isKnownNever(fcPosNormal));

        // We can skip the fabs if the source was already known positive.
        if (KnownLHS.isKnownAlways(fcPositive))
          return X;

        // => fabs(x), in case this was a -inf or -0.
        // Note: Dropping canonicalize.
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(I);
        Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FMF);
        Fabs->takeName(I);
        return Fabs;
      }

      return nullptr;
    }

    if (SimplifyDemandedFPClass(I, 1, SrcDemandedMask, KnownRHS, Depth + 1) ||
        SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1))
      return I;

    // Propagate nnan-ness to sources to simplify source checks.
    if ((DemandedMask & fcNan) == fcNone) {
      KnownLHS.knownNot(fcNan);
      KnownRHS.knownNot(fcNan);
    }

    if (FMF.noInfs()) {
      // Flag implies inputs cannot be infinity.
      KnownLHS.knownNot(fcInf);
      KnownRHS.knownNot(fcInf);
    }

    bool NonNanResult = (DemandedMask & fcNan) == fcNone;

    // With no-nans/no-infs:
    // X * 0.0 --> copysign(0.0, X)
    // X * -0.0 --> copysign(0.0, -X)
    if ((NonNanResult || KnownLHS.isKnownNeverInfOrNaN()) &&
        KnownRHS.isKnownAlways(fcPosZero | fcNan)) {
      // => copysign(+0, lhs)
      // Note: Dropping canonicalize
      Value *Copysign = Builder.CreateCopySign(Y, X, FMF);
      Copysign->takeName(I);
      return Copysign;
    }

    if (KnownLHS.isKnownAlways(fcPosZero | fcNan) &&
        (NonNanResult || KnownRHS.isKnownNeverInfOrNaN())) {
      // => copysign(+0, rhs)
      // Note: Dropping canonicalize
      Value *Copysign = Builder.CreateCopySign(X, Y, FMF);
      Copysign->takeName(I);
      return Copysign;
    }

    if ((NonNanResult || KnownLHS.isKnownNeverInfOrNaN()) &&
        KnownRHS.isKnownAlways(fcNegZero | fcNan)) {
      // => copysign(0, fneg(lhs))
      // Note: Dropping canonicalize
      Value *Copysign =
          Builder.CreateCopySign(Y, Builder.CreateFNegFMF(X, FMF), FMF);
      Copysign->takeName(I);
      return Copysign;
    }

    if (KnownLHS.isKnownAlways(fcNegZero | fcNan) &&
        (NonNanResult || KnownRHS.isKnownNeverInfOrNaN())) {
      // => copysign(+0, fneg(rhs))
      // Note: Dropping canonicalize
      Value *Copysign =
          Builder.CreateCopySign(X, Builder.CreateFNegFMF(Y, FMF), FMF);
      Copysign->takeName(I);
      return Copysign;
    }

    Type *EltTy = VTy->getScalarType();
    DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());

    if (KnownLHS.isKnownAlways(fcInf | fcNan) &&
        (KnownRHS.isKnownNeverNaN() &&
         KnownRHS.cannotBeOrderedGreaterEqZero(Mode))) {
      // Note: Dropping canonicalize
      Value *Neg = Builder.CreateFNegFMF(X, FMF);
      Neg->takeName(I);
      return Neg;
    }

    if (KnownRHS.isKnownAlways(fcInf | fcNan) &&
        (KnownLHS.isKnownNeverNaN() &&
         KnownLHS.cannotBeOrderedGreaterEqZero(Mode))) {
      // Note: Dropping canonicalize
      Value *Neg = Builder.CreateFNegFMF(Y, FMF);
      Neg->takeName(I);
      return Neg;
    }

    Known = KnownFPClass::fmul(KnownLHS, KnownRHS, Mode);

    FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
    return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
  }
  case Instruction::FPExt: {
    FPClassTest SrcDemandedMask = DemandedMask;

    // No subnormal result does not imply not-subnormal in the source type.
    if ((DemandedMask & fcNegNormal) != fcNone)
      SrcDemandedMask |= fcNegSubnormal;
    if ((DemandedMask & fcPosNormal) != fcNone)
      SrcDemandedMask |= fcPosSubnormal;

    KnownFPClass KnownSrc;
    if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
      return I;

    const fltSemantics &DstTy = VTy->getScalarType()->getFltSemantics();
    const fltSemantics &SrcTy =
        I->getOperand(0)->getType()->getScalarType()->getFltSemantics();

    Known = KnownFPClass::fpext(KnownSrc, DstTy, SrcTy);
    FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;

    return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
  }
  case Instruction::Call: {
    CallInst *CI = cast<CallInst>(I);
    const Intrinsic::ID IID = CI->getIntrinsicID();
    switch (IID) {
    case Intrinsic::fabs:
      if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), Known,
                                  Depth + 1))
        return I;

      if (Known.SignBit == false ||
          ((DemandedMask & fcNan) == fcNone && Known.isKnownNever(fcNegative)))
        return CI->getArgOperand(0);

      Known.fabs();
      break;
    case Intrinsic::arithmetic_fence:
      if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
        return I;
      break;
    case Intrinsic::copysign: {
      // Flip on more potentially demanded classes
      const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
      if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
        return I;

      if ((DemandedMask & fcNegative) == DemandedMask) {
        // Roundabout way of replacing with fneg(fabs)
        CI->setOperand(1, ConstantFP::get(VTy, -1.0));
        return I;
      }

      if ((DemandedMask & fcPositive) == DemandedMask) {
        // Roundabout way of replacing with fabs
        CI->setOperand(1, ConstantFP::getZero(VTy));
        return I;
      }

      KnownFPClass KnownSign = computeKnownFPClass(CI->getArgOperand(1),
                                                   fcAllFlags, CxtI, Depth + 1);

      if (Known.SignBit && KnownSign.SignBit &&
          *Known.SignBit == *KnownSign.SignBit)
        return CI->getOperand(0);

      // TODO: Call argument attribute not considered
      // Input implied not-nan from flag.
      if (FMF.noNaNs())
        KnownSign.knownNot(fcNan);

      if (KnownSign.SignBit == false) {
        CI->dropUBImplyingAttrsAndMetadata();
        CI->setOperand(1, ConstantFP::getZero(VTy));
        return I;
      }

      if (KnownSign.SignBit == true) {
        CI->dropUBImplyingAttrsAndMetadata();
        CI->setOperand(1, ConstantFP::get(VTy, -1.0));
        return I;
      }

      Known.copysign(KnownSign);
      break;
    }
    case Intrinsic::maximum:
    case Intrinsic::minimum:
    case Intrinsic::maximumnum:
    case Intrinsic::minimumnum: {
      const bool PropagateNaN =
          IID == Intrinsic::maximum || IID == Intrinsic::minimum;

      // We can't tell much based on the demanded result without inspecting the
      // operands (e.g., a known-positive result could have been clamped), but
      // we can still prune known-nan inputs.
      FPClassTest SrcDemandedMask =
          PropagateNaN ? DemandedMask | ~fcNan : fcAllFlags;

      KnownFPClass KnownLHS, KnownRHS;
      if (SimplifyDemandedFPClass(CI, 1, SrcDemandedMask, KnownRHS,
                                  Depth + 1) ||
          SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownLHS, Depth + 1))
        return I;

      /// Propagate nnan-ness to simplify edge case checks.
      if (PropagateNaN && (DemandedMask & fcNan) == fcNone) {
        KnownLHS.knownNot(fcNan);
        KnownRHS.knownNot(fcNan);
      }

      KnownFPClass::MinMaxKind OpKind;

      switch (IID) {
      case Intrinsic::maximum: {
        OpKind = KnownFPClass::MinMaxKind::maximum;

        // If at least one operand is known to be positive and the other
        // negative, the result must be the positive (unless the other operand
        // may be propagating a nan).
        if (KnownLHS.isKnownNever(fcNegative) &&
            KnownRHS.isKnownNever(fcPositive | fcNan))
          return CI->getArgOperand(0);

        if (KnownRHS.isKnownNever(fcNegative) &&
            KnownLHS.isKnownNever(fcPositive | fcNan))
          return CI->getArgOperand(1);

        // If one value must be pinf, the result is pinf or a propagated nan.
        if (KnownLHS.isKnownAlways(fcPosInf | fcNan) &&
            KnownRHS.isKnownNever(fcNan))
          return CI->getArgOperand(0);

        if (KnownRHS.isKnownAlways(fcPosInf | fcNan) &&
            KnownLHS.isKnownNever(fcNan))
          return CI->getArgOperand(1);

        break;
      }
      case Intrinsic::minimum: {
        OpKind = KnownFPClass::MinMaxKind::minimum;

        // If one operand is known to be negative, and the other positive, the
        // result must be the negative (unless the other operand may be
        // propagating a nan).
        if (KnownLHS.isKnownNever(fcPositive) &&
            KnownRHS.isKnownNever(fcNegative | fcNan))
          return CI->getArgOperand(0);

        if (KnownRHS.isKnownNever(fcPositive) &&
            KnownLHS.isKnownNever(fcNegative | fcNan))
          return CI->getArgOperand(1);

        // If one value must be ninf, the result is ninf or a propagated nan.
        if (KnownLHS.isKnownAlways(fcNegInf | fcNan) &&
            KnownRHS.isKnownNever(fcNan))
          return CI->getArgOperand(0);

        if (KnownRHS.isKnownAlways(fcNegInf | fcNan) &&
            KnownLHS.isKnownNever(fcNan))
          return CI->getArgOperand(1);

        break;
      }
      case Intrinsic::maximumnum: {
        OpKind = KnownFPClass::MinMaxKind::maximumnum;

        // If at least one operand is known to be positive and the other
        // negative, the result must be the positive.
        if (KnownLHS.isKnownNever(fcNegative | fcNan) &&
            KnownRHS.isKnownNever(fcPositive))
          return CI->getArgOperand(0);

        if (KnownRHS.isKnownNever(fcNegative | fcNan) &&
            KnownLHS.isKnownNever(fcPositive))
          return CI->getArgOperand(1);

        // If one value must be ninf or nan, the other value must be returned
        if (KnownLHS.isKnownAlways(fcNegInf | fcNan) &&
            KnownRHS.isKnownNever(fcNan))
          return CI->getArgOperand(1);

        if (KnownRHS.isKnownAlways(fcNegInf | fcNan) &&
            KnownLHS.isKnownNever(fcNan))
          return CI->getArgOperand(0);

        break;
      }
      case Intrinsic::minimumnum: {
        OpKind = KnownFPClass::MinMaxKind::minimumnum;

        // If at least one operand is known to be negative and the other
        // positive, the result must be the negative
        if (KnownLHS.isKnownNever(fcPositive | fcNan) &&
            KnownRHS.isKnownNever(fcNegative))
          return CI->getArgOperand(0);

        if (KnownRHS.isKnownNever(fcPositive | fcNan) &&
            KnownLHS.isKnownNever(fcNegative))
          return CI->getArgOperand(1);

        // If one value must be pinf or nan, the other value must be returned
        if (KnownLHS.isKnownAlways(fcPosInf | fcNan) &&
            KnownRHS.isKnownNever(fcNan))
          return CI->getArgOperand(1);

        if (KnownRHS.isKnownAlways(fcPosInf | fcNan) &&
            KnownLHS.isKnownNever(fcNan))
          return CI->getArgOperand(0);

        break;
      }
      default:
        llvm_unreachable("not a min/max intrinsic");
      }

      Type *EltTy = VTy->getScalarType();
      DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
      Known = KnownFPClass::minMaxLike(KnownLHS, KnownRHS, OpKind, Mode);

      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;

      if (Constant *SingleVal =
              getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
        return SingleVal;

      auto *FPOp = cast<FPMathOperator>(CI);

      bool ChangedFlags = false;

      // TODO: Add NSZ flag if we know the result will not be sensitive on the
      // sign of 0.
      if (!FPOp->hasNoNaNs() &&
          ((PropagateNaN && (ValidResults & fcNan) == fcNone) ||
           (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN()))) {
        CI->dropUBImplyingAttrsAndMetadata();
        CI->setHasNoNaNs(true);
        ChangedFlags = true;
      }

      if (ChangedFlags)
        return FPOp;

      return nullptr;
    }
    case Intrinsic::exp:
    case Intrinsic::exp2:
    case Intrinsic::exp10: {
      if ((DemandedMask & fcPositive) == fcNone) {
        // Only returns positive values or nans.
        if ((DemandedMask & fcNan) == fcNone)
          return PoisonValue::get(VTy);

        // Only need nan propagation.
        if ((DemandedMask & ~fcNan) == fcNone)
          return ConstantFP::getQNaN(VTy);

        return CI->getArgOperand(0);
      }

      FPClassTest SrcDemandedMask = DemandedMask & fcNan;

      if (DemandedMask & fcZero) {
        // exp(-infinity) = 0
        SrcDemandedMask |= fcNegInf;

        // exp(-largest_normal) = 0
        //
        // Negative numbers of sufficiently large magnitude underflow to 0. No
        // subnormal input has a 0 result.
        SrcDemandedMask |= fcNegNormal;
      }

      if (DemandedMask & fcPosSubnormal) {
        // Negative numbers of sufficiently large magnitude underflow to 0. No
        // subnormal input has a 0 result.
        SrcDemandedMask |= fcNegNormal;
      }

      if (DemandedMask & fcPosNormal) {
        // exp(0) = 1
        // exp(+/- smallest_normal) = 1
        // exp(+/- largest_denormal) = 1
        // exp(+/- smallest_denormal) = 1
        // exp(-1) = pos normal
        SrcDemandedMask |= fcNormal | fcSubnormal | fcZero;
      }

      // exp(inf), exp(largest_normal) = inf
      if (DemandedMask & fcPosInf)
        SrcDemandedMask |= fcPosInf | fcPosNormal;

      KnownFPClass KnownSrc;

      // TODO: This could really make use of KnownFPClass of specific value
      // range, (i.e., close enough to 1)
      if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
        return I;

      /// Propagate nnan-ness to simplify edge case checks.
      if ((DemandedMask & fcNan) == fcNone)
        KnownSrc.knownNot(fcNan);

      // exp(+/-0) = 1
      if (KnownSrc.isKnownAlways(fcZero))
        return ConstantFP::get(VTy, 1.0);

      // Only perform nan propagation.
      // Note: Dropping canonicalize / quiet of signaling nan.
      if (KnownSrc.isKnownAlways(fcNan))
        return CI->getArgOperand(0);

      // exp(0 | nan) => x == 0.0 ? 1.0 : x
      if (KnownSrc.isKnownAlways(fcZero | fcNan)) {
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(CI);

        // fadd +/-0, 1.0 => 1.0
        // fadd nan, 1.0 => nan
        return Builder.CreateFAddFMF(CI->getArgOperand(0),
                                     ConstantFP::get(VTy, 1.0), FMF);
      }

      if (KnownSrc.isKnownAlways(fcInf | fcNan)) {
        // exp(-inf) = 0
        // exp(+inf) = +inf
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(CI);

        // Note: Dropping canonicalize / quiet of signaling nan.
        Value *X = CI->getArgOperand(0);
        Value *IsPosInfOrNan = Builder.CreateFCmpFMF(
            FCmpInst::FCMP_UEQ, X, ConstantFP::getInfinity(VTy), FMF);
        // We do not know whether an infinity or a NaN is more likely here,
        // so mark the branch weights as unkown.
        Value *ZeroOrInf = Builder.CreateSelectFMFWithUnknownProfile(
            IsPosInfOrNan, X, ConstantFP::getZero(VTy), FMF, DEBUG_TYPE);
        return ZeroOrInf;
      }

      Known = KnownFPClass::exp(KnownSrc);

      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
      return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
    }
    case Intrinsic::log:
    case Intrinsic::log2:
    case Intrinsic::log10: {
      FPClassTest DemandedSrcMask = DemandedMask & (fcNan | fcPosInf);

      Type *EltTy = VTy->getScalarType();
      DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());

      // log(x < 0) = nan
      if (DemandedMask & fcNan)
        DemandedSrcMask |= (fcNegative & ~fcNegZero);

      // log(0) = -inf
      if (DemandedMask & fcNegInf) {
        DemandedSrcMask |= fcZero;

        // No value produces subnormal result.
        if (Mode.inputsMayBeZero())
          DemandedSrcMask |= fcSubnormal;
      }

      if (DemandedMask & fcNormal)
        DemandedSrcMask |= fcNormal | fcSubnormal;

      // log(1) = 0
      if (DemandedMask & fcZero)
        DemandedSrcMask |= fcPosNormal;

      KnownFPClass KnownSrc;
      if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
        return I;

      Known = KnownFPClass::log(KnownSrc, Mode);

      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
      return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
    }
    case Intrinsic::sqrt: {
      FPClassTest DemandedSrcMask =
          DemandedMask & (fcNegZero | fcPositive | fcNan);

      if (DemandedMask & fcNan)
        DemandedSrcMask |= (fcNegative & ~fcNegZero);

      // sqrt(max_subnormal) is a normal value
      if (DemandedMask & fcPosNormal)
        DemandedSrcMask |= fcPosSubnormal;

      KnownFPClass KnownSrc;
      if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
        return I;

      Type *EltTy = VTy->getScalarType();
      DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());

      // sqrt(-x) = nan, but be careful of negative subnormals flushed to 0.
      if (KnownSrc.isKnownNever(fcPositive) &&
          KnownSrc.isKnownNeverLogicalZero(Mode))
        return ConstantFP::getQNaN(VTy);

      Known = KnownFPClass::sqrt(KnownSrc, Mode);
      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;

      if (ValidResults == fcZero) {
        if (FMF.noSignedZeros())
          return ConstantFP::getZero(VTy);

        Value *Copysign = Builder.CreateCopySign(ConstantFP::getZero(VTy),
                                                 CI->getArgOperand(0), FMF);
        Copysign->takeName(CI);
        return Copysign;
      }

      return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
    }
    case Intrinsic::trunc:
    case Intrinsic::floor:
    case Intrinsic::ceil:
    case Intrinsic::rint:
    case Intrinsic::nearbyint:
    case Intrinsic::round:
    case Intrinsic::roundeven: {
      FPClassTest DemandedSrcMask = DemandedMask;

      // Zero results imply valid subnormal sources.
      if (DemandedMask & fcNegZero)
        DemandedSrcMask |= fcNegSubnormal | fcNegNormal;

      if (DemandedMask & fcPosZero)
        DemandedSrcMask |= fcPosSubnormal | fcPosNormal;

      KnownFPClass KnownSrc;
      if (SimplifyDemandedFPClass(CI, 0, DemandedSrcMask, KnownSrc, Depth + 1))
        return I;

      // Note: Possibly dropping snan quiet.
      if (KnownSrc.isKnownAlways(fcInf | fcNan | fcZero))
        return CI->getArgOperand(0);

      // Propagate nnan-ness to source to simplify source checks.
      if ((DemandedMask & fcNan) == fcNone)
        KnownSrc.knownNot(fcNan);

      bool IsRoundNearestOrTrunc =
          IID == Intrinsic::round || IID == Intrinsic::roundeven ||
          IID == Intrinsic::nearbyint || IID == Intrinsic::rint ||
          IID == Intrinsic::trunc;

      // Ignore denormals-as-zero, as canonicalization is not mandated.
      if ((IID == Intrinsic::floor || IsRoundNearestOrTrunc) &&
          KnownSrc.isKnownAlways(fcPosZero | fcPosSubnormal))
        return ConstantFP::getZero(VTy);

      if ((IID == Intrinsic::ceil || IsRoundNearestOrTrunc) &&
          KnownSrc.isKnownAlways(fcNegZero | fcNegSubnormal))
        return ConstantFP::getZero(VTy, true);

      if (IID == Intrinsic::floor && KnownSrc.isKnownAlways(fcNegSubnormal))
        return ConstantFP::get(VTy, -1.0);

      if (IID == Intrinsic::ceil && KnownSrc.isKnownAlways(fcPosSubnormal))
        return ConstantFP::get(VTy, 1.0);

      Known = KnownFPClass::roundToIntegral(
          KnownSrc, IID == Intrinsic::trunc,
          VTy->getScalarType()->isMultiUnitFPType());

      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
      if (Constant *SingleVal =
              getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
        return SingleVal;

      if ((IID == Intrinsic::trunc || IsRoundNearestOrTrunc) &&
          KnownSrc.isKnownAlways(fcZero | fcSubnormal)) {
        Value *Copysign = Builder.CreateCopySign(ConstantFP::getZero(VTy),
                                                 CI->getArgOperand(0));
        Copysign->takeName(CI);
        return Copysign;
      }

      return nullptr;
    }
    case Intrinsic::canonicalize: {
      Type *EltTy = VTy->getScalarType();

      // TODO: This could have more refined support for PositiveZero denormal
      // mode.
      if (EltTy->isIEEELikeFPTy()) {
        DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());

        FPClassTest SrcDemandedMask = DemandedMask;

        // A demanded quiet nan result may have come from a signaling nan, so we
        // need to expand the demanded mask.
        if ((DemandedMask & fcQNan) != fcNone)
          SrcDemandedMask |= fcSNan;

        if (Mode != DenormalMode::getIEEE()) {
          // Any zero results may have come from flushed denormals.
          if (DemandedMask & fcPosZero)
            SrcDemandedMask |= fcPosSubnormal;
          if (DemandedMask & fcNegZero)
            SrcDemandedMask |= fcNegSubnormal;
        }

        if (Mode == DenormalMode::getPreserveSign()) {
          // If a denormal input will be flushed, and we don't need zeros, we
          // don't need denormals either.
          if ((DemandedMask & fcPosZero) == fcNone)
            SrcDemandedMask &= ~fcPosSubnormal;

          if ((DemandedMask & fcNegZero) == fcNone)
            SrcDemandedMask &= ~fcNegSubnormal;
        }

        KnownFPClass KnownSrc;

        // Simplify upstream operations before trying to simplify this call.
        if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
          return I;

        // Perform the canonicalization to see if this folded to a constant.
        Known = KnownFPClass::canonicalize(KnownSrc, Mode);

        if (Constant *SingleVal =
                getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses))
          return SingleVal;

        // For IEEE handling, there is only a bit change for nan inputs, so we
        // can drop it if we do not demand nan results or we know the input
        // isn't a nan.
        // Otherwise, we also need to avoid denormal inputs to drop the
        // canonicalize.
        if ((KnownSrc.isKnownNeverNaN() || (DemandedMask & fcNan) == fcNone) &&
            (Mode == DenormalMode::getIEEE() ||
             KnownSrc.isKnownNeverSubnormal()))
          return CI->getArgOperand(0);

        return nullptr;
      }

      [[fallthrough]];
    }
    default:
      Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
      break;
    }

    break;
  }
  case Instruction::Select: {
    KnownFPClass KnownLHS, KnownRHS;
    if (SimplifyDemandedFPClass(I, 2, DemandedMask, KnownRHS, Depth + 1) ||
        SimplifyDemandedFPClass(I, 1, DemandedMask, KnownLHS, Depth + 1))
      return I;

    if (KnownLHS.isKnownNever(DemandedMask))
      return I->getOperand(2);
    if (KnownRHS.isKnownNever(DemandedMask))
      return I->getOperand(1);

    const SimplifyQuery &SQ = getSimplifyQuery();
    adjustKnownFPClassForSelectArm(KnownLHS, I->getOperand(0), I->getOperand(1),
                                   /*Invert=*/false, SQ, Depth);
    adjustKnownFPClassForSelectArm(KnownRHS, I->getOperand(0), I->getOperand(2),
                                   /*Invert=*/true, SQ, Depth);
    Known = KnownLHS.intersectWith(KnownRHS);
    break;
  }
  case Instruction::ExtractElement: {
    // TODO: Handle demanded element mask
    if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
      return I;
    break;
  }
  case Instruction::InsertElement: {
    KnownFPClass KnownInserted, KnownVec;
    if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownInserted, Depth + 1) ||
        SimplifyDemandedFPClass(I, 0, DemandedMask, KnownVec, Depth + 1))
      return I;

    // TODO: Use demanded elements logic from computeKnownFPClass
    Known = KnownVec | KnownInserted;
    break;
  }
  case Instruction::ShuffleVector: {
    KnownFPClass KnownLHS, KnownRHS;
    if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownRHS, Depth + 1) ||
        SimplifyDemandedFPClass(I, 0, DemandedMask, KnownLHS, Depth + 1))
      return I;

    // TODO: This is overly conservative and should consider demanded elements,
    // and splats.
    Known = KnownLHS | KnownRHS;
    break;
  }
  default:
    Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
    break;
  }

  return getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
}

/// Helper routine of SimplifyDemandedUseFPClass. It computes Known
/// floating-point classes. It also tries to handle simplifications that can be
/// done based on DemandedMask, but without modifying the Instruction.
Value *InstCombinerImpl::SimplifyMultipleUseDemandedFPClass(
    Instruction *I, FPClassTest DemandedMask, KnownFPClass &Known,
    Instruction *CxtI, unsigned Depth) {
  switch (I->getOpcode()) {
  case Instruction::Select: {
    // TODO: Can we infer which side it came from based on adjusted result
    // class?
    KnownFPClass KnownRHS =
        computeKnownFPClass(I->getOperand(2), DemandedMask, CxtI, Depth + 1);
    if (KnownRHS.isKnownNever(DemandedMask))
      return I->getOperand(1);

    KnownFPClass KnownLHS =
        computeKnownFPClass(I->getOperand(1), DemandedMask, CxtI, Depth + 1);
    if (KnownLHS.isKnownNever(DemandedMask))
      return I->getOperand(2);

    const SimplifyQuery &SQ = getSimplifyQuery();
    adjustKnownFPClassForSelectArm(KnownLHS, I->getOperand(0), I->getOperand(1),
                                   /*Invert=*/false, SQ, Depth);
    adjustKnownFPClassForSelectArm(KnownRHS, I->getOperand(0), I->getOperand(2),
                                   /*Invert=*/true, SQ, Depth);
    Known = KnownLHS.intersectWith(KnownRHS);
    break;
  }
  default:
    Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
    break;
  }

  return getFPClassConstant(I->getType(), DemandedMask & Known.KnownFPClasses);
}

bool InstCombinerImpl::SimplifyDemandedFPClass(Instruction *I, unsigned OpNo,
                                               FPClassTest DemandedMask,
                                               KnownFPClass &Known,
                                               unsigned Depth) {
  Use &U = I->getOperandUse(OpNo);
  Value *V = U.get();
  Type *VTy = V->getType();

  if (DemandedMask == fcNone) {
    if (isa<UndefValue>(V))
      return false;
    replaceUse(U, PoisonValue::get(VTy));
    return true;
  }

  // Handle constant
  Instruction *VInst = dyn_cast<Instruction>(V);
  if (!VInst) {
    // Handle constants and arguments
    Known = computeKnownFPClass(V, fcAllFlags, I, Depth);

    FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
    if (ValidResults == fcNone) {
      if (isa<UndefValue>(V))
        return false;
      replaceUse(U, PoisonValue::get(VTy));
      return true;
    }

    // Do not try to replace values which are already constants (unless we are
    // folding to poison). Doing so could promote poison elements to non-poison
    // constants.
    if (isa<Constant>(V))
      return false;

    Value *FoldedToConst = getFPClassConstant(VTy, ValidResults);
    if (!FoldedToConst || FoldedToConst == V)
      return false;

    replaceUse(U, FoldedToConst);
    return true;
  }

  if (Depth == MaxAnalysisRecursionDepth)
    return false;

  Value *NewVal;

  if (VInst->hasOneUse()) {
    // If the instruction has one use, we can directly simplify it.
    NewVal = SimplifyDemandedUseFPClass(VInst, DemandedMask, Known, I, Depth);
  } else {
    // If there are multiple uses of this instruction, then we can simplify
    // VInst to some other value, but not modify the instruction.
    NewVal = SimplifyMultipleUseDemandedFPClass(VInst, DemandedMask, Known, I,
                                                Depth);
  }

  if (!NewVal)
    return false;
  if (Instruction *OpInst = dyn_cast<Instruction>(U))
    salvageDebugInfo(*OpInst);

  replaceUse(U, NewVal);
  return true;
}
