//===- 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/ADT/SmallBitVector.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.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);
}

bool InstCombinerImpl::SimplifyDemandedInstructionFPClass(Instruction &Inst) {
  KnownFPClass Known;

  Value *V = SimplifyDemandedUseFPClass(&Inst, fcAllFlags, Known,
                                        SQ.getWithInstruction(&Inst));
  if (!V)
    return false;
  if (V == &Inst)
    return true;
  replaceInstUsesWith(Inst, V);
  return true;
}

/// 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_Ctpop(m_Value(LHS))) &&
        match(I->getOperand(1), m_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  |  0 | -1 |
        // Y:1  | -1 | -1 |
        //      -----------
        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);

    unsigned NtzLHS = (~DemandedMask & LHSKnown.Zero).countr_one();
    APInt DemandedFromRHS = DemandedFromOps;
    DemandedFromRHS.clearLowBits(NtzLHS);
    if (ShrinkDemandedConstant(I, 1, DemandedFromRHS))
      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()) {
        Instruction *Inst = I->user_back();
        if (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.CtxI, 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()) {
        Instruction *Inst = I->user_back();
        if (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.CtxI, 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.CtxI, 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));
            // Range attribute or metadata may no longer hold.
            I->dropPoisonGeneratingAnnotations();
            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));
            // Range attribute or metadata may no longer hold.
            I->dropPoisonGeneratingAnnotations();
            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;
}

/// Return true if the top-level all-lanes demanded-elements query can be
/// skipped for an intermediate insertelement chain node. This is limited to a
/// bounded one-use chain with distinct in-range constant indices, where SDVE
/// cannot remove a dead insert before hitting its depth limit.
static bool canSkipDemandedEltsInInsertChain(InsertElementInst &IE,
                                             unsigned VWidth,
                                             unsigned DepthLimit) {
  // Only skip chain nodes that feed another insertelement; the final chain root
  // still runs the full query.
  if (!IE.hasOneUse())
    return false;
  auto *UserIE = dyn_cast<InsertElementInst>(IE.user_back());
  if (!UserIE || UserIE->getOperand(0) != &IE)
    return false;

  SmallBitVector SeenIndices(VWidth);
  auto HasNewIndexInRange = [&](InsertElementInst &Insert) {
    auto *Idx = dyn_cast<ConstantInt>(Insert.getOperand(2));
    // Let the normal SDVE path handle variable or out-of-range indices. The
    // latter may simplify the chain and must not be passed to getZExtValue().
    if (!Idx || Idx->getValue().uge(VWidth))
      return false;

    unsigned Index = Idx->getZExtValue();
    if (SeenIndices.test(Index))
      return false;

    SeenIndices.set(Index);
    return true;
  };

  auto *Cur = &IE;
  for (unsigned I = 0; I != DepthLimit; ++I) {
    // This loop scans the same base-chain window that the SDVE query would
    // inspect before hitting its depth limit. With distinct insert indices in
    // that window, the all-lanes query cannot remove a dead insert; with
    // VWidth > DepthLimit, it also cannot narrow demand to a single lane.
    if (!HasNewIndexInRange(*Cur))
      return false;

    Value *Base = Cur->getOperand(0);
    if (match(Base, m_Poison()))
      return true;

    Cur = dyn_cast<InsertElementInst>(Base);
    if (!Cur || !Cur->hasOneUse())
      return false;
  }

  return true;
}

/// 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: {
    unsigned DepthLimit = SimplifyDemandedVectorEltsDepthLimit;
    auto *IE = cast<InsertElementInst>(I);
    // Skip only when SDVE cannot simplify this insert chain before the limit.
    if (Depth == 0 && DemandedElts.isAllOnes() && VWidth > DepthLimit &&
        canSkipDemandedEltsInInsertChain(*IE, VWidth, DepthLimit))
      return nullptr;

    // 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(), equal_to(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;
      };

      User *ShufBO = findShufBO(/* MatchShufAsOp0 */ true);
      if (!ShufBO)
        ShufBO = findShufBO(/* MatchShufAsOp0 */ false);
      if (ShufBO) {
        auto *ShufBOI = cast<Instruction>(ShufBO);
        ShufBOI->andIRFlags(BO);
        Worklist.add(ShufBOI);
        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);

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

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

  switch (Mask) {
  case fcNegZero:
    return ConstantFP::getZero(Ty, true);
  case fcPosInf:
    return ConstantFP::getInfinity(Ty);
  case fcNegInf:
    return ConstantFP::getInfinity(Ty, true);
  case fcQNan:
    // Payload bits cannot be dropped for pure signbit operations.
    return IsCanonicalizing ? ConstantFP::getQNaN(Ty) : nullptr;
  default:
    return nullptr;
  }
}

/// Perform multiple-use aware simplfications for fabs(\p Src). Returns a
/// replacement value if it's simplified, otherwise nullptr. Updates \p Known
/// with the known fpclass if not simplified.
static Value *simplifyDemandedFPClassFabs(KnownFPClass &Known, Value *Src,
                                          FPClassTest DemandedMask,
                                          KnownFPClass KnownSrc, bool NSZ) {
  if ((DemandedMask & fcNan) == fcNone)
    KnownSrc.knownNot(fcNan);
  if ((DemandedMask & fcInf) == fcNone)
    KnownSrc.knownNot(fcInf);

  if (KnownSrc.getSignBit() == false ||
      ((DemandedMask & fcNan) == fcNone && KnownSrc.isKnownNever(fcNegative)))
    return Src;

  // If the only sign bit difference is due to -0, ignore it with nsz
  if (NSZ &&
      KnownSrc.isKnownNever(KnownFPClass::OrderedLessThanZeroMask | fcNan))
    return Src;

  Known = KnownFPClass::fabs(KnownSrc);
  Known.knownNot(~DemandedMask);
  return nullptr;
}

