llvm/llvm/lib/Analysis/InstructionSimplify.cpp

//===- InstructionSimplify.cpp - Fold instruction operands ----------------===//
//
// 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 implements routines for folding instructions into simpler forms
// that do not require creating new instructions.  This does constant folding
// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either
// returning a constant ("and i32 %x, 0" -> "0") or an already existing value
// ("and i32 %x, %x" -> "%x").  All operands are assumed to have already been
// simplified: This is usually true and assuming it simplifies the logic (if
// they have not been simplified then results are correct but maybe suboptimal).
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/InstructionSimplify.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/CmpInstAnalysis.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstSimplifyFolder.h"
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/OverflowInstAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/Support/KnownBits.h"
#include <algorithm>
#include <optional>
usingnamespacellvm;
usingnamespacellvm::PatternMatch;

#define DEBUG_TYPE

enum {};

STATISTIC(NumExpand, "Number of expansions");
STATISTIC(NumReassoc, "Number of reassociations");

static Value *simplifyAndInst(Value *, Value *, const SimplifyQuery &,
                              unsigned);
static Value *simplifyUnOp(unsigned, Value *, const SimplifyQuery &, unsigned);
static Value *simplifyFPUnOp(unsigned, Value *, const FastMathFlags &,
                             const SimplifyQuery &, unsigned);
static Value *simplifyBinOp(unsigned, Value *, Value *, const SimplifyQuery &,
                            unsigned);
static Value *simplifyBinOp(unsigned, Value *, Value *, const FastMathFlags &,
                            const SimplifyQuery &, unsigned);
static Value *simplifyCmpInst(unsigned, Value *, Value *, const SimplifyQuery &,
                              unsigned);
static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                               const SimplifyQuery &Q, unsigned MaxRecurse);
static Value *simplifyOrInst(Value *, Value *, const SimplifyQuery &, unsigned);
static Value *simplifyXorInst(Value *, Value *, const SimplifyQuery &,
                              unsigned);
static Value *simplifyCastInst(unsigned, Value *, Type *, const SimplifyQuery &,
                               unsigned);
static Value *simplifyGEPInst(Type *, Value *, ArrayRef<Value *>,
                              GEPNoWrapFlags, const SimplifyQuery &, unsigned);
static Value *simplifySelectInst(Value *, Value *, Value *,
                                 const SimplifyQuery &, unsigned);
static Value *simplifyInstructionWithOperands(Instruction *I,
                                              ArrayRef<Value *> NewOps,
                                              const SimplifyQuery &SQ,
                                              unsigned MaxRecurse);

static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal,
                                     Value *FalseVal) {}

/// For a boolean type or a vector of boolean type, return false or a vector
/// with every element false.
static Constant *getFalse(Type *Ty) {}

/// For a boolean type or a vector of boolean type, return true or a vector
/// with every element true.
static Constant *getTrue(Type *Ty) {}

/// isSameCompare - Is V equivalent to the comparison "LHS Pred RHS"?
static bool isSameCompare(Value *V, CmpInst::Predicate Pred, Value *LHS,
                          Value *RHS) {}

/// Simplify comparison with true or false branch of select:
///  %sel = select i1 %cond, i32 %tv, i32 %fv
///  %cmp = icmp sle i32 %sel, %rhs
/// Compose new comparison by substituting %sel with either %tv or %fv
/// and see if it simplifies.
static Value *simplifyCmpSelCase(CmpInst::Predicate Pred, Value *LHS,
                                 Value *RHS, Value *Cond,
                                 const SimplifyQuery &Q, unsigned MaxRecurse,
                                 Constant *TrueOrFalse) {}

/// Simplify comparison with true branch of select
static Value *simplifyCmpSelTrueCase(CmpInst::Predicate Pred, Value *LHS,
                                     Value *RHS, Value *Cond,
                                     const SimplifyQuery &Q,
                                     unsigned MaxRecurse) {}

