llvm/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

//===- InstCombineAndOrXor.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 implements the visitAnd, visitOr, and visitXor functions.
//
//===----------------------------------------------------------------------===//

#include "InstCombineInternal.h"
#include "llvm/Analysis/CmpInstAnalysis.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/InstCombine/InstCombiner.h"
#include "llvm/Transforms/Utils/Local.h"

usingnamespacellvm;
usingnamespacePatternMatch;

#define DEBUG_TYPE

/// This is the complement of getICmpCode, which turns an opcode and two
/// operands into either a constant true or false, or a brand new ICmp
/// instruction. The sign is passed in to determine which kind of predicate to
/// use in the new icmp instruction.
static Value *getNewICmpValue(unsigned Code, bool Sign, Value *LHS, Value *RHS,
                              InstCombiner::BuilderTy &Builder) {}

/// This is the complement of getFCmpCode, which turns an opcode and two
/// operands into either a FCmp instruction, or a true/false constant.
static Value *getFCmpValue(unsigned Code, Value *LHS, Value *RHS,
                           InstCombiner::BuilderTy &Builder) {}

/// Emit a computation of: (V >= Lo && V < Hi) if Inside is true, otherwise
/// (V < Lo || V >= Hi). This method expects that Lo < Hi. IsSigned indicates
/// whether to treat V, Lo, and Hi as signed or not.
Value *InstCombinerImpl::insertRangeTest(Value *V, const APInt &Lo,
                                         const APInt &Hi, bool isSigned,
                                         bool Inside) {}

/// Classify (icmp eq (A & B), C) and (icmp ne (A & B), C) as matching patterns
/// that can be simplified.
/// One of A and B is considered the mask. The other is the value. This is
/// described as the "AMask" or "BMask" part of the enum. If the enum contains
/// only "Mask", then both A and B can be considered masks. If A is the mask,
/// then it was proven that (A & C) == C. This is trivial if C == A or C == 0.
/// If both A and C are constants, this proof is also easy.
/// For the following explanations, we assume that A is the mask.
///
/// "AllOnes" declares that the comparison is true only if (A & B) == A or all
/// bits of A are set in B.
///   Example: (icmp eq (A & 3), 3) -> AMask_AllOnes
///
/// "AllZeros" declares that the comparison is true only if (A & B) == 0 or all
/// bits of A are cleared in B.
///   Example: (icmp eq (A & 3), 0) -> Mask_AllZeroes
///
/// "Mixed" declares that (A & B) == C and C might or might not contain any
/// number of one bits and zero bits.
///   Example: (icmp eq (A & 3), 1) -> AMask_Mixed
///
/// "Not" means that in above descriptions "==" should be replaced by "!=".
///   Example: (icmp ne (A & 3), 3) -> AMask_NotAllOnes
///
/// If the mask A contains a single bit, then the following is equivalent:
///    (icmp eq (A & B), A) equals (icmp ne (A & B), 0)
///    (icmp ne (A & B), A) equals (icmp eq (A & B), 0)
enum MaskedICmpType {};

/// Return the set of patterns (from MaskedICmpType) that (icmp SCC (A & B), C)
/// satisfies.
static unsigned getMaskedICmpType(Value *A, Value *B, Value *C,
                                  ICmpInst::Predicate Pred) {}

/// Convert an analysis of a masked ICmp into its equivalent if all boolean
/// operations had the opposite sense. Since each "NotXXX" flag (recording !=)
/// is adjacent to the corresponding normal flag (recording ==), this just
/// involves swapping those bits over.
static unsigned conjugateICmpMask(unsigned Mask) {}

// Adapts the external decomposeBitTestICmp for local use.
static bool decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred,
                                 Value *&X, Value *&Y, Value *&Z) {}

/// Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E).
/// Return the pattern classes (from MaskedICmpType) for the left hand side and
/// the right hand side as a pair.
/// LHS and RHS are the left hand side and the right hand side ICmps and PredL
/// and PredR are their predicates, respectively.
static std::optional<std::pair<unsigned, unsigned>> getMaskedTypeForICmpPair(
    Value *&A, Value *&B, Value *&C, Value *&D, Value *&E, ICmpInst *LHS,
    ICmpInst *RHS, ICmpInst::Predicate &PredL, ICmpInst::Predicate &PredR) {}

/// Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E) into a single
/// (icmp(A & X) ==/!= Y), where the left-hand side is of type Mask_NotAllZeros
/// and the right hand side is of type BMask_Mixed. For example,
/// (icmp (A & 12) != 0) & (icmp (A & 15) == 8) -> (icmp (A & 15) == 8).
/// Also used for logical and/or, must be poison safe.
static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
    ICmpInst *LHS, ICmpInst *RHS, bool IsAnd, Value *A, Value *B, Value *D,
    Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR,
    InstCombiner::BuilderTy &Builder) {}