/// Try to set an inferred no-nans or no-infs in \p FMF. \p ValidResults is a
/// mask of known valid results for the operator (already computed from the
/// result, and the known operand inputs in \p Known)
static FastMathFlags inferFastMathValueFlags(FastMathFlags FMF,
                                             FPClassTest ValidResults,
                                             ArrayRef<KnownFPClass> Known) {
  if (!FMF.noNaNs() && (ValidResults & fcNan) == fcNone) {
    if (all_of(Known, [](const KnownFPClass KnownSrc) {
          return KnownSrc.isKnownNeverNaN();
        }))
      FMF.setNoNaNs();
  }

  if (!FMF.noInfs() && (ValidResults & fcInf) == fcNone) {
    if (all_of(Known, [](const KnownFPClass KnownSrc) {
          return KnownSrc.isKnownNeverInfinity();
        }))
      FMF.setNoInfs();
  }

  return FMF;
}

static FPClassTest adjustDemandedMaskFromFlags(FPClassTest DemandedMask,
                                               FastMathFlags FMF) {
  if (FMF.noNaNs())
    DemandedMask &= ~fcNan;

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

/// Apply epilog fixups to a floating-point intrinsic. See if the result can
/// fold to a constant, or apply fast math flags.
static Value *simplifyDemandedFPClassResult(Instruction *FPOp,
                                            FastMathFlags FMF,
                                            FPClassTest DemandedMask,
                                            KnownFPClass &Known,
                                            ArrayRef<KnownFPClass> KnownSrcs) {
  FPClassTest ValidResults = DemandedMask & Known.getKnownFPClasses();
  Constant *SingleVal = getFPClassConstant(FPOp->getType(), ValidResults,
                                           /*IsCanonicalizing=*/true);
  if (SingleVal)
    return SingleVal;

  FastMathFlags InferredFMF =
      inferFastMathValueFlags(FMF, ValidResults, KnownSrcs);
  if (InferredFMF != FMF) {
    FPOp->dropUBImplyingAttrsAndMetadata();
    FPOp->setFastMathFlags(InferredFMF);
    return FPOp;
  }

  return nullptr;
}

/// Perform multiple-use aware simplfications for fneg(fabs(\p Src)). Returns a
/// replacement value if it's simplified, otherwise nullptr. Updates \p Known
/// with the known fpclass if not simplified.
static Value *simplifyDemandedFPClassFnegFabs(KnownFPClass &Known, Value *Src,
                                              FPClassTest DemandedMask,
                                              KnownFPClass KnownSrc, bool NSZ) {
  if ((DemandedMask & fcNan) == fcNone)
    KnownSrc.knownNot(fcNan);
  if ((DemandedMask & fcInf) == fcNone)
    KnownSrc.knownNot(fcInf);

  // If the source value is known negative, we can directly fold to it.
  if (KnownSrc.getSignBit() == true)
    return Src;

  // If the only sign bit difference is for 0, ignore it with nsz.
  if (NSZ &&
      KnownSrc.isKnownNever(KnownFPClass::OrderedGreaterThanZeroMask | fcNan))
    return Src;

  Known = KnownFPClass::fneg(KnownFPClass::fabs(KnownSrc));
  Known.knownNot(~DemandedMask);
  return nullptr;
}

static Value *simplifyDemandedFPClassCopysignMag(Value *MagSrc,
                                                 FPClassTest DemandedMask,
                                                 KnownFPClass KnownSrc,
                                                 bool NSZ) {
  if (NSZ) {
    constexpr FPClassTest NegOrZero = fcNegative | fcPosZero;
    constexpr FPClassTest PosOrZero = fcPositive | fcNegZero;

    if ((DemandedMask & ~NegOrZero) == fcNone &&
        KnownSrc.isKnownAlways(NegOrZero))
      return MagSrc;

    if ((DemandedMask & ~PosOrZero) == fcNone &&
        KnownSrc.isKnownAlways(PosOrZero))
      return MagSrc;
  } else {
    if ((DemandedMask & ~fcNegative) == fcNone && KnownSrc.getSignBit() == true)
      return MagSrc;

    if ((DemandedMask & ~fcPositive) == fcNone &&
        KnownSrc.getSignBit() == false)
      return MagSrc;
  }

  return nullptr;
}

static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
                              const CallInst *CI, FPClassTest DemandedMask,
                              KnownFPClass KnownLHS, KnownFPClass KnownRHS,
                              const Function &F, bool NSZ) {
  bool OrderedZeroSign = !NSZ;

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

    // If one operand is known greater than the other, it must be that
    // operand unless the other is a nan.
    if (cannotOrderStrictlyLess(KnownLHS.getKnownFPClasses(),
                                KnownRHS.getKnownFPClasses(),
                                OrderedZeroSign) &&
        KnownRHS.isKnownNever(fcNan))
      return CI->getArgOperand(0);

    if (cannotOrderStrictlyGreater(KnownLHS.getKnownFPClasses(),
                                   KnownRHS.getKnownFPClasses(),
                                   OrderedZeroSign) &&
        KnownLHS.isKnownNever(fcNan))
      return CI->getArgOperand(1);

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

    // If one operand is known less than the other, it must be that operand
    // unless the other is a nan.
    if (cannotOrderStrictlyGreater(KnownLHS.getKnownFPClasses(),
                                   KnownRHS.getKnownFPClasses(),
                                   OrderedZeroSign) &&
        KnownRHS.isKnownNever(fcNan))
      return CI->getArgOperand(0);

    if (cannotOrderStrictlyLess(KnownLHS.getKnownFPClasses(),
                                KnownRHS.getKnownFPClasses(),
                                OrderedZeroSign) &&
        KnownLHS.isKnownNever(fcNan))
      return CI->getArgOperand(1);

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

    if (cannotOrderStrictlyLess(KnownLHS.getKnownFPClasses(),
                                KnownRHS.getKnownFPClasses(),
                                OrderedZeroSign) &&
        KnownLHS.isKnownNever(fcNan))
      return CI->getArgOperand(0);

    if (cannotOrderStrictlyGreater(KnownLHS.getKnownFPClasses(),
                                   KnownRHS.getKnownFPClasses(),
                                   OrderedZeroSign) &&
        KnownRHS.isKnownNever(fcNan))
      return CI->getArgOperand(1);

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

    if (cannotOrderStrictlyGreater(KnownLHS.getKnownFPClasses(),
                                   KnownRHS.getKnownFPClasses(),
                                   OrderedZeroSign) &&
        KnownLHS.isKnownNever(fcNan))
      return CI->getArgOperand(0);

    if (cannotOrderStrictlyLess(KnownLHS.getKnownFPClasses(),
                                KnownRHS.getKnownFPClasses(),
                                OrderedZeroSign) &&
        KnownRHS.isKnownNever(fcNan))
      return CI->getArgOperand(1);

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

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

  return getFPClassConstant(CI->getType(), Known.getKnownFPClasses(),
                            /*IsCanonicalizing=*/true);
}