/// Simplify comparison with false branch of select
static Value *simplifyCmpSelFalseCase(CmpInst::Predicate Pred, Value *LHS,
                                      Value *RHS, Value *Cond,
                                      const SimplifyQuery &Q,
                                      unsigned MaxRecurse) {}

/// We know comparison with both branches of select can be simplified, but they
/// are not equal. This routine handles some logical simplifications.
static Value *handleOtherCmpSelSimplifications(Value *TCmp, Value *FCmp,
                                               Value *Cond,
                                               const SimplifyQuery &Q,
                                               unsigned MaxRecurse) {}

/// Does the given value dominate the specified phi node?
static bool valueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {}

/// Try to simplify a binary operator of form "V op OtherOp" where V is
/// "(B0 opex B1)" by distributing 'op' across 'opex' as
/// "(B0 op OtherOp) opex (B1 op OtherOp)".
static Value *expandBinOp(Instruction::BinaryOps Opcode, Value *V,
                          Value *OtherOp, Instruction::BinaryOps OpcodeToExpand,
                          const SimplifyQuery &Q, unsigned MaxRecurse) {}

/// Try to simplify binops of form "A op (B op' C)" or the commuted variant by
/// distributing op over op'.
static Value *expandCommutativeBinOp(Instruction::BinaryOps Opcode, Value *L,
                                     Value *R,
                                     Instruction::BinaryOps OpcodeToExpand,
                                     const SimplifyQuery &Q,
                                     unsigned MaxRecurse) {}

/// Generic simplifications for associative binary operations.
/// Returns the simpler value, or null if none was found.
static Value *simplifyAssociativeBinOp(Instruction::BinaryOps Opcode,
                                       Value *LHS, Value *RHS,
                                       const SimplifyQuery &Q,
                                       unsigned MaxRecurse) {}

/// In the case of a binary operation with a select instruction as an operand,
/// try to simplify the binop by seeing whether evaluating it on both branches
/// of the select results in the same value. Returns the common value if so,
/// otherwise returns null.
static Value *threadBinOpOverSelect(Instruction::BinaryOps Opcode, Value *LHS,
                                    Value *RHS, const SimplifyQuery &Q,
                                    unsigned MaxRecurse) {}

/// In the case of a comparison with a select instruction, try to simplify the
/// comparison by seeing whether both branches of the select result in the same
/// value. Returns the common value if so, otherwise returns null.
/// For example, if we have:
///  %tmp = select i1 %cmp, i32 1, i32 2
///  %cmp1 = icmp sle i32 %tmp, 3
/// We can simplify %cmp1 to true, because both branches of select are
/// less than 3. We compose new comparison by substituting %tmp with both
/// branches of select and see if it can be simplified.
static Value *threadCmpOverSelect(CmpInst::Predicate Pred, Value *LHS,
                                  Value *RHS, const SimplifyQuery &Q,
                                  unsigned MaxRecurse) {}

/// In the case of a binary operation with an operand that is a PHI instruction,
/// try to simplify the binop by seeing whether evaluating it on the incoming
/// phi values yields the same result for every value. If so returns the common
/// value, otherwise returns null.
static Value *threadBinOpOverPHI(Instruction::BinaryOps Opcode, Value *LHS,
                                 Value *RHS, const SimplifyQuery &Q,
                                 unsigned MaxRecurse) {}