/// Try to fold (icmp(A & B) ==/!= 0) &/| (icmp(A & D) ==/!= E) into a single
/// (icmp(A & X) ==/!= Y), where the left-hand side and the right hand side
/// aren't of the common mask pattern type.
/// Also used for logical and/or, must be poison safe.
static Value *foldLogOpOfMaskedICmpsAsymmetric(
    ICmpInst *LHS, ICmpInst *RHS, bool IsAnd, Value *A, Value *B, Value *C,
    Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR,
    unsigned LHSMask, unsigned RHSMask, InstCombiner::BuilderTy &Builder) {}

/// Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E)
/// into a single (icmp(A & X) ==/!= Y).
static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
                                     bool IsLogical,
                                     InstCombiner::BuilderTy &Builder) {}

/// Try to fold a signed range checked with lower bound 0 to an unsigned icmp.
/// Example: (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n
/// If \p Inverted is true then the check is for the inverted range, e.g.
/// (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
                                            bool Inverted) {}

// (or (icmp eq X, 0), (icmp eq X, Pow2OrZero))
//      -> (icmp eq (and X, Pow2OrZero), X)
// (and (icmp ne X, 0), (icmp ne X, Pow2OrZero))
//      -> (icmp ne (and X, Pow2OrZero), X)
static Value *
foldAndOrOfICmpsWithPow2AndWithZero(InstCombiner::BuilderTy &Builder,
                                    ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
                                    const SimplifyQuery &Q) {}

// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
Value *InstCombinerImpl::foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS,
                                                       ICmpInst *RHS,
                                                       Instruction *CxtI,
                                                       bool IsAnd,
                                                       bool IsLogical) {}

/// General pattern:
///   X & Y
///
/// Where Y is checking that all the high bits (covered by a mask 4294967168)
/// are uniform, i.e.  %arg & 4294967168  can be either  4294967168  or  0
/// Pattern can be one of:
///   %t = add        i32 %arg,    128
///   %r = icmp   ult i32 %t,      256
/// Or
///   %t0 = shl       i32 %arg,    24
///   %t1 = ashr      i32 %t0,     24
///   %r  = icmp  eq  i32 %t1,     %arg
/// Or
///   %t0 = trunc     i32 %arg  to i8
///   %t1 = sext      i8  %t0   to i32
///   %r  = icmp  eq  i32 %t1,     %arg
/// This pattern is a signed truncation check.
///
/// And X is checking that some bit in that same mask is zero.
/// I.e. can be one of:
///   %r = icmp sgt i32   %arg,    -1
/// Or
///   %t = and      i32   %arg,    2147483648
///   %r = icmp eq  i32   %t,      0
///
/// Since we are checking that all the bits in that mask are the same,
/// and a particular bit is zero, what we are really checking is that all the
/// masked bits are zero.
/// So this should be transformed to:
///   %r = icmp ult i32 %arg, 128
static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,
                                        Instruction &CxtI,
                                        InstCombiner::BuilderTy &Builder) {}

/// Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and
/// fold (icmp ne ctpop(X) 1) & (icmp ne X 0) into (icmp ugt ctpop(X) 1).
/// Also used for logical and/or, must be poison safe.
static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
                                   InstCombiner::BuilderTy &Builder) {}

/// Reduce a pair of compares that check if a value has exactly 1 bit set.
/// Also used for logical and/or, must be poison safe.
static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
                             InstCombiner::BuilderTy &Builder) {}

/// Try to fold (icmp(A & B) == 0) & (icmp(A & D) != E) into (icmp A u< D) iff
/// B is a contiguous set of ones starting from the most significant bit
/// (negative power of 2), D and E are equal, and D is a contiguous set of ones
/// starting at the most significant zero bit in B. Parameter B supports masking
/// using undef/poison in either scalar or vector values.
static Value *foldNegativePower2AndShiftedMask(
    Value *A, Value *B, Value *D, Value *E, ICmpInst::Predicate PredL,
    ICmpInst::Predicate PredR, InstCombiner::BuilderTy &Builder) {}

