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

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

/// 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,
                                     0, SQ.getWithInstruction(&Inst));
  if (!V) return false;
  if (V == &Inst) return true;
  replaceInstUsesWith(Inst, V);
  return true;
}

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

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

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

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

    // 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, Depth + 1, Q) ||
        SimplifyDemandedBits(I, 0, DemandedMask & ~RHSKnown.One, LHSKnown,
                             Depth + 1, Q)) {
      // Disjoint flag may not longer hold.
      I->dropPoisonGeneratingFlags();
      return I;
    }

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

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

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

    // 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, Depth + 1, Q) ||
        SimplifyDemandedBits(I, 1, DemandedMask, LHSKnown, Depth + 1, Q))
      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, Depth, Q);
    adjustKnownBitsForSelectArm(RHSKnown, I->getOperand(0), I->getOperand(2),
                                /*Invert=*/true, Depth, Q);
    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, Depth + 1,
                             Q)) {
      // 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, Depth + 1, Q))
      return I;

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

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

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

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

    // Right fill the mask of bits for the operands to demand the most
    // significant bit and all those below it.
    unsigned NLZ = DemandedMask.countl_zero();
    APInt DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ);
    if (ShrinkDemandedConstant(I, 1, DemandedFromOps) ||
        SimplifyDemandedBits(I, 1, DemandedFromOps, RHSKnown, Depth + 1, Q))
      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, Depth + 1, Q))
      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, Depth + 1, Q))
      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, Depth + 1, Q))
      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, Depth, Q);
    break;
  }
  case Instruction::Shl: {
    const APInt *SA;
    if (match(I->getOperand(1), m_APInt(SA))) {
      const APInt *ShrAmt;
      if (match(I->getOperand(0), m_Shr(m_Value(), m_APInt(ShrAmt))))
        if (Instruction *Shr = dyn_cast<Instruction>(I->getOperand(0)))
          if (Value *R = simplifyShrShlDemandedBits(Shr, *ShrAmt, I, *SA,
                                                    DemandedMask, Known))
            return R;

      // Do not simplify if shl is part of funnel-shift pattern
      if (I->hasOneUse()) {
        auto *Inst = dyn_cast<Instruction>(I->user_back());
        if (Inst && Inst->getOpcode() == BinaryOperator::Or) {
          if (auto Opt = convertOrOfShiftsToFunnelShift(*Inst)) {
            auto [IID, FShiftArgs] = *Opt;
            if ((IID == Intrinsic::fshl || IID == Intrinsic::fshr) &&
                FShiftArgs[0] == FShiftArgs[1]) {
              llvm::computeKnownBits(I, Known, Depth, Q);
              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), Depth + 1, Q.CxtI);
          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, Depth + 1, Q))
        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, Depth + 1, Q)) {
          // We can't guarantee that nsw/nuw hold after simplifying the operand.
          I->dropPoisonGeneratingFlags();
          return I;
        }
      }
      llvm::computeKnownBits(I, Known, Depth, Q);
    }
    break;
  }
  case Instruction::LShr: {
    const APInt *SA;
    if (match(I->getOperand(1), m_APInt(SA))) {
      uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1);

      // Do not simplify if lshr is part of funnel-shift pattern
      if (I->hasOneUse()) {
        auto *Inst = dyn_cast<Instruction>(I->user_back());
        if (Inst && Inst->getOpcode() == BinaryOperator::Or) {
          if (auto Opt = convertOrOfShiftsToFunnelShift(*Inst)) {
            auto [IID, FShiftArgs] = *Opt;
            if ((IID == Intrinsic::fshl || IID == Intrinsic::fshr) &&
                FShiftArgs[0] == FShiftArgs[1]) {
              llvm::computeKnownBits(I, Known, Depth, Q);
              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), Depth + 1, Q.CxtI);
        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, Depth + 1, Q)) {
        // exact flag may not longer hold.
        I->dropPoisonGeneratingFlags();
        return I;
      }
      Known.Zero.lshrInPlace(ShiftAmt);
      Known.One.lshrInPlace(ShiftAmt);
      if (ShiftAmt)
        Known.Zero.setHighBits(ShiftAmt);  // high bits known zero.
    } else {
      llvm::computeKnownBits(I, Known, Depth, Q);
    }
    break;
  }
  case Instruction::AShr: {
    unsigned SignBits = ComputeNumSignBits(I->getOperand(0), Depth + 1, Q.CxtI);

    // 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, Depth + 1, Q)) {
        // 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, Depth, Q);
    }
    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, Depth + 1, Q)) {
        // 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, Depth, Q);
    }
    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, Depth + 1, Q))
        return I;
      Known = KnownBits::srem(LHSKnown, KnownBits::makeConstant(*Rem));
      break;
    }

    llvm::computeKnownBits(I, Known, Depth, Q);
    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, Depth + 1, Q) ||
            SimplifyDemandedBits(
                I, 1, (DemandedMask & ~LHSKnown.Zero).zextOrTrunc(MaskWidth),
                RHSKnown, Depth + 1, Q))
          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, Depth + 1, I);
          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,
                                   Depth + 1, Q) ||
              SimplifyDemandedBits(I, 1, DemandedMaskRHS, RHSKnown, Depth + 1,
                                   Q))
            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), Depth + 1, I);
          if (DemandedMaskLHS.isSubsetOf(LHSKnown.Zero | LHSKnown.One) &&
              !match(I->getOperand(0), m_SpecificInt(LHSKnown.One))) {
            replaceOperand(*I, 0, Constant::getIntegerValue(VTy, LHSKnown.One));
            return I;
          }

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

        Known.Zero = LHSKnown.Zero.shl(ShiftAmt) |
                     RHSKnown.Zero.lshr(BitWidth - ShiftAmt);
        Known.One = LHSKnown.One.shl(ShiftAmt) |
                    RHSKnown.One.lshr(BitWidth - ShiftAmt);
        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, Depth, Q);
    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, Depth, Q);
    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, unsigned Depth,
    const SimplifyQuery &Q) {
  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, Depth + 1, Q);
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1, Q);
    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Depth, Q);
    computeKnownBitsFromContext(I, Known, Depth, Q);

    // 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, Depth + 1, Q);
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1, Q);
    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Depth, Q);
    computeKnownBitsFromContext(I, Known, Depth, Q);

    // 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, Depth + 1, Q);
    llvm::computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1, Q);
    Known = analyzeKnownBitsFromAndXorOr(cast<Operator>(I), LHSKnown, RHSKnown,
                                         Depth, Q);
    computeKnownBitsFromContext(I, Known, Depth, Q);

    // 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, Depth + 1, Q);
    if (DemandedFromOps.isSubsetOf(RHSKnown.Zero))
      return I->getOperand(0);

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

    // 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, Depth, Q);

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

    break;
  }

  return nullptr;
}

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

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

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

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

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

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

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

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

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

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

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

  return nullptr;
}

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

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

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

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

  PoisonElts = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    simplifyAndSetOp(I, 0, PreInsertDemandedElts, PoisonElts);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    simplifyAndSetOp(I, 0, InputDemandedElts, PoisonElts2);

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

  case Instruction::Call: {
    IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
    if (!II) break;
    switch (II->getIntrinsicID()) {
    case Intrinsic::masked_gather: // fallthrough
    case Intrinsic::masked_load: {
      // Subtlety: If we load from a pointer, the pointer must be valid
      // regardless of whether the element is demanded.  Doing otherwise risks
      // segfaults which didn't exist in the original program.
      APInt DemandedPtrs(APInt::getAllOnes(VWidth)),
          DemandedPassThrough(DemandedElts);
      if (auto *CV = dyn_cast<ConstantVector>(II->getOperand(2)))
        for (unsigned i = 0; i < VWidth; i++) {
          Constant *CElt = CV->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, 3, 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)
        BinaryOperator::BinaryOps Opcode = BO->getOpcode();
        Value *ShufOp = MatchShufAsOp0 ? X : Y;
        Value *OtherOp = MatchShufAsOp0 ? Y : X;
        for (User *U : OtherOp->users()) {
          ArrayRef<int> Mask;
          auto Shuf = m_Shuffle(m_Specific(ShufOp), m_Value(), m_Mask(Mask));
          if (BO->isCommutative()
                  ? match(U, m_c_BinOp(Opcode, Shuf, m_Specific(OtherOp)))
                  : MatchShufAsOp0
                        ? match(U, m_BinOp(Opcode, Shuf, m_Specific(OtherOp)))
                        : match(U, m_BinOp(Opcode, m_Specific(OtherOp), Shuf)))
            if (match(Mask, m_ZeroMask()) && Mask[0] != PoisonMaskElem)
              if (DT.dominates(U, I))
                return U;
        }
        return nullptr;
      };

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

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

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

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

  return MadeChange ? I : nullptr;
}

/// For floating-point classes that resolve to a single bit pattern, return that
/// value.
static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
  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;

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

Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
    Value *V, const FPClassTest DemandedMask, KnownFPClass &Known,
    unsigned Depth, Instruction *CxtI) {
  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
  Type *VTy = V->getType();

  assert(Known == KnownFPClass() && "expected uninitialized state");

  if (DemandedMask == fcNone)
    return isa<UndefValue>(V) ? nullptr : PoisonValue::get(VTy);

  if (Depth == MaxAnalysisRecursionDepth)
    return nullptr;

  Instruction *I = dyn_cast<Instruction>(V);
  if (!I) {
    // Handle constants and arguments
    Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
    Value *FoldedToConst =
        getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses);
    return FoldedToConst == V ? nullptr : FoldedToConst;
  }

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

  // TODO: Should account for nofpclass/FastMathFlags on current instruction
  switch (I->getOpcode()) {
  case Instruction::FNeg: {
    if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
                                Depth + 1))
      return I;
    Known.fneg();
    break;
  }
  case Instruction::Call: {
    CallInst *CI = cast<CallInst>(I);
    switch (CI->getIntrinsicID()) {
    case Intrinsic::fabs:
      if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), Known,
                                  Depth + 1))
        return I;
      Known.fabs();
      break;
    case Intrinsic::arithmetic_fence:
      if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
        return I;
      break;
    case Intrinsic::copysign: {
      // Flip on more potentially demanded classes
      const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
      if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
        return I;

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

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

      KnownFPClass KnownSign =
          computeKnownFPClass(I->getOperand(1), fcAllFlags, CxtI, Depth + 1);
      Known.copysign(KnownSign);
      break;
    }
    default:
      Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);
      break;
    }

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

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

    // TODO: Recognize clamping patterns
    Known = KnownLHS | KnownRHS;
    break;
  }
  default:
    Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);
    break;
  }

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

bool InstCombinerImpl::SimplifyDemandedFPClass(Instruction *I, unsigned OpNo,
                                               FPClassTest DemandedMask,
                                               KnownFPClass &Known,
                                               unsigned Depth) {
  Use &U = I->getOperandUse(OpNo);
  Value *NewVal =
      SimplifyDemandedUseFPClass(U.get(), DemandedMask, Known, Depth, I);
  if (!NewVal)
    return false;
  if (Instruction *OpInst = dyn_cast<Instruction>(U))
    salvageDebugInfo(*OpInst);

  replaceUse(U, NewVal);
  return true;
}