/// In the case of a comparison with a PHI instruction, try to simplify the
/// comparison by seeing whether comparing with all of the incoming phi values
/// yields the same result every time. If so returns the common result,
/// otherwise returns null.
static Value *threadCmpOverPHI(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

static Constant *foldOrCommuteConstant(Instruction::BinaryOps Opcode,
                                       Value *&Op0, Value *&Op1,
                                       const SimplifyQuery &Q) {}

/// Given operands for an Add, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyAddInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                              const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyAddInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                             const SimplifyQuery &Query) {}

/// Compute the base pointer and cumulative constant offsets for V.
///
/// This strips all constant offsets off of V, leaving it the base pointer, and
/// accumulates the total constant offset applied in the returned constant.
/// It returns zero if there are no constant offsets applied.
///
/// This is very similar to stripAndAccumulateConstantOffsets(), except it
/// normalizes the offset bitwidth to the stripped pointer type, not the
/// original pointer type.
static APInt stripAndComputeConstantOffsets(const DataLayout &DL, Value *&V,
                                            bool AllowNonInbounds = false) {}

/// Compute the constant difference between two pointer values.
/// If the difference is not a constant, returns zero.
static Constant *computePointerDifference(const DataLayout &DL, Value *LHS,
                                          Value *RHS) {}

/// Test if there is a dominating equivalence condition for the
/// two operands. If there is, try to reduce the binary operation
/// between the two operands.
/// Example: Op0 - Op1 --> 0 when Op0 == Op1
static Value *simplifyByDomEq(unsigned Opcode, Value *Op0, Value *Op1,
                              const SimplifyQuery &Q, unsigned MaxRecurse) {}

/// Given operands for a Sub, see if we can fold the result.
/// If not, this returns null.
static Value *simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                              const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                             const SimplifyQuery &Q) {}

/// Given operands for a Mul, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyMulInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                              const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyMulInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                             const SimplifyQuery &Q) {}

/// Given a predicate and two operands, return true if the comparison is true.
/// This is a helper for div/rem simplification where we return some other value
/// when we can prove a relationship between the operands.
static bool isICmpTrue(ICmpInst::Predicate Pred, Value *LHS, Value *RHS,
                       const SimplifyQuery &Q, unsigned MaxRecurse) {}

/// Return true if we can simplify X / Y to 0. Remainder can adapt that answer
/// to simplify X % Y to X.
static bool isDivZero(Value *X, Value *Y, const SimplifyQuery &Q,
                      unsigned MaxRecurse, bool IsSigned) {}

/// Check for common or similar folds of integer division or integer remainder.
/// This applies to all 4 opcodes (sdiv/udiv/srem/urem).
static Value *simplifyDivRem(Instruction::BinaryOps Opcode, Value *Op0,
                             Value *Op1, const SimplifyQuery &Q,
                             unsigned MaxRecurse) {}

/// These are simplifications common to SDiv and UDiv.
static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
                          bool IsExact, const SimplifyQuery &Q,
                          unsigned MaxRecurse) {}

/// These are simplifications common to SRem and URem.
static Value *simplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
                          const SimplifyQuery &Q, unsigned MaxRecurse) {}

/// Given operands for an SDiv, see if we can fold the result.
/// If not, this returns null.
static Value *simplifySDivInst(Value *Op0, Value *Op1, bool IsExact,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifySDivInst(Value *Op0, Value *Op1, bool IsExact,
                              const SimplifyQuery &Q) {}

/// Given operands for a UDiv, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyUDivInst(Value *Op0, Value *Op1, bool IsExact,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyUDivInst(Value *Op0, Value *Op1, bool IsExact,
                              const SimplifyQuery &Q) {}

/// Given operands for an SRem, see if we can fold the result.
/// If not, this returns null.
static Value *simplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
                               unsigned MaxRecurse) {}

Value *llvm::simplifySRemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {}

/// Given operands for a URem, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
                               unsigned MaxRecurse) {}

Value *llvm::simplifyURemInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {}

/// Returns true if a shift by \c Amount always yields poison.
static bool isPoisonShift(Value *Amount, const SimplifyQuery &Q) {}

/// Given operands for an Shl, LShr or AShr, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyShift(Instruction::BinaryOps Opcode, Value *Op0,
                            Value *Op1, bool IsNSW, const SimplifyQuery &Q,
                            unsigned MaxRecurse) {}

/// Given operands for an LShr or AShr, see if we can fold the result.  If not,
/// this returns null.
static Value *simplifyRightShift(Instruction::BinaryOps Opcode, Value *Op0,
                                 Value *Op1, bool IsExact,
                                 const SimplifyQuery &Q, unsigned MaxRecurse) {}

/// Given operands for an Shl, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyShlInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                              const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyShlInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
                             const SimplifyQuery &Q) {}