/// Try to fold ((icmp X u< P) & (icmp(X & M) != M)) or ((icmp X s> -1) &
/// (icmp(X & M) != M)) into (icmp X u< M). Where P is a power of 2, M < P, and
/// M is a contiguous shifted mask starting at the right most significant zero
/// bit in P. SGT is supported as when P is the largest representable power of
/// 2, an earlier optimization converts the expression into (icmp X s> -1).
/// Parameter P supports masking using undef/poison in either scalar or vector
/// values.
static Value *foldPowerOf2AndShiftedMask(ICmpInst *Cmp0, ICmpInst *Cmp1,
                                         bool JoinedByAnd,
                                         InstCombiner::BuilderTy &Builder) {}

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

struct IntPart {};

/// Match an extraction of bits from an integer.
static std::optional<IntPart> matchIntPart(Value *V) {}

/// Materialize an extraction of bits from an integer in IR.
static Value *extractIntPart(const IntPart &P, IRBuilderBase &Builder) {}

/// (icmp eq X0, Y0) & (icmp eq X1, Y1) -> icmp eq X01, Y01
/// (icmp ne X0, Y0) | (icmp ne X1, Y1) -> icmp ne X01, Y01
/// where X0, X1 and Y0, Y1 are adjacent parts extracted from an integer.
Value *InstCombinerImpl::foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1,
                                       bool IsAnd) {}

/// Reduce logic-of-compares with equality to a constant by substituting a
/// common operand with the constant. Callers are expected to call this with
/// Cmp0/Cmp1 switched to handle logic op commutativity.
static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
                                          bool IsAnd, bool IsLogical,
                                          InstCombiner::BuilderTy &Builder,
                                          const SimplifyQuery &Q) {}

/// Fold (icmp Pred1 V1, C1) & (icmp Pred2 V2, C2)
/// or   (icmp Pred1 V1, C1) | (icmp Pred2 V2, C2)
/// into a single comparison using range-based reasoning.
/// NOTE: This is also used for logical and/or, must be poison-safe!
Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,
                                                     ICmpInst *ICmp2,
                                                     bool IsAnd) {}

/// Ignore all operations which only change the sign of a value, returning the
/// underlying magnitude value.
static Value *stripSignOnlyFPOps(Value *Val) {}

/// Matches canonical form of isnan, fcmp ord x, 0
static bool matchIsNotNaN(FCmpInst::Predicate P, Value *LHS, Value *RHS) {}

/// Matches fcmp u__ x, +/-inf
static bool matchUnorderedInfCompare(FCmpInst::Predicate P, Value *LHS,
                                     Value *RHS) {}

/// and (fcmp ord x, 0), (fcmp u* x, inf) -> fcmp o* x, inf
///
/// Clang emits this pattern for doing an isfinite check in __builtin_isnormal.
static Value *matchIsFiniteTest(InstCombiner::BuilderTy &Builder, FCmpInst *LHS,
                                FCmpInst *RHS) {}

Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
                                          bool IsAnd, bool IsLogicalSelect) {}

/// Match an fcmp against a special value that performs a test possible by
/// llvm.is.fpclass.
static bool matchIsFPClassLikeFCmp(Value *Op, Value *&ClassVal,
                                   uint64_t &ClassMask) {}

/// or (is_fpclass x, mask0), (is_fpclass x, mask1)
///     -> is_fpclass x, (mask0 | mask1)
/// and (is_fpclass x, mask0), (is_fpclass x, mask1)
///     -> is_fpclass x, (mask0 & mask1)
/// xor (is_fpclass x, mask0), (is_fpclass x, mask1)
///     -> is_fpclass x, (mask0 ^ mask1)
Instruction *InstCombinerImpl::foldLogicOfIsFPClass(BinaryOperator &BO,
                                                    Value *Op0, Value *Op1) {}

/// Look for the pattern that conditionally negates a value via math operations:
///   cond.splat = sext i1 cond
///   sub = add cond.splat, x
///   xor = xor sub, cond.splat
/// and rewrite it to do the same, but via logical operations:
///   value.neg = sub 0, value
///   cond = select i1 neg, value.neg, value
Instruction *InstCombinerImpl::canonicalizeConditionalNegationViaMathToSelect(
    BinaryOperator &I) {}

/// This a limited reassociation for a special case (see above) where we are
/// checking if two values are either both NAN (unordered) or not-NAN (ordered).
/// This could be handled more generally in '-reassociation', but it seems like
/// an unlikely pattern for a large number of logic ops and fcmps.
static Instruction *reassociateFCmps(BinaryOperator &BO,
                                     InstCombiner::BuilderTy &Builder) {}

/// Match variations of De Morgan's Laws:
/// (~A & ~B) == (~(A | B))
/// (~A | ~B) == (~(A & B))
static Instruction *matchDeMorgansLaws(BinaryOperator &I,
                                       InstCombiner &IC) {}