static Value *
simplifyDemandedUseFPClassFPTrunc(InstCombinerImpl &IC, Instruction &I,
                                  FastMathFlags FMF, FPClassTest DemandedMask,
                                  KnownFPClass &Known, const SimplifyQuery &SQ,
                                  unsigned Depth) {

  FPClassTest SrcDemandedMask = DemandedMask;
  if (DemandedMask & fcNan)
    SrcDemandedMask |= fcNan;

  // Zero results may have been rounded from subnormal or normal sources.
  if (DemandedMask & fcNegZero)
    SrcDemandedMask |= fcNegSubnormal | fcNegNormal;
  if (DemandedMask & fcPosZero)
    SrcDemandedMask |= fcPosSubnormal | fcPosNormal;

  // Subnormal results may have been normal in the source type
  if (DemandedMask & fcNegSubnormal)
    SrcDemandedMask |= fcNegNormal;
  if (DemandedMask & fcPosSubnormal)
    SrcDemandedMask |= fcPosNormal;

  if (DemandedMask & fcPosInf)
    SrcDemandedMask |= fcPosNormal;
  if (DemandedMask & fcNegInf)
    SrcDemandedMask |= fcNegNormal;

  KnownFPClass KnownSrc;
  if (IC.SimplifyDemandedFPClass(&I, 0, SrcDemandedMask, KnownSrc, SQ,
                                 Depth + 1))
    return &I;

  Known = KnownFPClass::fptrunc(KnownSrc);
  Known.knownNot(~DemandedMask);

  return simplifyDemandedFPClassResult(&I, FMF, DemandedMask, Known,
                                       {KnownSrc});
}

Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
                                                    FPClassTest DemandedMask,
                                                    KnownFPClass &Known,
                                                    const SimplifyQuery &SQ,
                                                    unsigned Depth) {
  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
  assert(Known == KnownFPClass() && "expected uninitialized state");

  Type *VTy = I->getType();

  FastMathFlags FMF;
  if (auto *FPOp = dyn_cast<FPMathOperator>(I)) {
    FMF = FPOp->getFastMathFlags();
    DemandedMask = adjustDemandedMaskFromFlags(DemandedMask, FMF);
  }

  switch (I->getOpcode()) {
  case Instruction::FNeg: {
    // Special case fneg(fabs(x))

    Value *FNegSrc = I->getOperand(0);
    Value *FNegFAbsSrc;
    if (match(FNegSrc, m_OneUse(m_FAbs(m_Value(FNegFAbsSrc))))) {
      KnownFPClass KnownSrc;
      if (SimplifyDemandedFPClass(cast<Instruction>(FNegSrc), 0,
                                  llvm::unknown_sign(DemandedMask), KnownSrc,
                                  SQ, Depth + 1))
        return I;

      FastMathFlags FabsFMF = cast<FPMathOperator>(FNegSrc)->getFastMathFlags();
      FPClassTest ThisDemandedMask =
          adjustDemandedMaskFromFlags(DemandedMask, FabsFMF);

      bool IsNSZ = FMF.noSignedZeros() || FabsFMF.noSignedZeros();
      if (Value *Simplified = simplifyDemandedFPClassFnegFabs(
              Known, FNegFAbsSrc, ThisDemandedMask, KnownSrc, IsNSZ))
        return Simplified;

      if ((ThisDemandedMask & fcNan) == fcNone)
        KnownSrc.knownNot(fcNan);
      if ((ThisDemandedMask & fcInf) == fcNone)
        KnownSrc.knownNot(fcInf);

      // fneg(fabs(x)) => fneg(x)
      if (KnownSrc.getSignBit() == false)
        return replaceOperand(*I, 0, FNegFAbsSrc);

      // fneg(fabs(x)) => fneg(x), ignoring -0 if nsz.
      if (IsNSZ &&
          KnownSrc.isKnownNever(KnownFPClass::OrderedLessThanZeroMask | fcNan))
        return replaceOperand(*I, 0, FNegFAbsSrc);

      break;
    }

    if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known, SQ,
                                Depth + 1))
      return I;
    Known.fneg();
    Known.knownNot(~DemandedMask);
    break;
  }
  case Instruction::FAdd:
  case Instruction::FSub: {
    KnownFPClass KnownLHS, KnownRHS;

    // fadd x, x can be handled more aggressively.
    if (I->getOperand(0) == I->getOperand(1) &&
        I->getOpcode() == Instruction::FAdd &&
        isGuaranteedNotToBeUndef(I->getOperand(0), SQ.AC, SQ.CtxI, SQ.DT,
                                 Depth + 1)) {
      Type *EltTy = VTy->getScalarType();
      DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());

      FPClassTest SrcDemandedMask = DemandedMask;
      if (DemandedMask & fcNan)
        SrcDemandedMask |= fcNan;

      // Doubling a subnormal could have resulted in a normal value.
      if (DemandedMask & fcPosNormal)
        SrcDemandedMask |= fcPosSubnormal;
      if (DemandedMask & fcNegNormal)
        SrcDemandedMask |= fcNegSubnormal;

      // Doubling a subnormal may produce 0 if FTZ/DAZ.
      if (Mode != DenormalMode::getIEEE()) {
        if (DemandedMask & fcPosZero) {
          SrcDemandedMask |= fcPosSubnormal;

          if (Mode.inputsMayBePositiveZero() || Mode.outputsMayBePositiveZero())
            SrcDemandedMask |= fcNegSubnormal;
        }

        if (DemandedMask & fcNegZero)
          SrcDemandedMask |= fcNegSubnormal;
      }

      // Doubling a normal could have resulted in an infinity.
      if (DemandedMask & fcPosInf)
        SrcDemandedMask |= fcPosNormal;
      if (DemandedMask & fcNegInf)
        SrcDemandedMask |= fcNegNormal;

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

      Known = KnownFPClass::fadd_self(KnownLHS, Mode);
      KnownRHS = KnownLHS;
    } else {
      FPClassTest SrcDemandedMask = fcFinite;

      // inf + (-inf) = nan
      if (DemandedMask & fcNan)
        SrcDemandedMask |= fcNan | fcInf;

      if (DemandedMask & fcInf)
        SrcDemandedMask |= fcInf;

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

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

      Known = I->getOpcode() == Instruction::FAdd
                  ? KnownFPClass::fadd(KnownLHS, KnownRHS, Mode)
                  : KnownFPClass::fsub(KnownLHS, KnownRHS, Mode);
    }

    Known.knownNot(~DemandedMask);

    if (Constant *SingleVal = getFPClassConstant(VTy, Known.getKnownFPClasses(),
                                                 /*IsCanonicalizing=*/true))
      return SingleVal;

    // Propagate known result to simplify edge case checks.
    bool ResultNotNan = (DemandedMask & fcNan) == fcNone;

    // With nnan: X + {+/-}Inf --> {+/-}Inf
    if (ResultNotNan && I->getOpcode() == Instruction::FAdd &&
        KnownRHS.isKnownAlways(fcInf | fcNan) && KnownLHS.isKnownNever(fcNan))
      return I->getOperand(1);

    // With nnan: {+/-}Inf + X --> {+/-}Inf
    // With nnan: {+/-}Inf - X --> {+/-}Inf
    if (ResultNotNan && KnownLHS.isKnownAlways(fcInf | fcNan) &&
        KnownRHS.isKnownNever(fcNan))
      return I->getOperand(0);

    FastMathFlags InferredFMF = inferFastMathValueFlags(
        FMF, Known.getKnownFPClasses(), {KnownLHS, KnownRHS});
    if (InferredFMF != FMF) {
      I->setFastMathFlags(InferredFMF);
      return I;
    }

    return nullptr;
  }
  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 | fcNan;

      // 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;

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

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

      if (Constant *Folded = getFPClassConstant(VTy, Known.getKnownFPClasses(),
                                                /*IsCanonicalizing=*/true))
        return Folded;

      if (Known.isKnownAlways(fcPosZero | fcPosInf | fcNan) &&
          KnownLHS.isKnownNever(fcSubnormal | fcNormal)) {
        // 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.CreateFAbs(X, FMF);
        Fabs->takeName(I);
        return Fabs;
      }

      return nullptr;
    }

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

    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)) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // => 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())) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // => 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)) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // => 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())) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // => 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))) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // Note: Dropping canonicalize
      Value *Neg = Builder.CreateFNegFMF(X, FMF);
      Neg->takeName(I);
      return Neg;
    }

    if (KnownRHS.isKnownAlways(fcInf | fcNan) &&
        (KnownLHS.isKnownNeverNaN() &&
         KnownLHS.cannotBeOrderedGreaterEqZero(Mode))) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // Note: Dropping canonicalize
      Value *Neg = Builder.CreateFNegFMF(Y, FMF);
      Neg->takeName(I);
      return Neg;
    }

    Known = KnownFPClass::fmul(KnownLHS, KnownRHS, Mode);
    Known.knownNot(~DemandedMask);

    if (Constant *SingleVal = getFPClassConstant(VTy, Known.getKnownFPClasses(),
                                                 /*IsCanonicalizing=*/true))
      return SingleVal;

    FastMathFlags InferredFMF = inferFastMathValueFlags(
        FMF, Known.getKnownFPClasses(), {KnownLHS, KnownRHS});
    if (InferredFMF != FMF) {
      I->setFastMathFlags(InferredFMF);
      return I;
    }

    return nullptr;
  }
  case Instruction::FDiv: {
    Value *X = I->getOperand(0);
    Value *Y = I->getOperand(1);
    if (X == Y &&
        isGuaranteedNotToBeUndef(X, SQ.AC, SQ.CtxI, SQ.DT, Depth + 1)) {
      // If the source is 0, inf or nan, the result is a nan
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      Value *IsZeroOrNan = Builder.CreateFCmpFMF(
          FCmpInst::FCMP_UEQ, I->getOperand(0), ConstantFP::getZero(VTy), FMF);

      Value *Fabs = Builder.CreateFAbs(I->getOperand(0), FMF);
      Value *IsInfOrNan = Builder.CreateFCmpFMF(
          FCmpInst::FCMP_UEQ, Fabs, ConstantFP::getInfinity(VTy), FMF);

      Value *IsInfOrZeroOrNan = Builder.CreateOr(IsInfOrNan, IsZeroOrNan);

      return Builder.CreateSelectFMFWithUnknownProfile(
          IsInfOrZeroOrNan, ConstantFP::getQNaN(VTy),
          ConstantFP::get(
              VTy, APFloat::getOne(VTy->getScalarType()->getFltSemantics())),
          FMF, DEBUG_TYPE);
    }

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

    // Every output class could require denormal inputs (except for the
    // degenerate case of only-nan results, without DAZ).
    FPClassTest SrcDemandedMask = (DemandedMask & fcNan) | fcSubnormal;

    // Normal inputs may result in underflow.
    // x / x = 1.0 for non0/inf/nan
    // -x = +y / -z
    // -x = -y / +z
    if (DemandedMask & (fcSubnormal | fcNormal))
      SrcDemandedMask |= fcNormal;

    if (DemandedMask & fcNan) {
      // 0 / 0 = nan
      // inf / inf = nan

      // Subnormal is added in case of DAZ, but this isn't strictly
      // necessary. Every other input class implies a possible subnormal source,
      // so this only could matter in the degenerate case of only-nan results.
      SrcDemandedMask |= fcZero | fcInf | fcNan;
    }

    // Zero outputs may be the result of underflow.
    if (DemandedMask & fcZero)
      SrcDemandedMask |= fcNormal | fcSubnormal;

    FPClassTest LHSDemandedMask = SrcDemandedMask;
    FPClassTest RHSDemandedMask = SrcDemandedMask;

    // 0 / inf = 0
    if (DemandedMask & fcZero) {
      assert((LHSDemandedMask & fcSubnormal) &&
             "should not have to worry about daz here");
      LHSDemandedMask |= fcZero;
      RHSDemandedMask |= fcInf;
    }

    // x / 0 = inf
    // large_normal / small_normal = inf
    // inf / 1 = inf
    // large_normal / subnormal = inf
    if (DemandedMask & fcInf) {
      LHSDemandedMask |= fcInf | fcNormal | fcSubnormal;
      RHSDemandedMask |= fcZero | fcSubnormal | fcNormal;
    }

    KnownFPClass KnownLHS, KnownRHS;
    if (SimplifyDemandedFPClass(I, 0, LHSDemandedMask, KnownLHS, SQ,
                                Depth + 1) ||
        SimplifyDemandedFPClass(I, 1, RHSDemandedMask, KnownRHS, SQ, Depth + 1))
      return I;

    bool ResultNotNan = (DemandedMask & fcNan) == fcNone;
    bool ResultNotInf = (DemandedMask & fcInf) == fcNone;

    // Replacing 0/x with a zero is only valid when the divisor can't be
    // (logical) zero, since 0/0 is NaN -- unless NaN results aren't demanded. A
    // subnormal divisor can flush to zero under a flushing denormal mode.
    bool CanIgnoreZeroByZeroNan =
        ResultNotNan || KnownRHS.isKnownNeverLogicalZero(Mode);

    // nsz [+-]0 / x -> 0
    if (FMF.noSignedZeros() && KnownLHS.isKnownAlways(fcZero) &&
        KnownRHS.isKnownNeverNaN() && CanIgnoreZeroByZeroNan)
      return ConstantFP::getZero(VTy);

    if (KnownLHS.isKnownAlways(fcPosZero) && KnownRHS.isKnownNeverNaN() &&
        CanIgnoreZeroByZeroNan) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // nnan +0 / x -> copysign(0, rhs)
      // TODO: -0 / x => copysign(0, fneg(rhs))
      Value *Copysign = Builder.CreateCopySign(X, Y, FMF);
      Copysign->takeName(I);
      return Copysign;
    }

    if (!ResultNotInf &&
        ((ResultNotNan || (KnownLHS.isKnownNeverNaN() &&
                           KnownLHS.isKnownNeverLogicalZero(Mode))) &&
         (KnownRHS.isKnownAlways(fcPosZero) ||
          (FMF.noSignedZeros() && KnownRHS.isKnownAlways(fcZero))))) {
      IRBuilderBase::InsertPointGuard Guard(Builder);
      Builder.SetInsertPoint(I);

      // nnan x / 0 => copysign(inf, x);
      // nnan nsz x / -0 => copysign(inf, x);
      Value *Copysign =
          Builder.CreateCopySign(ConstantFP::getInfinity(VTy), X, FMF);
      Copysign->takeName(I);
      return Copysign;
    }

    // nnan ninf X / [-]0.0 -> poison
    if (ResultNotNan && ResultNotInf && KnownRHS.isKnownAlways(fcZero))
      return PoisonValue::get(VTy);

    Known = KnownFPClass::fdiv(KnownLHS, KnownRHS, Mode);
    Known.knownNot(~DemandedMask);

    if (Constant *SingleVal = getFPClassConstant(VTy, Known.getKnownFPClasses(),
                                                 /*IsCanonicalizing=*/true))
      return SingleVal;

    FastMathFlags InferredFMF = inferFastMathValueFlags(
        FMF, Known.getKnownFPClasses(), {KnownLHS, KnownRHS});
    if (InferredFMF != FMF) {
      I->setFastMathFlags(InferredFMF);
      return I;
    }

    return nullptr;
  }
  case Instruction::FPTrunc:
    return simplifyDemandedUseFPClassFPTrunc(*this, *I, FMF, DemandedMask,
                                             Known, SQ, Depth);
  case Instruction::FPExt: {
    FPClassTest SrcDemandedMask = DemandedMask;
    if (DemandedMask & fcNan)
      SrcDemandedMask |= fcNan;

    // 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, SQ, 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);
    Known.knownNot(~DemandedMask);

    return simplifyDemandedFPClassResult(I, FMF, DemandedMask, Known,
                                         {KnownSrc});
  }
  case Instruction::Call: {
    CallInst *CI = cast<CallInst>(I);
    const Intrinsic::ID IID = CI->getIntrinsicID();
    switch (IID) {
    case Intrinsic::fabs: {
      KnownFPClass KnownSrc;
      if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask),
                                  KnownSrc, SQ, Depth + 1))
        return I;

      if (Value *Simplified = simplifyDemandedFPClassFabs(
              Known, CI->getArgOperand(0), DemandedMask, KnownSrc,
              FMF.noSignedZeros()))
        return Simplified;
      break;
    }
    case Intrinsic::arithmetic_fence:
      if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, SQ, Depth + 1))
        return I;
      break;
    case Intrinsic::copysign: {
      // Flip on more potentially demanded classes
      const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
      KnownFPClass KnownMag;
      if (SimplifyDemandedFPClass(CI, 0, DemandedMaskAnySign, KnownMag, SQ,
                                  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;
      }

      if (Value *Simplified = simplifyDemandedFPClassCopysignMag(
              CI->getArgOperand(0), DemandedMask, KnownMag,
              FMF.noSignedZeros()))
        return Simplified;

      KnownFPClass KnownSign =
          computeKnownFPClass(CI->getArgOperand(1), fcAllFlags, SQ, Depth + 1);
      if (KnownMag.getSignBit() && KnownSign.getSignBit() &&
          *KnownMag.getSignBit() == *KnownSign.getSignBit())
        return CI->getOperand(0);

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

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

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

      Known = KnownFPClass::copysign(KnownMag, KnownSign);
      Known.knownNot(~DemandedMask);
      break;
    }
    case Intrinsic::fma:
    case Intrinsic::fmuladd: {
      // We can't do any simplification on the source besides stripping out
      // unneeded nans.
      FPClassTest SrcDemandedMask = DemandedMask | ~fcNan;
      if (DemandedMask & fcNan)
        SrcDemandedMask |= fcNan;

      KnownFPClass KnownSrc[3];

      Type *EltTy = VTy->getScalarType();
      if (CI->getArgOperand(0) == CI->getArgOperand(1) &&
          isGuaranteedNotToBeUndef(CI->getArgOperand(0), SQ.AC, SQ.CtxI, SQ.DT,
                                   Depth + 1)) {
        if (SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownSrc[0], SQ,
                                    Depth + 1) ||
            SimplifyDemandedFPClass(CI, 2, SrcDemandedMask, KnownSrc[2], SQ,
                                    Depth + 1))
          return I;

        KnownSrc[1] = KnownSrc[0];
        DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
        Known = KnownFPClass::fma_square(KnownSrc[0], KnownSrc[2], Mode);
      } else {
        for (int OpIdx = 0; OpIdx != 3; ++OpIdx) {
          if (SimplifyDemandedFPClass(CI, OpIdx, SrcDemandedMask,
                                      KnownSrc[OpIdx], SQ, Depth + 1))
            return CI;
        }

        DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
        Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
      }

      return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
                                           {KnownSrc});
    }
    case Intrinsic::maximum:
    case Intrinsic::minimum:
    case Intrinsic::maximumnum:
    case Intrinsic::minimumnum:
    case Intrinsic::maxnum:
    case Intrinsic::minnum: {
      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) == fcNone)
              ? DemandedMask | ~fcNan
              : fcAllFlags;

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

      Value *Simplified =
          simplifyDemandedFPClassMinMax(Known, IID, CI, DemandedMask, KnownLHS,
                                        KnownRHS, F, FMF.noSignedZeros());
      if (Simplified)
        return Simplified;

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

      FPClassTest ValidResults = DemandedMask & Known.getKnownFPClasses();
      FastMathFlags InferredFMF = FMF;

      if (!FMF.noSignedZeros()) {
        // Add NSZ flag if we know the result will not be sensitive to the sign
        // of 0.
        FPClassTest ZeroMask = fcZero;

        Type *EltTy = VTy->getScalarType();
        DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
        if (Mode != DenormalMode::getIEEE())
          ZeroMask |= fcSubnormal;

        bool ResultNotLogical0 = (ValidResults & ZeroMask) == fcNone;
        if (ResultNotLogical0 || ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
                                   KnownRHS.isKnownNeverLogicalPosZero(Mode)) &&
                                  (KnownLHS.isKnownNeverLogicalPosZero(Mode) ||
                                   KnownRHS.isKnownNeverLogicalNegZero(Mode))))
          InferredFMF.setNoSignedZeros(true);
      }

      if (!FMF.noNaNs() &&
          ((PropagateNaN && (ValidResults & fcNan) == fcNone) ||
           (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN()))) {
        CI->dropUBImplyingAttrsAndMetadata();
        InferredFMF.setNoNaNs(true);
      }

      if (InferredFMF != FMF) {
        CI->setFastMathFlags(InferredFMF);
        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 & fcNan)
        SrcDemandedMask |= 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, SQ,
                                  Depth + 1))
        return I;

      // 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);
      Known.knownNot(~DemandedMask);

      return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
                                           KnownSrc);
    }
    case Intrinsic::log:
    case Intrinsic::log2:
    case Intrinsic::log10: {
      FPClassTest DemandedSrcMask = DemandedMask & (fcNan | fcPosInf);
      if (DemandedMask & fcNan)
        DemandedSrcMask |= fcNan;

      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, SQ,
                                  Depth + 1))
        return I;

      Known = KnownFPClass::log(KnownSrc, Mode);
      Known.knownNot(~DemandedMask);

      return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
                                           KnownSrc);
    }
    case Intrinsic::sqrt: {
      FPClassTest DemandedSrcMask =
          DemandedMask & (fcNegZero | fcPositive | fcNan);

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

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

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

      // Infer the source cannot be negative if the result cannot be nan.
      if ((DemandedMask & fcNan) == fcNone)
        KnownSrc.knownNot((fcNegative & ~fcNegZero) | fcNan);

      // Infer the source cannot be +inf if the result is not +nf
      if ((DemandedMask & fcPosInf) == fcNone)
        KnownSrc.knownNot(fcPosInf);

      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);
      Known.knownNot(~DemandedMask);

      if (Known.getKnownFPClasses() == fcZero) {
        if (FMF.noSignedZeros())
          return ConstantFP::getZero(VTy);
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(CI);

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

      return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
                                           {KnownSrc});
    }
    case Intrinsic::ldexp: {
      FPClassTest SrcDemandedMask = DemandedMask & fcInf;
      if (DemandedMask & fcNan)
        SrcDemandedMask |= fcNan;

      if (DemandedMask & fcPosInf)
        SrcDemandedMask |= fcPosNormal | fcPosSubnormal;
      if (DemandedMask & fcNegInf)
        SrcDemandedMask |= fcNegNormal | fcNegSubnormal;

      if (DemandedMask & (fcPosNormal | fcPosSubnormal))
        SrcDemandedMask |= fcPosNormal | fcPosSubnormal;
      if (DemandedMask & (fcNegNormal | fcNegSubnormal))
        SrcDemandedMask |= fcNegNormal | fcNegSubnormal;

      if (DemandedMask & fcPosZero)
        SrcDemandedMask |= fcPosFinite;
      if (DemandedMask & fcNegZero)
        SrcDemandedMask |= fcNegFinite;

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

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

      KnownBits KnownExpBits =
          ::computeKnownBits(CI->getArgOperand(1), SQ, Depth + 1);

      Known = KnownFPClass::ldexp(KnownSrc, KnownExpBits, FltSem, Mode);
      Known.knownNot(~DemandedMask);

      return simplifyDemandedFPClassResult(CI, FMF, DemandedMask, Known,
                                           {KnownSrc});
    }
    case Intrinsic::trunc:
    case Intrinsic::floor:
    case Intrinsic::ceil:
    case Intrinsic::rint:
    case Intrinsic::nearbyint:
    case Intrinsic::round:
    case Intrinsic::roundeven: {
      FPClassTest DemandedSrcMask = DemandedMask;
      if (DemandedMask & fcNan)
        DemandedSrcMask |= fcNan;

      // 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, SQ,
                                  Depth + 1))
        return I;

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

      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());

      Known.knownNot(~DemandedMask);

      if (Constant *SingleVal =
              getFPClassConstant(VTy, Known.getKnownFPClasses(),
                                 /*IsCanonicalizing=*/true))
        return SingleVal;

      if ((IID == Intrinsic::trunc || IsRoundNearestOrTrunc) &&
          KnownSrc.isKnownAlways(fcZero | fcSubnormal)) {
        IRBuilderBase::InsertPointGuard Guard(Builder);
        Builder.SetInsertPoint(CI);

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

      FastMathFlags InferredFMF =
          inferFastMathValueFlags(FMF, Known.getKnownFPClasses(), KnownSrc);
      if (InferredFMF != FMF) {
        CI->dropUBImplyingAttrsAndMetadata();
        CI->setFastMathFlags(InferredFMF);
        return CI;
      }

      return nullptr;
    }
    case Intrinsic::fptrunc_round:
      return simplifyDemandedUseFPClassFPTrunc(*this, *CI, FMF, DemandedMask,
                                               Known, SQ, Depth);
    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, SQ,
                                    Depth + 1))
          return I;

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

        if (Constant *SingleVal =
                getFPClassConstant(VTy, Known.getKnownFPClasses()))
          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() && (Mode == DenormalMode::getIEEE() ||
                                           KnownSrc.isKnownNeverSubnormal()))
          return CI->getArgOperand(0);

        FastMathFlags InferredFMF =
            inferFastMathValueFlags(FMF, Known.getKnownFPClasses(), KnownSrc);
        if (InferredFMF != FMF) {
          CI->dropUBImplyingAttrsAndMetadata();
          CI->setFastMathFlags(InferredFMF);
          return CI;
        }

        return nullptr;
      }

      [[fallthrough]];
    }
    default:
      Known = computeKnownFPClass(I, DemandedMask, SQ, Depth + 1);
      Known.knownNot(~DemandedMask);
      break;
    }

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

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

    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);
    Known.knownNot(~DemandedMask);
    break;
  }
  case Instruction::ExtractElement: {
    // TODO: Handle demanded element mask
    if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, SQ, Depth + 1))
      return I;
    Known.knownNot(~DemandedMask);
    break;
  }
  case Instruction::InsertElement: {
    KnownFPClass KnownInserted, KnownVec;
    if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownInserted, SQ,
                                Depth + 1) ||
        SimplifyDemandedFPClass(I, 0, DemandedMask, KnownVec, SQ, Depth + 1))
      return I;

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

    // TODO: This is overly conservative and should consider demanded elements,
    // and splats.
    Known = KnownLHS | KnownRHS;
    Known.knownNot(~DemandedMask);
    break;
  }
  case Instruction::InsertValue: {
    KnownFPClass KnownAgg, KnownElt;
    if (SimplifyDemandedFPClass(I, 0, DemandedMask, KnownAgg, SQ, Depth + 1) ||
        SimplifyDemandedFPClass(I, 1, DemandedMask, KnownElt, SQ, Depth + 1))
      return I;

    Known = KnownAgg | KnownElt;
    break;
  }
  case Instruction::ExtractValue: {
    Value *ExtractSrc;
    if (match(I, m_ExtractValue<0>(m_OneUse(m_Value(ExtractSrc))))) {
      if (auto *II = dyn_cast<IntrinsicInst>(ExtractSrc)) {
        const Intrinsic::ID IID = II->getIntrinsicID();
        switch (IID) {
        case Intrinsic::frexp: {
          FPClassTest SrcDemandedMask = fcNone;
          if (DemandedMask & fcNan)
            SrcDemandedMask |= fcNan;
          if (DemandedMask & fcNegFinite)
            SrcDemandedMask |= fcNegFinite;
          if (DemandedMask & fcPosFinite)
            SrcDemandedMask |= fcPosFinite;
          if (DemandedMask & fcPosInf)
            SrcDemandedMask |= fcPosInf;
          if (DemandedMask & fcNegInf)
            SrcDemandedMask |= fcNegInf;

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

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

          Known = KnownFPClass::frexp_mant(KnownSrc, Mode);
          Known.setKnownFPClasses(Known.getKnownFPClasses() & DemandedMask);

          if (Constant *SingleVal =
                  getFPClassConstant(VTy, Known.getKnownFPClasses(),
                                     /*IsCanonicalizing=*/true))
            return SingleVal;

          if (Known.isKnownAlways(fcInf | fcNan))
            return II->getArgOperand(0);

          return nullptr;
        }
        default:
          break;
        }
      }
    }

    KnownFPClass KnownSrc;
    if (SimplifyDemandedFPClass(I, 0, DemandedMask, KnownSrc, SQ, Depth + 1))
      return I;
    Known = KnownSrc;
    break;
  }
  case Instruction::PHI: {
    const unsigned PhiRecursionLimit = MaxAnalysisRecursionDepth - 2;
    if (Depth >= PhiRecursionLimit)
      break;

    PHINode *P = cast<PHINode>(I);
    SimplifyQuery ContextSQ = SQ.getWithoutCondContext();

    bool First = true;
    bool Changed = false;
    for (unsigned I = 0, E = P->getNumIncomingValues(); I != E; ++I) {
      // TODO: Better support for self recursive phi
      BasicBlock *PredBB = P->getIncomingBlock(I);
      const Instruction *CtxI = PredBB->getTerminator();

      // Attempt to simplify all incoming edges at a time. If we simplify one
      // incoming edge, the phi may fold away, losing information on a later
      // visit.
      KnownFPClass KnownSrc;
      if (SimplifyDemandedFPClass(
              P, P->getOperandNumForIncomingValue(I), DemandedMask, KnownSrc,
              ContextSQ.getWithInstruction(CtxI), Depth + 1)) {
        // Fixup the other block references to the simplified value.
        P->setIncomingValueForBlock(PredBB, P->getIncomingValue(I));
        Changed = true;
      }

      if (First) {
        Known = KnownSrc;
        First = false;
      } else {
        Known |= KnownSrc;
      }
    }

    if (Changed)
      return P;

    Known.knownNot(~DemandedMask);
    break;
  }
  default:
    Known = computeKnownFPClass(I, DemandedMask, SQ, Depth + 1);
    Known.knownNot(~DemandedMask);
    break;
  }

  return getFPClassConstant(VTy, Known.getKnownFPClasses());
}

/// 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,
    const SimplifyQuery &SQ, unsigned Depth) {
  FastMathFlags FMF;
  if (auto *FPOp = dyn_cast<FPMathOperator>(I)) {
    FMF = FPOp->getFastMathFlags();
    DemandedMask = adjustDemandedMaskFromFlags(DemandedMask, FMF);
  }

  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, SQ, Depth + 1);
    if (KnownRHS.isKnownNever(DemandedMask))
      return I->getOperand(1);

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

    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);
    Known.knownNot(~DemandedMask);
    break;
  }
  case Instruction::FNeg: {
    // Special case fneg(fabs(x))
    Value *Src;

    Value *FNegSrc = I->getOperand(0);
    if (!match(FNegSrc, m_FAbs(m_Value(Src)))) {
      Known = computeKnownFPClass(I, DemandedMask, SQ, Depth + 1);
      break;
    }

    KnownFPClass KnownSrc = computeKnownFPClass(Src, fcAllFlags, SQ, Depth + 1);

    FastMathFlags FabsFMF = cast<FPMathOperator>(FNegSrc)->getFastMathFlags();
    FPClassTest ThisDemandedMask =
        adjustDemandedMaskFromFlags(DemandedMask, FabsFMF);

    // We cannot apply the NSZ logic with multiple uses. We can apply it if the
    // inner fabs has it and this is the only use.
    if (Value *Simplified = simplifyDemandedFPClassFnegFabs(
            Known, Src, ThisDemandedMask, KnownSrc, /*NSZ=*/false))
      return Simplified;
    break;
  }
  case Instruction::Call: {
    const CallInst *CI = cast<CallInst>(I);
    const Intrinsic::ID IID = CI->getIntrinsicID();
    switch (IID) {
    case Intrinsic::fabs: {
      Value *Src = CI->getArgOperand(0);
      KnownFPClass KnownSrc =
          computeKnownFPClass(Src, fcAllFlags, SQ, Depth + 1);

      // NSZ cannot be applied in multiple use case (maybe it could if all uses
      // were known nsz)
      if (Value *Simplified = simplifyDemandedFPClassFabs(
              Known, CI->getArgOperand(0), DemandedMask, KnownSrc,
              /*NSZ=*/false))
        return Simplified;
      break;
    }
    case Intrinsic::copysign: {
      Value *Mag = CI->getArgOperand(0);
      Value *Sign = CI->getArgOperand(1);
      KnownFPClass KnownMag =
          computeKnownFPClass(Mag, fcAllFlags, SQ, Depth + 1);

      // Rule out some cases by magnitude, which may help prove the sign bit is
      // one direction or the other.
      KnownMag.knownNot(~llvm::unknown_sign(DemandedMask));

      // Cannot use nsz in the multiple use case.
      if (Value *Simplified = simplifyDemandedFPClassCopysignMag(
              Mag, DemandedMask, KnownMag, /*NSZ=*/false))
        return Simplified;

      KnownFPClass KnownSign =
          computeKnownFPClass(Sign, fcAllFlags, SQ, Depth + 1);

      if (FMF.noInfs())
        KnownSign.knownNot(fcInf);
      if (FMF.noNaNs())
        KnownSign.knownNot(fcNan);

      if (KnownSign.getSignBit() && KnownMag.getSignBit() &&
          *KnownSign.getSignBit() == *KnownMag.getSignBit())
        return Mag;

      Known = KnownFPClass::copysign(KnownMag, KnownSign);
      break;
    }
    case Intrinsic::maxnum:
    case Intrinsic::minnum:
    case Intrinsic::maximum:
    case Intrinsic::minimum:
    case Intrinsic::maximumnum:
    case Intrinsic::minimumnum: {
      KnownFPClass KnownRHS = computeKnownFPClass(CI->getArgOperand(1),
                                                  DemandedMask, SQ, Depth + 1);
      if (KnownRHS.isUnknown())
        return nullptr;

      KnownFPClass KnownLHS = computeKnownFPClass(CI->getArgOperand(0),
                                                  DemandedMask, SQ, Depth + 1);

      // Cannot use NSZ in the multiple use case.
      return simplifyDemandedFPClassMinMax(Known, IID, CI, DemandedMask,
                                           KnownLHS, KnownRHS, F,
                                           /*NSZ=*/false);
    }
    default:
      break;
    }

    [[fallthrough]];
  }
  default:
    Known = computeKnownFPClass(I, DemandedMask, SQ, Depth + 1);
    Known.knownNot(~DemandedMask);
    break;
  }

  return getFPClassConstant(I->getType(), Known.getKnownFPClasses());
}

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

  if (DemandedMask == fcNone) {
    if (isa<PoisonValue>(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, SQ, Depth);
    Known.knownNot(~DemandedMask);

    if (Known.getKnownFPClasses() == fcNone) {
      if (isa<PoisonValue>(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, Known.getKnownFPClasses());
    if (!FoldedToConst || FoldedToConst == V)
      return false;

    replaceUse(U, FoldedToConst);
    return true;
  }

  if (Depth == MaxAnalysisRecursionDepth) {
    Known.knownNot(~DemandedMask);
    return false;
  }

  Value *NewVal;

  if (VInst->hasOneUse()) {
    // If the instruction has one use, we can directly simplify it.
    NewVal = SimplifyDemandedUseFPClass(VInst, DemandedMask, Known, SQ, 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, SQ,
                                                Depth);
  }

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

  replaceUse(U, NewVal);
  return true;
}