/// Given operands for an LShr, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyLShrInst(Value *Op0, Value *Op1, bool IsExact,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyLShrInst(Value *Op0, Value *Op1, bool IsExact,
                              const SimplifyQuery &Q) {}

/// Given operands for an AShr, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyAShrInst(Value *Op0, Value *Op1, bool IsExact,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyAShrInst(Value *Op0, Value *Op1, bool IsExact,
                              const SimplifyQuery &Q) {}

/// Commuted variants are assumed to be handled by calling this function again
/// with the parameters swapped.
static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
                                         ICmpInst *UnsignedICmp, bool IsAnd,
                                         const SimplifyQuery &Q) {}

/// Test if a pair of compares with a shared operand and 2 constants has an
/// empty set intersection, full set union, or if one compare is a superset of
/// the other.
static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
                                                bool IsAnd) {}

static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
                                        const InstrInfoQuery &IIQ) {}

/// Try to simplify and/or of icmp with ctpop intrinsic.
static Value *simplifyAndOrOfICmpsWithCtpop(ICmpInst *Cmp0, ICmpInst *Cmp1,
                                            bool IsAnd) {}

static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
                                 const SimplifyQuery &Q) {}

static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
                                       const InstrInfoQuery &IIQ) {}

static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1,
                                const SimplifyQuery &Q) {}

static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
                                   FCmpInst *RHS, bool IsAnd) {}

static Value *simplifyAndOrOfCmps(const SimplifyQuery &Q, Value *Op0,
                                  Value *Op1, bool IsAnd) {}

static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                     const SimplifyQuery &Q,
                                     bool AllowRefinement,
                                     SmallVectorImpl<Instruction *> *DropFlags,
                                     unsigned MaxRecurse);

static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
                                      const SimplifyQuery &Q,
                                      unsigned MaxRecurse) {}

/// Given a bitwise logic op, check if the operands are add/sub with a common
/// source value and inverted constant (identity: C - X -> ~(X + ~C)).
static Value *simplifyLogicOfAddSub(Value *Op0, Value *Op1,
                                    Instruction::BinaryOps Opcode) {}

// Commutative patterns for and that will be tried with both operand orders.
static Value *simplifyAndCommutative(Value *Op0, Value *Op1,
                                     const SimplifyQuery &Q,
                                     unsigned MaxRecurse) {}

/// Given operands for an And, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
                              unsigned MaxRecurse) {}

Value *llvm::simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {}

// TODO: Many of these folds could use LogicalAnd/LogicalOr.
static Value *simplifyOrLogic(Value *X, Value *Y) {}

/// Given operands for an Or, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
                             unsigned MaxRecurse) {}

Value *llvm::simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {}

/// Given operands for a Xor, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
                              unsigned MaxRecurse) {}

Value *llvm::simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {}

static Type *getCompareTy(Value *Op) {}

/// Rummage around inside V looking for something equivalent to the comparison
/// "LHS Pred RHS". Return such a value if found, otherwise return null.
/// Helper function for analyzing max/min idioms.
static Value *extractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
                                         Value *LHS, Value *RHS) {}

/// Return true if the underlying object (storage) must be disjoint from
/// storage returned by any noalias return call.
static bool isAllocDisjoint(const Value *V) {}

/// Return true if V1 and V2 are each the base of some distict storage region
/// [V, object_size(V)] which do not overlap.  Note that zero sized regions
/// *are* possible, and that zero sized regions do not overlap with any other.
static bool haveNonOverlappingStorage(const Value *V1, const Value *V2) {}

// A significant optimization not implemented here is assuming that alloca
// addresses are not equal to incoming argument values. They don't *alias*,
// as we say, but that doesn't mean they aren't equal, so we take a
// conservative approach.
//
// This is inspired in part by C++11 5.10p1:
//   "Two pointers of the same type compare equal if and only if they are both
//    null, both point to the same function, or both represent the same
//    address."
//
// This is pretty permissive.
//
// It's also partly due to C11 6.5.9p6:
//   "Two pointers compare equal if and only if both are null pointers, both are
//    pointers to the same object (including a pointer to an object and a
//    subobject at its beginning) or function, both are pointers to one past the
//    last element of the same array object, or one is a pointer to one past the
//    end of one array object and the other is a pointer to the start of a
//    different array object that happens to immediately follow the first array
//    object in the address space.)
//
// C11's version is more restrictive, however there's no reason why an argument
// couldn't be a one-past-the-end value for a stack object in the caller and be
// equal to the beginning of a stack object in the callee.
//
// If the C and C++ standards are ever made sufficiently restrictive in this
// area, it may be possible to update LLVM's semantics accordingly and reinstate
// this optimization.
static Constant *computePointerICmp(CmpInst::Predicate Pred, Value *LHS,
                                    Value *RHS, const SimplifyQuery &Q) {}

/// Fold an icmp when its operands have i1 scalar type.
static Value *simplifyICmpOfBools(CmpInst::Predicate Pred, Value *LHS,
                                  Value *RHS, const SimplifyQuery &Q) {}

/// Try hard to fold icmp with zero RHS because this is a common case.
static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS,
                                   Value *RHS, const SimplifyQuery &Q) {}

static Value *simplifyICmpWithConstant(CmpInst::Predicate Pred, Value *LHS,
                                       Value *RHS, const InstrInfoQuery &IIQ) {}

static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
                                         BinaryOperator *LBO, Value *RHS,
                                         const SimplifyQuery &Q,
                                         unsigned MaxRecurse) {}

// If only one of the icmp's operands has NSW flags, try to prove that:
//
//   icmp slt (x + C1), (x +nsw C2)
//
// is equivalent to:
//
//   icmp slt C1, C2
//
// which is true if x + C2 has the NSW flags set and:
// *) C1 < C2 && C1 >= 0, or
// *) C2 < C1 && C1 <= 0.
//
static bool trySimplifyICmpWithAdds(CmpInst::Predicate Pred, Value *LHS,
                                    Value *RHS, const InstrInfoQuery &IIQ) {}

/// TODO: A large part of this logic is duplicated in InstCombine's
/// foldICmpBinOp(). We should be able to share that and avoid the code
/// duplication.
static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS,
                                    Value *RHS, const SimplifyQuery &Q,
                                    unsigned MaxRecurse) {}

/// simplify integer comparisons where at least one operand of the compare
/// matches an integer min/max idiom.
static Value *simplifyICmpWithMinMax(CmpInst::Predicate Pred, Value *LHS,
                                     Value *RHS, const SimplifyQuery &Q,
                                     unsigned MaxRecurse) {}

static Value *simplifyICmpWithDominatingAssume(CmpInst::Predicate Predicate,
                                               Value *LHS, Value *RHS,
                                               const SimplifyQuery &Q) {}

static Value *simplifyICmpWithIntrinsicOnLHS(CmpInst::Predicate Pred,
                                             Value *LHS, Value *RHS) {}

/// Helper method to get range from metadata or attribute.
static std::optional<ConstantRange> getRange(Value *V,
                                             const InstrInfoQuery &IIQ) {}

/// Given operands for an ICmpInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              const SimplifyQuery &Q) {}

/// Given operands for an FCmpInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                               FastMathFlags FMF, const SimplifyQuery &Q,
                               unsigned MaxRecurse) {}

Value *llvm::simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              FastMathFlags FMF, const SimplifyQuery &Q) {}

static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                     const SimplifyQuery &Q,
                                     bool AllowRefinement,
                                     SmallVectorImpl<Instruction *> *DropFlags,
                                     unsigned MaxRecurse) {}

Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                    const SimplifyQuery &Q,
                                    bool AllowRefinement,
                                    SmallVectorImpl<Instruction *> *DropFlags) {}

/// Try to simplify a select instruction when its condition operand is an
/// integer comparison where one operand of the compare is a constant.
static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X,
                                    const APInt *Y, bool TrueWhenUnset) {}

static Value *simplifyCmpSelOfMaxMin(Value *CmpLHS, Value *CmpRHS,
                                     ICmpInst::Predicate Pred, Value *TVal,
                                     Value *FVal) {}

/// An alternative way to test if a bit is set or not uses sgt/slt instead of
/// eq/ne.
static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
                                           ICmpInst::Predicate Pred,
                                           Value *TrueVal, Value *FalseVal) {}

/// Try to simplify a select instruction when its condition operand is an
/// integer equality comparison.
static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
                                       Value *TrueVal, Value *FalseVal,
                                       const SimplifyQuery &Q,
                                       unsigned MaxRecurse) {}

/// Try to simplify a select instruction when its condition operand is an
/// integer comparison.
static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
                                         Value *FalseVal,
                                         const SimplifyQuery &Q,
                                         unsigned MaxRecurse) {}

/// Try to simplify a select instruction when its condition operand is a
/// floating-point comparison.
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
                                     const SimplifyQuery &Q) {}

/// Given operands for a SelectInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
                                 const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
                                const SimplifyQuery &Q) {}

/// Given operands for an GetElementPtrInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyGEPInst(Type *SrcTy, Value *Ptr,
                              ArrayRef<Value *> Indices, GEPNoWrapFlags NW,
                              const SimplifyQuery &Q, unsigned) {}

Value *llvm::simplifyGEPInst(Type *SrcTy, Value *Ptr, ArrayRef<Value *> Indices,
                             GEPNoWrapFlags NW, const SimplifyQuery &Q) {}

/// Given operands for an InsertValueInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyInsertValueInst(Value *Agg, Value *Val,
                                      ArrayRef<unsigned> Idxs,
                                      const SimplifyQuery &Q, unsigned) {}

Value *llvm::simplifyInsertValueInst(Value *Agg, Value *Val,
                                     ArrayRef<unsigned> Idxs,
                                     const SimplifyQuery &Q) {}

Value *llvm::simplifyInsertElementInst(Value *Vec, Value *Val, Value *Idx,
                                       const SimplifyQuery &Q) {}

/// Given operands for an ExtractValueInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
                                       const SimplifyQuery &, unsigned) {}

Value *llvm::simplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
                                      const SimplifyQuery &Q) {}

/// Given operands for an ExtractElementInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyExtractElementInst(Value *Vec, Value *Idx,
                                         const SimplifyQuery &Q, unsigned) {}

Value *llvm::simplifyExtractElementInst(Value *Vec, Value *Idx,
                                        const SimplifyQuery &Q) {}

/// See if we can fold the given phi. If not, returns null.
static Value *simplifyPHINode(PHINode *PN, ArrayRef<Value *> IncomingValues,
                              const SimplifyQuery &Q) {}

static Value *simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
                              const SimplifyQuery &Q) {}

/// For the given destination element of a shuffle, peek through shuffles to
/// match a root vector source operand that contains that element in the same
/// vector lane (ie, the same mask index), so we can eliminate the shuffle(s).
static Value *foldIdentityShuffles(int DestElt, Value *Op0, Value *Op1,
                                   int MaskVal, Value *RootVec,
                                   unsigned MaxRecurse) {}

static Value *simplifyShuffleVectorInst(Value *Op0, Value *Op1,
                                        ArrayRef<int> Mask, Type *RetTy,
                                        const SimplifyQuery &Q,
                                        unsigned MaxRecurse) {}

/// Given operands for a ShuffleVectorInst, fold the result or return null.
Value *llvm::simplifyShuffleVectorInst(Value *Op0, Value *Op1,
                                       ArrayRef<int> Mask, Type *RetTy,
                                       const SimplifyQuery &Q) {}

static Constant *foldConstant(Instruction::UnaryOps Opcode, Value *&Op,
                              const SimplifyQuery &Q) {}

/// Given the operand for an FNeg, see if we can fold the result.  If not, this
/// returns null.
static Value *simplifyFNegInst(Value *Op, FastMathFlags FMF,
                               const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyFNegInst(Value *Op, FastMathFlags FMF,
                              const SimplifyQuery &Q) {}

/// Try to propagate existing NaN values when possible. If not, replace the
/// constant or elements in the constant with a canonical NaN.
static Constant *propagateNaN(Constant *In) {}

/// Perform folds that are common to any floating-point operation. This implies
/// transforms based on poison/undef/NaN because the operation itself makes no
/// difference to the result.
static Constant *simplifyFPOp(ArrayRef<Value *> Ops, FastMathFlags FMF,
                              const SimplifyQuery &Q,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

/// Given operands for an FAdd, see if we can fold the result.  If not, this
/// returns null.
static Value *
simplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                 const SimplifyQuery &Q, unsigned MaxRecurse,
                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {}

/// Given operands for an FSub, see if we can fold the result.  If not, this
/// returns null.
static Value *
simplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                 const SimplifyQuery &Q, unsigned MaxRecurse,
                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {}

static Value *simplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
                              const SimplifyQuery &Q, unsigned MaxRecurse,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

/// Given the operands for an FMul, see if we can fold the result
static Value *
simplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                 const SimplifyQuery &Q, unsigned MaxRecurse,
                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {}

Value *llvm::simplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                              const SimplifyQuery &Q,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

Value *llvm::simplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                              const SimplifyQuery &Q,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

Value *llvm::simplifyFMulInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                              const SimplifyQuery &Q,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

Value *llvm::simplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
                             const SimplifyQuery &Q,
                             fp::ExceptionBehavior ExBehavior,
                             RoundingMode Rounding) {}

static Value *
simplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                 const SimplifyQuery &Q, unsigned,
                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {}

Value *llvm::simplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                              const SimplifyQuery &Q,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

static Value *
simplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                 const SimplifyQuery &Q, unsigned,
                 fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
                 RoundingMode Rounding = RoundingMode::NearestTiesToEven) {}

Value *llvm::simplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
                              const SimplifyQuery &Q,
                              fp::ExceptionBehavior ExBehavior,
                              RoundingMode Rounding) {}

//=== Helper functions for higher up the class hierarchy.

/// Given the operand for a UnaryOperator, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q,
                           unsigned MaxRecurse) {}

/// Given the operand for a UnaryOperator, see if we can fold the result.
/// If not, this returns null.
/// Try to use FastMathFlags when folding the result.
static Value *simplifyFPUnOp(unsigned Opcode, Value *Op,
                             const FastMathFlags &FMF, const SimplifyQuery &Q,
                             unsigned MaxRecurse) {}

Value *llvm::simplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q) {}

Value *llvm::simplifyUnOp(unsigned Opcode, Value *Op, FastMathFlags FMF,
                          const SimplifyQuery &Q) {}

/// Given operands for a BinaryOperator, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                            const SimplifyQuery &Q, unsigned MaxRecurse) {}

/// Given operands for a BinaryOperator, see if we can fold the result.
/// If not, this returns null.
/// Try to use FastMathFlags when folding the result.
static Value *simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                            const FastMathFlags &FMF, const SimplifyQuery &Q,
                            unsigned MaxRecurse) {}

Value *llvm::simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                           const SimplifyQuery &Q) {}

Value *llvm::simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
                           FastMathFlags FMF, const SimplifyQuery &Q) {}

/// Given operands for a CmpInst, see if we can fold the result.
static Value *simplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                              const SimplifyQuery &Q, unsigned MaxRecurse) {}

Value *llvm::simplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
                             const SimplifyQuery &Q) {}

static bool isIdempotent(Intrinsic::ID ID) {}

/// Return true if the intrinsic rounds a floating-point value to an integral
/// floating-point value (not an integer type).
static bool removesFPFraction(Intrinsic::ID ID) {}

static Value *simplifyRelativeLoad(Constant *Ptr, Constant *Offset,
                                   const DataLayout &DL) {}

// TODO: Need to pass in FastMathFlags
static Value *simplifyLdexp(Value *Op0, Value *Op1, const SimplifyQuery &Q,
                            bool IsStrict) {}

static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
                                     const SimplifyQuery &Q,
                                     const CallBase *Call) {}