bool InstCombinerImpl::shouldOptimizeCast(CastInst *CI) {}

/// Fold {and,or,xor} (cast X), C.
static Instruction *foldLogicCastConstant(BinaryOperator &Logic, CastInst *Cast,
                                          InstCombinerImpl &IC) {}

/// Fold {and,or,xor} (cast X), Y.
Instruction *InstCombinerImpl::foldCastedBitwiseLogic(BinaryOperator &I) {}

static Instruction *foldAndToXor(BinaryOperator &I,
                                 InstCombiner::BuilderTy &Builder) {}

static Instruction *foldOrToXor(BinaryOperator &I,
                                InstCombiner::BuilderTy &Builder) {}

/// Return true if a constant shift amount is always less than the specified
/// bit-width. If not, the shift could create poison in the narrower type.
static bool canNarrowShiftAmt(Constant *C, unsigned BitWidth) {}

/// Try to use narrower ops (sink zext ops) for an 'and' with binop operand and
/// a common zext operand: and (binop (zext X), C), (zext X).
Instruction *InstCombinerImpl::narrowMaskedBinOp(BinaryOperator &And) {}

/// Try folding relatively complex patterns for both And and Or operations
/// with all And and Or swapped.
static Instruction *foldComplexAndOrPatterns(BinaryOperator &I,
                                             InstCombiner::BuilderTy &Builder) {}

/// Try to reassociate a pair of binops so that values with one use only are
/// part of the same instruction. This may enable folds that are limited with
/// multi-use restrictions and makes it more likely to match other patterns that
/// are looking for a common operand.
static Instruction *reassociateForUses(BinaryOperator &BO,
                                       InstCombinerImpl::BuilderTy &Builder) {}

// Match
// (X + C2) | C
// (X + C2) ^ C
// (X + C2) & C
// and convert to do the bitwise logic first:
// (X | C) + C2
// (X ^ C) + C2
// (X & C) + C2
// iff bits affected by logic op are lower than last bit affected by math op
static Instruction *canonicalizeLogicFirst(BinaryOperator &I,
                                           InstCombiner::BuilderTy &Builder) {}

// binop(shift(ShiftedC1, ShAmt), shift(ShiftedC2, add(ShAmt, AddC))) ->
// shift(binop(ShiftedC1, shift(ShiftedC2, AddC)), ShAmt)
// where both shifts are the same and AddC is a valid shift amount.
Instruction *InstCombinerImpl::foldBinOpOfDisplacedShifts(BinaryOperator &I) {}

// Fold and/or/xor with two equal intrinsic IDs:
// bitwise(fshl (A, B, ShAmt), fshl(C, D, ShAmt))
// -> fshl(bitwise(A, C), bitwise(B, D), ShAmt)
// bitwise(fshr (A, B, ShAmt), fshr(C, D, ShAmt))
// -> fshr(bitwise(A, C), bitwise(B, D), ShAmt)
// bitwise(bswap(A), bswap(B)) -> bswap(bitwise(A, B))
// bitwise(bswap(A), C) -> bswap(bitwise(A, bswap(C)))
// bitwise(bitreverse(A), bitreverse(B)) -> bitreverse(bitwise(A, B))
// bitwise(bitreverse(A), C) -> bitreverse(bitwise(A, bitreverse(C)))
static Instruction *
foldBitwiseLogicWithIntrinsics(BinaryOperator &I,
                               InstCombiner::BuilderTy &Builder) {}

// Try to simplify V by replacing occurrences of Op with RepOp, but only look
// through bitwise operations. In particular, for X | Y we try to replace Y with
// 0 inside X and for X & Y we try to replace Y with -1 inside X.
// Return the simplified result of X if successful, and nullptr otherwise.
// If SimplifyOnly is true, no new instructions will be created.
static Value *simplifyAndOrWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                          bool SimplifyOnly,
                                          InstCombinerImpl &IC,
                                          unsigned Depth = 0) {}

// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
// here. We should standardize that construct where it is needed or choose some
// other way to ensure that commutated variants of patterns are not missed.
Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {}

Instruction *InstCombinerImpl::matchBSwapOrBitReverse(Instruction &I,
                                                      bool MatchBSwaps,
                                                      bool MatchBitReversals) {}

std::optional<std::pair<Intrinsic::ID, SmallVector<Value *, 3>>>
InstCombinerImpl::convertOrOfShiftsToFunnelShift(Instruction &Or) {}

/// Match UB-safe variants of the funnel shift intrinsic.
static Instruction *matchFunnelShift(Instruction &Or, InstCombinerImpl &IC) {}