/// Given a min/max intrinsic, see if it can be removed based on having an
/// operand that is another min/max intrinsic with shared operand(s). The caller
/// is expected to swap the operand arguments to handle commutation.
static Value *foldMinMaxSharedOp(Intrinsic::ID IID, Value *Op0, Value *Op1) {}

/// Given a min/max intrinsic, see if it can be removed based on having an
/// operand that is another min/max intrinsic with shared operand(s). The caller
/// is expected to swap the operand arguments to handle commutation.
static Value *foldMinimumMaximumSharedOp(Intrinsic::ID IID, Value *Op0,
                                         Value *Op1) {}

Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
                                     Value *Op0, Value *Op1,
                                     const SimplifyQuery &Q,
                                     const CallBase *Call) {}

static Value *simplifyIntrinsic(CallBase *Call, Value *Callee,
                                ArrayRef<Value *> Args,
                                const SimplifyQuery &Q) {}

static Value *tryConstantFoldCall(CallBase *Call, Value *Callee,
                                  ArrayRef<Value *> Args,
                                  const SimplifyQuery &Q) {}

Value *llvm::simplifyCall(CallBase *Call, Value *Callee, ArrayRef<Value *> Args,
                          const SimplifyQuery &Q) {}

Value *llvm::simplifyConstrainedFPCall(CallBase *Call, const SimplifyQuery &Q) {}

/// Given operands for a Freeze, see if we can fold the result.
static Value *simplifyFreezeInst(Value *Op0, const SimplifyQuery &Q) {}

Value *llvm::simplifyFreezeInst(Value *Op0, const SimplifyQuery &Q) {}

Value *llvm::simplifyLoadInst(LoadInst *LI, Value *PtrOp,
                              const SimplifyQuery &Q) {}

/// See if we can compute a simplified version of this instruction.
/// If not, this returns null.

static Value *simplifyInstructionWithOperands(Instruction *I,
                                              ArrayRef<Value *> NewOps,
                                              const SimplifyQuery &SQ,
                                              unsigned MaxRecurse) {}

Value *llvm::simplifyInstructionWithOperands(Instruction *I,
                                             ArrayRef<Value *> NewOps,
                                             const SimplifyQuery &SQ) {}

Value *llvm::simplifyInstruction(Instruction *I, const SimplifyQuery &SQ) {}

/// Implementation of recursive simplification through an instruction's
/// uses.
///
/// This is the common implementation of the recursive simplification routines.
/// If we have a pre-simplified value in 'SimpleV', that is forcibly used to
/// replace the instruction 'I'. Otherwise, we simply add 'I' to the list of
/// instructions to process and attempt to simplify it using
/// InstructionSimplify. Recursively visited users which could not be
/// simplified themselves are to the optional UnsimplifiedUsers set for
/// further processing by the caller.
///
/// This routine returns 'true' only when *it* simplifies something. The passed
/// in simplified value does not count toward this.
static bool replaceAndRecursivelySimplifyImpl(
    Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI,
    const DominatorTree *DT, AssumptionCache *AC,
    SmallSetVector<Instruction *, 8> *UnsimplifiedUsers = nullptr) {}

bool llvm::replaceAndRecursivelySimplify(
    Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI,
    const DominatorTree *DT, AssumptionCache *AC,
    SmallSetVector<Instruction *, 8> *UnsimplifiedUsers) {}

namespace llvm {
const SimplifyQuery getBestSimplifyQuery(Pass &P, Function &F) {}

const SimplifyQuery getBestSimplifyQuery(LoopStandardAnalysisResults &AR,
                                         const DataLayout &DL) {}

template <class T, class... TArgs>
const SimplifyQuery getBestSimplifyQuery(AnalysisManager<T, TArgs...> &AM,
                                         Function &F) {}
template const SimplifyQuery getBestSimplifyQuery(AnalysisManager<Function> &,
                                                  Function &);

bool SimplifyQuery::isUndefValue(Value *V) const {}

} // namespace llvm

void InstSimplifyFolder::anchor() {}