/// Attempt to combine or(zext(x),shl(zext(y),bw/2) concat packing patterns.
static Instruction *matchOrConcat(Instruction &Or,
                                  InstCombiner::BuilderTy &Builder) {}

/// If all elements of two constant vectors are 0/-1 and inverses, return true.
static bool areInverseVectorBitmasks(Constant *C1, Constant *C2) {}

/// We have an expression of the form (A & C) | (B & D). If A is a scalar or
/// vector composed of all-zeros or all-ones values and is the bitwise 'not' of
/// B, it can be used as the condition operand of a select instruction.
/// We will detect (A & C) | ~(B | D) when the flag ABIsTheSame enabled.
Value *InstCombinerImpl::getSelectCondition(Value *A, Value *B,
                                            bool ABIsTheSame) {}

/// We have an expression of the form (A & B) | (C & D). Try to simplify this
/// to "A' ? B : D", where A' is a boolean or vector of booleans.
/// When InvertFalseVal is set to true, we try to match the pattern
/// where we have peeked through a 'not' op and A and C are the same:
/// (A & B) | ~(A | D) --> (A & B) | (~A & ~D) --> A' ? B : ~D
Value *InstCombinerImpl::matchSelectFromAndOr(Value *A, Value *B, Value *C,
                                              Value *D, bool InvertFalseVal) {}

// (icmp eq X, C) | (icmp ult Other, (X - C)) -> (icmp ule Other, (X - (C + 1)))
// (icmp ne X, C) & (icmp uge Other, (X - C)) -> (icmp ugt Other, (X - (C + 1)))
static Value *foldAndOrOfICmpEqConstantAndICmp(ICmpInst *LHS, ICmpInst *RHS,
                                               bool IsAnd, bool IsLogical,
                                               IRBuilderBase &Builder) {}

/// Fold (icmp)&(icmp) or (icmp)|(icmp) if possible.
/// If IsLogical is true, then the and/or is in select form and the transform
/// must be poison-safe.
Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
                                          Instruction &I, bool IsAnd,
                                          bool IsLogical) {}

static Value *foldOrOfInversions(BinaryOperator &I,
                                 InstCombiner::BuilderTy &Builder) {}

// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
// here. We should standardize that construct where it is needed or choose some
// other way to ensure that commutated variants of patterns are not missed.
Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {}

/// A ^ B can be specified using other logic ops in a variety of patterns. We
/// can fold these early and efficiently by morphing an existing instruction.
static Instruction *foldXorToXor(BinaryOperator &I,
                                 InstCombiner::BuilderTy &Builder) {}

Value *InstCombinerImpl::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS,
                                        BinaryOperator &I) {}

/// If we have a masked merge, in the canonical form of:
/// (assuming that A only has one use.)
///   |        A  |  |B|
///   ((x ^ y) & M) ^ y
///    |  D  |
/// * If M is inverted:
///      |  D  |
///     ((x ^ y) & ~M) ^ y
///   We can canonicalize by swapping the final xor operand
///   to eliminate the 'not' of the mask.
///     ((x ^ y) & M) ^ x
/// * If M is a constant, and D has one use, we transform to 'and' / 'or' ops
///   because that shortens the dependency chain and improves analysis:
///     (x & M) | (y & ~M)
static Instruction *visitMaskedMerge(BinaryOperator &I,
                                     InstCombiner::BuilderTy &Builder) {}

static Instruction *foldNotXor(BinaryOperator &I,
                               InstCombiner::BuilderTy &Builder) {}

/// Canonicalize a shifty way to code absolute value to the more common pattern
/// that uses negation and select.
static Instruction *canonicalizeAbs(BinaryOperator &Xor,
                                    InstCombiner::BuilderTy &Builder) {}

static bool canFreelyInvert(InstCombiner &IC, Value *Op,
                            Instruction *IgnoredUser) {}

static Value *freelyInvert(InstCombinerImpl &IC, Value *Op,
                           Instruction *IgnoredUser) {}

// Transform
//   z = ~(x &/| y)
// into:
//   z = ((~x) |/& (~y))
// iff both x and y are free to invert and all uses of z can be freely updated.
bool InstCombinerImpl::sinkNotIntoLogicalOp(Instruction &I) {}

// Transform
//   z = (~x) &/| y
// into:
//   z = ~(x |/& (~y))
// iff y is free to invert and all uses of z can be freely updated.
bool InstCombinerImpl::sinkNotIntoOtherHandOfLogicalOp(Instruction &I) {}

Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) {}

// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
// here. We should standardize that construct where it is needed or choose some
// other way to ensure that commutated variants of patterns are not missed.
Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {}