xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineInternal.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- InstCombineInternal.h - InstCombine pass internals -------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric ///
110b57cec5SDimitry Andric /// This file provides internal interfaces used to implement the InstCombine.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #ifndef LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEINTERNAL_H
160b57cec5SDimitry Andric #define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEINTERNAL_H
170b57cec5SDimitry Andric 
185ffd83dbSDimitry Andric #include "llvm/ADT/Statistic.h"
195f757f3fSDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
200b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/TargetFolder.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
230b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
240b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h"
250b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
26349cc55cSDimitry Andric #include "llvm/IR/Value.h"
270b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
280b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h"
29e8d8bef9SDimitry Andric #include "llvm/Transforms/InstCombine/InstCombiner.h"
300b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
310b57cec5SDimitry Andric #include <cassert>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #define DEBUG_TYPE "instcombine"
34349cc55cSDimitry Andric #include "llvm/Transforms/Utils/InstructionWorklist.h"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm::PatternMatch;
370b57cec5SDimitry Andric 
38e8d8bef9SDimitry Andric // As a default, let's assume that we want to be aggressive,
39e8d8bef9SDimitry Andric // and attempt to traverse with no limits in attempt to sink negation.
40e8d8bef9SDimitry Andric static constexpr unsigned NegatorDefaultMaxDepth = ~0U;
41e8d8bef9SDimitry Andric 
42e8d8bef9SDimitry Andric // Let's guesstimate that most often we will end up visiting/producing
43e8d8bef9SDimitry Andric // fairly small number of new instructions.
44e8d8bef9SDimitry Andric static constexpr unsigned NegatorMaxNodesSSO = 16;
45e8d8bef9SDimitry Andric 
460b57cec5SDimitry Andric namespace llvm {
470b57cec5SDimitry Andric 
485ffd83dbSDimitry Andric class AAResults;
490b57cec5SDimitry Andric class APInt;
500b57cec5SDimitry Andric class AssumptionCache;
510b57cec5SDimitry Andric class BlockFrequencyInfo;
520b57cec5SDimitry Andric class DataLayout;
530b57cec5SDimitry Andric class DominatorTree;
540b57cec5SDimitry Andric class GEPOperator;
550b57cec5SDimitry Andric class GlobalVariable;
560b57cec5SDimitry Andric class LoopInfo;
570b57cec5SDimitry Andric class OptimizationRemarkEmitter;
580b57cec5SDimitry Andric class ProfileSummaryInfo;
590b57cec5SDimitry Andric class TargetLibraryInfo;
600b57cec5SDimitry Andric class User;
610b57cec5SDimitry Andric 
62e8d8bef9SDimitry Andric class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
63e8d8bef9SDimitry Andric     : public InstCombiner,
64e8d8bef9SDimitry Andric       public InstVisitor<InstCombinerImpl, Instruction *> {
650b57cec5SDimitry Andric public:
66349cc55cSDimitry Andric   InstCombinerImpl(InstructionWorklist &Worklist, BuilderTy &Builder,
67e8d8bef9SDimitry Andric                    bool MinimizeSize, AAResults *AA, AssumptionCache &AC,
68e8d8bef9SDimitry Andric                    TargetLibraryInfo &TLI, TargetTransformInfo &TTI,
69e8d8bef9SDimitry Andric                    DominatorTree &DT, OptimizationRemarkEmitter &ORE,
70*0fca6ea1SDimitry Andric                    BlockFrequencyInfo *BFI, BranchProbabilityInfo *BPI,
71*0fca6ea1SDimitry Andric                    ProfileSummaryInfo *PSI, const DataLayout &DL, LoopInfo *LI)
72e8d8bef9SDimitry Andric       : InstCombiner(Worklist, Builder, MinimizeSize, AA, AC, TLI, TTI, DT, ORE,
73*0fca6ea1SDimitry Andric                      BFI, BPI, PSI, DL, LI) {}
740b57cec5SDimitry Andric 
7581ad6265SDimitry Andric   virtual ~InstCombinerImpl() = default;
760b57cec5SDimitry Andric 
775f757f3fSDimitry Andric   /// Perform early cleanup and prepare the InstCombine worklist.
785f757f3fSDimitry Andric   bool prepareWorklist(Function &F,
795f757f3fSDimitry Andric                        ReversePostOrderTraversal<BasicBlock *> &RPOT);
805f757f3fSDimitry Andric 
810b57cec5SDimitry Andric   /// Run the combiner over the entire worklist until it is empty.
820b57cec5SDimitry Andric   ///
830b57cec5SDimitry Andric   /// \returns true if the IR is changed.
840b57cec5SDimitry Andric   bool run();
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   // Visitation implementation - Implement instruction combining for different
870b57cec5SDimitry Andric   // instruction types.  The semantics are as follows:
880b57cec5SDimitry Andric   // Return Value:
890b57cec5SDimitry Andric   //    null        - No change was made
900b57cec5SDimitry Andric   //     I          - Change was made, I is still valid, I may be dead though
910b57cec5SDimitry Andric   //   otherwise    - Change was made, replace I with returned instruction
920b57cec5SDimitry Andric   //
930b57cec5SDimitry Andric   Instruction *visitFNeg(UnaryOperator &I);
940b57cec5SDimitry Andric   Instruction *visitAdd(BinaryOperator &I);
950b57cec5SDimitry Andric   Instruction *visitFAdd(BinaryOperator &I);
96480093f4SDimitry Andric   Value *OptimizePointerDifference(
97480093f4SDimitry Andric       Value *LHS, Value *RHS, Type *Ty, bool isNUW);
980b57cec5SDimitry Andric   Instruction *visitSub(BinaryOperator &I);
990b57cec5SDimitry Andric   Instruction *visitFSub(BinaryOperator &I);
1000b57cec5SDimitry Andric   Instruction *visitMul(BinaryOperator &I);
101*0fca6ea1SDimitry Andric   Instruction *foldPowiReassoc(BinaryOperator &I);
1025f757f3fSDimitry Andric   Instruction *foldFMulReassoc(BinaryOperator &I);
1030b57cec5SDimitry Andric   Instruction *visitFMul(BinaryOperator &I);
1040b57cec5SDimitry Andric   Instruction *visitURem(BinaryOperator &I);
1050b57cec5SDimitry Andric   Instruction *visitSRem(BinaryOperator &I);
1060b57cec5SDimitry Andric   Instruction *visitFRem(BinaryOperator &I);
1070b57cec5SDimitry Andric   bool simplifyDivRemOfSelectWithZeroOp(BinaryOperator &I);
1080b57cec5SDimitry Andric   Instruction *commonIRemTransforms(BinaryOperator &I);
1090b57cec5SDimitry Andric   Instruction *commonIDivTransforms(BinaryOperator &I);
1100b57cec5SDimitry Andric   Instruction *visitUDiv(BinaryOperator &I);
1110b57cec5SDimitry Andric   Instruction *visitSDiv(BinaryOperator &I);
1120b57cec5SDimitry Andric   Instruction *visitFDiv(BinaryOperator &I);
1130b57cec5SDimitry Andric   Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted);
1140b57cec5SDimitry Andric   Instruction *visitAnd(BinaryOperator &I);
1150b57cec5SDimitry Andric   Instruction *visitOr(BinaryOperator &I);
116bdd1243dSDimitry Andric   bool sinkNotIntoLogicalOp(Instruction &I);
117bdd1243dSDimitry Andric   bool sinkNotIntoOtherHandOfLogicalOp(Instruction &I);
1180b57cec5SDimitry Andric   Instruction *visitXor(BinaryOperator &I);
1190b57cec5SDimitry Andric   Instruction *visitShl(BinaryOperator &I);
1208bcb0991SDimitry Andric   Value *reassociateShiftAmtsOfTwoSameDirectionShifts(
1218bcb0991SDimitry Andric       BinaryOperator *Sh0, const SimplifyQuery &SQ,
1228bcb0991SDimitry Andric       bool AnalyzeForSignBitExtraction = false);
1238bcb0991SDimitry Andric   Instruction *canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
1248bcb0991SDimitry Andric       BinaryOperator &I);
1258bcb0991SDimitry Andric   Instruction *foldVariableSignZeroExtensionOfVariableHighBitExtract(
1268bcb0991SDimitry Andric       BinaryOperator &OldAShr);
1270b57cec5SDimitry Andric   Instruction *visitAShr(BinaryOperator &I);
1280b57cec5SDimitry Andric   Instruction *visitLShr(BinaryOperator &I);
1290b57cec5SDimitry Andric   Instruction *commonShiftTransforms(BinaryOperator &I);
1300b57cec5SDimitry Andric   Instruction *visitFCmpInst(FCmpInst &I);
131e8d8bef9SDimitry Andric   CmpInst *canonicalizeICmpPredicate(CmpInst &I);
1320b57cec5SDimitry Andric   Instruction *visitICmpInst(ICmpInst &I);
1330b57cec5SDimitry Andric   Instruction *FoldShiftByConstant(Value *Op0, Constant *Op1,
1340b57cec5SDimitry Andric                                    BinaryOperator &I);
1350b57cec5SDimitry Andric   Instruction *commonCastTransforms(CastInst &CI);
1360b57cec5SDimitry Andric   Instruction *visitTrunc(TruncInst &CI);
137bdd1243dSDimitry Andric   Instruction *visitZExt(ZExtInst &Zext);
138bdd1243dSDimitry Andric   Instruction *visitSExt(SExtInst &Sext);
1390b57cec5SDimitry Andric   Instruction *visitFPTrunc(FPTruncInst &CI);
1400b57cec5SDimitry Andric   Instruction *visitFPExt(CastInst &CI);
1410b57cec5SDimitry Andric   Instruction *visitFPToUI(FPToUIInst &FI);
1420b57cec5SDimitry Andric   Instruction *visitFPToSI(FPToSIInst &FI);
1430b57cec5SDimitry Andric   Instruction *visitUIToFP(CastInst &CI);
1440b57cec5SDimitry Andric   Instruction *visitSIToFP(CastInst &CI);
1450b57cec5SDimitry Andric   Instruction *visitPtrToInt(PtrToIntInst &CI);
1460b57cec5SDimitry Andric   Instruction *visitIntToPtr(IntToPtrInst &CI);
1470b57cec5SDimitry Andric   Instruction *visitBitCast(BitCastInst &CI);
1480b57cec5SDimitry Andric   Instruction *visitAddrSpaceCast(AddrSpaceCastInst &CI);
1495ffd83dbSDimitry Andric   Instruction *foldItoFPtoI(CastInst &FI);
1500b57cec5SDimitry Andric   Instruction *visitSelectInst(SelectInst &SI);
1510b57cec5SDimitry Andric   Instruction *visitCallInst(CallInst &CI);
1520b57cec5SDimitry Andric   Instruction *visitInvokeInst(InvokeInst &II);
1530b57cec5SDimitry Andric   Instruction *visitCallBrInst(CallBrInst &CBI);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   Instruction *SliceUpIllegalIntegerPHI(PHINode &PN);
1560b57cec5SDimitry Andric   Instruction *visitPHINode(PHINode &PN);
1570b57cec5SDimitry Andric   Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
15804eeddc0SDimitry Andric   Instruction *visitGEPOfGEP(GetElementPtrInst &GEP, GEPOperator *Src);
1590b57cec5SDimitry Andric   Instruction *visitAllocaInst(AllocaInst &AI);
1600b57cec5SDimitry Andric   Instruction *visitAllocSite(Instruction &FI);
161fcaf7f86SDimitry Andric   Instruction *visitFree(CallInst &FI, Value *FreedOp);
1620b57cec5SDimitry Andric   Instruction *visitLoadInst(LoadInst &LI);
1630b57cec5SDimitry Andric   Instruction *visitStoreInst(StoreInst &SI);
1640b57cec5SDimitry Andric   Instruction *visitAtomicRMWInst(AtomicRMWInst &SI);
1655ffd83dbSDimitry Andric   Instruction *visitUnconditionalBranchInst(BranchInst &BI);
1660b57cec5SDimitry Andric   Instruction *visitBranchInst(BranchInst &BI);
1670b57cec5SDimitry Andric   Instruction *visitFenceInst(FenceInst &FI);
1680b57cec5SDimitry Andric   Instruction *visitSwitchInst(SwitchInst &SI);
1690b57cec5SDimitry Andric   Instruction *visitReturnInst(ReturnInst &RI);
170e8d8bef9SDimitry Andric   Instruction *visitUnreachableInst(UnreachableInst &I);
171e8d8bef9SDimitry Andric   Instruction *
172e8d8bef9SDimitry Andric   foldAggregateConstructionIntoAggregateReuse(InsertValueInst &OrigIVI);
1730b57cec5SDimitry Andric   Instruction *visitInsertValueInst(InsertValueInst &IV);
1740b57cec5SDimitry Andric   Instruction *visitInsertElementInst(InsertElementInst &IE);
1750b57cec5SDimitry Andric   Instruction *visitExtractElementInst(ExtractElementInst &EI);
176bdd1243dSDimitry Andric   Instruction *simplifyBinOpSplats(ShuffleVectorInst &SVI);
1770b57cec5SDimitry Andric   Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI);
1780b57cec5SDimitry Andric   Instruction *visitExtractValueInst(ExtractValueInst &EV);
1790b57cec5SDimitry Andric   Instruction *visitLandingPadInst(LandingPadInst &LI);
1805ffd83dbSDimitry Andric   Instruction *visitVAEndInst(VAEndInst &I);
181fe6060f1SDimitry Andric   Value *pushFreezeToPreventPoisonFromPropagating(FreezeInst &FI);
18281ad6265SDimitry Andric   bool freezeOtherUses(FreezeInst &FI);
18381ad6265SDimitry Andric   Instruction *foldFreezeIntoRecurrence(FreezeInst &I, PHINode *PN);
184480093f4SDimitry Andric   Instruction *visitFreeze(FreezeInst &I);
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   /// Specify what to return for unhandled instructions.
1870b57cec5SDimitry Andric   Instruction *visitInstruction(Instruction &I) { return nullptr; }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   /// True when DB dominates all uses of DI except UI.
1900b57cec5SDimitry Andric   /// UI must be in the same block as DI.
1910b57cec5SDimitry Andric   /// The routine checks that the DI parent and DB are different.
1920b57cec5SDimitry Andric   bool dominatesAllUses(const Instruction *DI, const Instruction *UI,
1930b57cec5SDimitry Andric                         const BasicBlock *DB) const;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   /// Try to replace select with select operand SIOpd in SI-ICmp sequence.
1960b57cec5SDimitry Andric   bool replacedSelectWithOperand(SelectInst *SI, const ICmpInst *Icmp,
1970b57cec5SDimitry Andric                                  const unsigned SIOpd);
1980b57cec5SDimitry Andric 
199480093f4SDimitry Andric   LoadInst *combineLoadToNewType(LoadInst &LI, Type *NewTy,
200480093f4SDimitry Andric                                  const Twine &Suffix = "");
201480093f4SDimitry Andric 
2025f757f3fSDimitry Andric   KnownFPClass computeKnownFPClass(Value *Val, FastMathFlags FMF,
2035f757f3fSDimitry Andric                                    FPClassTest Interested = fcAllFlags,
2045f757f3fSDimitry Andric                                    const Instruction *CtxI = nullptr,
2055f757f3fSDimitry Andric                                    unsigned Depth = 0) const {
206*0fca6ea1SDimitry Andric     return llvm::computeKnownFPClass(
207*0fca6ea1SDimitry Andric         Val, FMF, Interested, Depth,
208*0fca6ea1SDimitry Andric         getSimplifyQuery().getWithInstruction(CtxI));
2095f757f3fSDimitry Andric   }
2105f757f3fSDimitry Andric 
2115f757f3fSDimitry Andric   KnownFPClass computeKnownFPClass(Value *Val,
2125f757f3fSDimitry Andric                                    FPClassTest Interested = fcAllFlags,
2135f757f3fSDimitry Andric                                    const Instruction *CtxI = nullptr,
2145f757f3fSDimitry Andric                                    unsigned Depth = 0) const {
215*0fca6ea1SDimitry Andric     return llvm::computeKnownFPClass(
216*0fca6ea1SDimitry Andric         Val, Interested, Depth, getSimplifyQuery().getWithInstruction(CtxI));
2175f757f3fSDimitry Andric   }
2185f757f3fSDimitry Andric 
2195f757f3fSDimitry Andric   /// Check if fmul \p MulVal, +0.0 will yield +0.0 (or signed zero is
2205f757f3fSDimitry Andric   /// ignorable).
2215f757f3fSDimitry Andric   bool fmulByZeroIsZero(Value *MulVal, FastMathFlags FMF,
2225f757f3fSDimitry Andric                         const Instruction *CtxI) const;
2235f757f3fSDimitry Andric 
2245f757f3fSDimitry Andric   Constant *getLosslessTrunc(Constant *C, Type *TruncTy, unsigned ExtOp) {
2255f757f3fSDimitry Andric     Constant *TruncC = ConstantExpr::getTrunc(C, TruncTy);
2265f757f3fSDimitry Andric     Constant *ExtTruncC =
2275f757f3fSDimitry Andric         ConstantFoldCastOperand(ExtOp, TruncC, C->getType(), DL);
2285f757f3fSDimitry Andric     if (ExtTruncC && ExtTruncC == C)
2295f757f3fSDimitry Andric       return TruncC;
2305f757f3fSDimitry Andric     return nullptr;
2315f757f3fSDimitry Andric   }
2325f757f3fSDimitry Andric 
2335f757f3fSDimitry Andric   Constant *getLosslessUnsignedTrunc(Constant *C, Type *TruncTy) {
2345f757f3fSDimitry Andric     return getLosslessTrunc(C, TruncTy, Instruction::ZExt);
2355f757f3fSDimitry Andric   }
2365f757f3fSDimitry Andric 
2375f757f3fSDimitry Andric   Constant *getLosslessSignedTrunc(Constant *C, Type *TruncTy) {
2385f757f3fSDimitry Andric     return getLosslessTrunc(C, TruncTy, Instruction::SExt);
2395f757f3fSDimitry Andric   }
2405f757f3fSDimitry Andric 
241*0fca6ea1SDimitry Andric   std::optional<std::pair<Intrinsic::ID, SmallVector<Value *, 3>>>
242*0fca6ea1SDimitry Andric   convertOrOfShiftsToFunnelShift(Instruction &Or);
243*0fca6ea1SDimitry Andric 
2440b57cec5SDimitry Andric private:
24581ad6265SDimitry Andric   bool annotateAnyAllocSite(CallBase &Call, const TargetLibraryInfo *TLI);
246349cc55cSDimitry Andric   bool isDesirableIntType(unsigned BitWidth) const;
2470b57cec5SDimitry Andric   bool shouldChangeType(unsigned FromBitWidth, unsigned ToBitWidth) const;
2480b57cec5SDimitry Andric   bool shouldChangeType(Type *From, Type *To) const;
2490b57cec5SDimitry Andric   Value *dyn_castNegVal(Value *V) const;
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   /// Classify whether a cast is worth optimizing.
2520b57cec5SDimitry Andric   ///
2530b57cec5SDimitry Andric   /// This is a helper to decide whether the simplification of
2540b57cec5SDimitry Andric   /// logic(cast(A), cast(B)) to cast(logic(A, B)) should be performed.
2550b57cec5SDimitry Andric   ///
2560b57cec5SDimitry Andric   /// \param CI The cast we are interested in.
2570b57cec5SDimitry Andric   ///
2580b57cec5SDimitry Andric   /// \return true if this cast actually results in any code being generated and
2590b57cec5SDimitry Andric   /// if it cannot already be eliminated by some other transformation.
2600b57cec5SDimitry Andric   bool shouldOptimizeCast(CastInst *CI);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   /// Try to optimize a sequence of instructions checking if an operation
2630b57cec5SDimitry Andric   /// on LHS and RHS overflows.
2640b57cec5SDimitry Andric   ///
2650b57cec5SDimitry Andric   /// If this overflow check is done via one of the overflow check intrinsics,
2660b57cec5SDimitry Andric   /// then CtxI has to be the call instruction calling that intrinsic.  If this
2670b57cec5SDimitry Andric   /// overflow check is done by arithmetic followed by a compare, then CtxI has
2680b57cec5SDimitry Andric   /// to be the arithmetic instruction.
2690b57cec5SDimitry Andric   ///
2700b57cec5SDimitry Andric   /// If a simplification is possible, stores the simplified result of the
2710b57cec5SDimitry Andric   /// operation in OperationResult and result of the overflow check in
2720b57cec5SDimitry Andric   /// OverflowResult, and return true.  If no simplification is possible,
2730b57cec5SDimitry Andric   /// returns false.
2740b57cec5SDimitry Andric   bool OptimizeOverflowCheck(Instruction::BinaryOps BinaryOp, bool IsSigned,
2750b57cec5SDimitry Andric                              Value *LHS, Value *RHS,
2760b57cec5SDimitry Andric                              Instruction &CtxI, Value *&OperationResult,
2770b57cec5SDimitry Andric                              Constant *&OverflowResult);
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   Instruction *visitCallBase(CallBase &Call);
2800b57cec5SDimitry Andric   Instruction *tryOptimizeCall(CallInst *CI);
2810b57cec5SDimitry Andric   bool transformConstExprCastCall(CallBase &Call);
2820b57cec5SDimitry Andric   Instruction *transformCallThroughTrampoline(CallBase &Call,
2830b57cec5SDimitry Andric                                               IntrinsicInst &Tramp);
2840b57cec5SDimitry Andric 
2851db9f3b2SDimitry Andric   // Return (a, b) if (LHS, RHS) is known to be (a, b) or (b, a).
2861db9f3b2SDimitry Andric   // Otherwise, return std::nullopt
2871db9f3b2SDimitry Andric   // Currently it matches:
2881db9f3b2SDimitry Andric   // - LHS = (select c, a, b), RHS = (select c, b, a)
2891db9f3b2SDimitry Andric   // - LHS = (phi [a, BB0], [b, BB1]), RHS = (phi [b, BB0], [a, BB1])
2901db9f3b2SDimitry Andric   // - LHS = min(a, b), RHS = max(a, b)
2911db9f3b2SDimitry Andric   std::optional<std::pair<Value *, Value *>> matchSymmetricPair(Value *LHS,
2921db9f3b2SDimitry Andric                                                                 Value *RHS);
293cb14a3feSDimitry Andric 
2940b57cec5SDimitry Andric   Value *simplifyMaskedLoad(IntrinsicInst &II);
2950b57cec5SDimitry Andric   Instruction *simplifyMaskedStore(IntrinsicInst &II);
2960b57cec5SDimitry Andric   Instruction *simplifyMaskedGather(IntrinsicInst &II);
2970b57cec5SDimitry Andric   Instruction *simplifyMaskedScatter(IntrinsicInst &II);
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   /// Transform (zext icmp) to bitwise / integer operations in order to
3000b57cec5SDimitry Andric   /// eliminate it.
3010b57cec5SDimitry Andric   ///
3020b57cec5SDimitry Andric   /// \param ICI The icmp of the (zext icmp) pair we are interested in.
3030b57cec5SDimitry Andric   /// \parem CI The zext of the (zext icmp) pair we are interested in.
3040b57cec5SDimitry Andric   ///
3050b57cec5SDimitry Andric   /// \return null if the transformation cannot be performed. If the
3060b57cec5SDimitry Andric   /// transformation can be performed the new instruction that replaces the
307349cc55cSDimitry Andric   /// (zext icmp) pair will be returned.
308bdd1243dSDimitry Andric   Instruction *transformZExtICmp(ICmpInst *Cmp, ZExtInst &Zext);
3090b57cec5SDimitry Andric 
310bdd1243dSDimitry Andric   Instruction *transformSExtICmp(ICmpInst *Cmp, SExtInst &Sext);
3110b57cec5SDimitry Andric 
3125f757f3fSDimitry Andric   bool willNotOverflowSignedAdd(const WithCache<const Value *> &LHS,
3135f757f3fSDimitry Andric                                 const WithCache<const Value *> &RHS,
3140b57cec5SDimitry Andric                                 const Instruction &CxtI) const {
3150b57cec5SDimitry Andric     return computeOverflowForSignedAdd(LHS, RHS, &CxtI) ==
3160b57cec5SDimitry Andric            OverflowResult::NeverOverflows;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric 
3195f757f3fSDimitry Andric   bool willNotOverflowUnsignedAdd(const WithCache<const Value *> &LHS,
3205f757f3fSDimitry Andric                                   const WithCache<const Value *> &RHS,
3210b57cec5SDimitry Andric                                   const Instruction &CxtI) const {
3220b57cec5SDimitry Andric     return computeOverflowForUnsignedAdd(LHS, RHS, &CxtI) ==
3230b57cec5SDimitry Andric            OverflowResult::NeverOverflows;
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   bool willNotOverflowAdd(const Value *LHS, const Value *RHS,
3270b57cec5SDimitry Andric                           const Instruction &CxtI, bool IsSigned) const {
3280b57cec5SDimitry Andric     return IsSigned ? willNotOverflowSignedAdd(LHS, RHS, CxtI)
3290b57cec5SDimitry Andric                     : willNotOverflowUnsignedAdd(LHS, RHS, CxtI);
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   bool willNotOverflowSignedSub(const Value *LHS, const Value *RHS,
3330b57cec5SDimitry Andric                                 const Instruction &CxtI) const {
3340b57cec5SDimitry Andric     return computeOverflowForSignedSub(LHS, RHS, &CxtI) ==
3350b57cec5SDimitry Andric            OverflowResult::NeverOverflows;
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   bool willNotOverflowUnsignedSub(const Value *LHS, const Value *RHS,
3390b57cec5SDimitry Andric                                   const Instruction &CxtI) const {
3400b57cec5SDimitry Andric     return computeOverflowForUnsignedSub(LHS, RHS, &CxtI) ==
3410b57cec5SDimitry Andric            OverflowResult::NeverOverflows;
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   bool willNotOverflowSub(const Value *LHS, const Value *RHS,
3450b57cec5SDimitry Andric                           const Instruction &CxtI, bool IsSigned) const {
3460b57cec5SDimitry Andric     return IsSigned ? willNotOverflowSignedSub(LHS, RHS, CxtI)
3470b57cec5SDimitry Andric                     : willNotOverflowUnsignedSub(LHS, RHS, CxtI);
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   bool willNotOverflowSignedMul(const Value *LHS, const Value *RHS,
3510b57cec5SDimitry Andric                                 const Instruction &CxtI) const {
3520b57cec5SDimitry Andric     return computeOverflowForSignedMul(LHS, RHS, &CxtI) ==
3530b57cec5SDimitry Andric            OverflowResult::NeverOverflows;
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   bool willNotOverflowUnsignedMul(const Value *LHS, const Value *RHS,
357*0fca6ea1SDimitry Andric                                   const Instruction &CxtI,
358*0fca6ea1SDimitry Andric                                   bool IsNSW = false) const {
359*0fca6ea1SDimitry Andric     return computeOverflowForUnsignedMul(LHS, RHS, &CxtI, IsNSW) ==
3600b57cec5SDimitry Andric            OverflowResult::NeverOverflows;
3610b57cec5SDimitry Andric   }
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   bool willNotOverflowMul(const Value *LHS, const Value *RHS,
3640b57cec5SDimitry Andric                           const Instruction &CxtI, bool IsSigned) const {
3650b57cec5SDimitry Andric     return IsSigned ? willNotOverflowSignedMul(LHS, RHS, CxtI)
3660b57cec5SDimitry Andric                     : willNotOverflowUnsignedMul(LHS, RHS, CxtI);
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   bool willNotOverflow(BinaryOperator::BinaryOps Opcode, const Value *LHS,
3700b57cec5SDimitry Andric                        const Value *RHS, const Instruction &CxtI,
3710b57cec5SDimitry Andric                        bool IsSigned) const {
3720b57cec5SDimitry Andric     switch (Opcode) {
3730b57cec5SDimitry Andric     case Instruction::Add: return willNotOverflowAdd(LHS, RHS, CxtI, IsSigned);
3740b57cec5SDimitry Andric     case Instruction::Sub: return willNotOverflowSub(LHS, RHS, CxtI, IsSigned);
3750b57cec5SDimitry Andric     case Instruction::Mul: return willNotOverflowMul(LHS, RHS, CxtI, IsSigned);
3760b57cec5SDimitry Andric     default: llvm_unreachable("Unexpected opcode for overflow query");
3770b57cec5SDimitry Andric     }
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric 
380*0fca6ea1SDimitry Andric   Value *EmitGEPOffset(GEPOperator *GEP, bool RewriteGEP = false);
3810b57cec5SDimitry Andric   Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
382349cc55cSDimitry Andric   Instruction *foldBitcastExtElt(ExtractElementInst &ExtElt);
3830b57cec5SDimitry Andric   Instruction *foldCastedBitwiseLogic(BinaryOperator &I);
384*0fca6ea1SDimitry Andric   Instruction *foldFBinOpOfIntCasts(BinaryOperator &I);
385*0fca6ea1SDimitry Andric   // Should only be called by `foldFBinOpOfIntCasts`.
386*0fca6ea1SDimitry Andric   Instruction *foldFBinOpOfIntCastsFromSign(
387*0fca6ea1SDimitry Andric       BinaryOperator &BO, bool OpsFromSigned, std::array<Value *, 2> IntOps,
388*0fca6ea1SDimitry Andric       Constant *Op1FpC, SmallVectorImpl<WithCache<const Value *>> &OpsKnown);
3894824e7fdSDimitry Andric   Instruction *foldBinopOfSextBoolToSelect(BinaryOperator &I);
3900b57cec5SDimitry Andric   Instruction *narrowBinOp(TruncInst &Trunc);
3910b57cec5SDimitry Andric   Instruction *narrowMaskedBinOp(BinaryOperator &And);
3920b57cec5SDimitry Andric   Instruction *narrowMathIfNoOverflow(BinaryOperator &I);
393e8d8bef9SDimitry Andric   Instruction *narrowFunnelShift(TruncInst &Trunc);
3940b57cec5SDimitry Andric   Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);
39581ad6265SDimitry Andric   Instruction *matchSAddSubSat(IntrinsicInst &MinMax1);
396349cc55cSDimitry Andric   Instruction *foldNot(BinaryOperator &I);
39706c3fb27SDimitry Andric   Instruction *foldBinOpOfDisplacedShifts(BinaryOperator &I);
398e8d8bef9SDimitry Andric 
3990b57cec5SDimitry Andric   /// Determine if a pair of casts can be replaced by a single cast.
4000b57cec5SDimitry Andric   ///
4010b57cec5SDimitry Andric   /// \param CI1 The first of a pair of casts.
4020b57cec5SDimitry Andric   /// \param CI2 The second of a pair of casts.
4030b57cec5SDimitry Andric   ///
4040b57cec5SDimitry Andric   /// \return 0 if the cast pair cannot be eliminated, otherwise returns an
4050b57cec5SDimitry Andric   /// Instruction::CastOps value for a cast that can replace the pair, casting
4060b57cec5SDimitry Andric   /// CI1->getSrcTy() to CI2->getDstTy().
4070b57cec5SDimitry Andric   ///
4080b57cec5SDimitry Andric   /// \see CastInst::isEliminableCastPair
4090b57cec5SDimitry Andric   Instruction::CastOps isEliminableCastPair(const CastInst *CI1,
4100b57cec5SDimitry Andric                                             const CastInst *CI2);
411fe6060f1SDimitry Andric   Value *simplifyIntToPtrRoundTripCast(Value *Val);
4120b57cec5SDimitry Andric 
41381ad6265SDimitry Andric   Value *foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &I,
41481ad6265SDimitry Andric                           bool IsAnd, bool IsLogical = false);
4155ffd83dbSDimitry Andric   Value *foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS, BinaryOperator &Xor);
4160b57cec5SDimitry Andric 
417349cc55cSDimitry Andric   Value *foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd);
418349cc55cSDimitry Andric 
41981ad6265SDimitry Andric   Value *foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1, ICmpInst *ICmp2,
42081ad6265SDimitry Andric                                      bool IsAnd);
42181ad6265SDimitry Andric 
4220b57cec5SDimitry Andric   /// Optimize (fcmp)&(fcmp) or (fcmp)|(fcmp).
4230b57cec5SDimitry Andric   /// NOTE: Unlike most of instcombine, this returns a Value which should
4240b57cec5SDimitry Andric   /// already be inserted into the function.
42581ad6265SDimitry Andric   Value *foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd,
42681ad6265SDimitry Andric                           bool IsLogicalSelect = false);
4270b57cec5SDimitry Andric 
428bdd1243dSDimitry Andric   Instruction *foldLogicOfIsFPClass(BinaryOperator &Operator, Value *LHS,
429bdd1243dSDimitry Andric                                     Value *RHS);
430bdd1243dSDimitry Andric 
431bdd1243dSDimitry Andric   Instruction *
432bdd1243dSDimitry Andric   canonicalizeConditionalNegationViaMathToSelect(BinaryOperator &i);
433bdd1243dSDimitry Andric 
4340b57cec5SDimitry Andric   Value *foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS,
435fe6060f1SDimitry Andric                                        Instruction *CxtI, bool IsAnd,
436fe6060f1SDimitry Andric                                        bool IsLogical = false);
437bdd1243dSDimitry Andric   Value *matchSelectFromAndOr(Value *A, Value *B, Value *C, Value *D,
438bdd1243dSDimitry Andric                               bool InvertFalseVal = false);
439bdd1243dSDimitry Andric   Value *getSelectCondition(Value *A, Value *B, bool ABIsTheSame);
4400b57cec5SDimitry Andric 
441bdd1243dSDimitry Andric   Instruction *foldLShrOverflowBit(BinaryOperator &I);
442bdd1243dSDimitry Andric   Instruction *foldExtractOfOverflowIntrinsic(ExtractValueInst &EV);
4430b57cec5SDimitry Andric   Instruction *foldIntrinsicWithOverflowCommon(IntrinsicInst *II);
44406c3fb27SDimitry Andric   Instruction *foldIntrinsicIsFPClass(IntrinsicInst &II);
4455ffd83dbSDimitry Andric   Instruction *foldFPSignBitOps(BinaryOperator &I);
446bdd1243dSDimitry Andric   Instruction *foldFDivConstantDivisor(BinaryOperator &I);
4470b57cec5SDimitry Andric 
448fe6060f1SDimitry Andric   // Optimize one of these forms:
449fe6060f1SDimitry Andric   //   and i1 Op, SI / select i1 Op, i1 SI, i1 false (if IsAnd = true)
450fe6060f1SDimitry Andric   //   or i1 Op, SI  / select i1 Op, i1 true, i1 SI  (if IsAnd = false)
451fe6060f1SDimitry Andric   // into simplier select instruction using isImpliedCondition.
452fe6060f1SDimitry Andric   Instruction *foldAndOrOfSelectUsingImpliedCond(Value *Op, SelectInst &SI,
453fe6060f1SDimitry Andric                                                  bool IsAnd);
454fe6060f1SDimitry Andric 
4555f757f3fSDimitry Andric   Instruction *hoistFNegAboveFMulFDiv(Value *FNegOp, Instruction &FMFSource);
4565f757f3fSDimitry Andric 
4570b57cec5SDimitry Andric public:
4580b57cec5SDimitry Andric   /// Create and insert the idiom we use to indicate a block is unreachable
4590b57cec5SDimitry Andric   /// without having to rewrite the CFG from within InstCombine.
4600b57cec5SDimitry Andric   void CreateNonTerminatorUnreachable(Instruction *InsertAt) {
4610b57cec5SDimitry Andric     auto &Ctx = InsertAt->getContext();
46206c3fb27SDimitry Andric     auto *SI = new StoreInst(ConstantInt::getTrue(Ctx),
4635f757f3fSDimitry Andric                              PoisonValue::get(PointerType::getUnqual(Ctx)),
46406c3fb27SDimitry Andric                              /*isVolatile*/ false, Align(1));
465*0fca6ea1SDimitry Andric     InsertNewInstWith(SI, InsertAt->getIterator());
4660b57cec5SDimitry Andric   }
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   /// Combiner aware instruction erasure.
4690b57cec5SDimitry Andric   ///
4700b57cec5SDimitry Andric   /// When dealing with an instruction that has side effects or produces a void
4710b57cec5SDimitry Andric   /// value, we can't rely on DCE to delete the instruction. Instead, visit
4720b57cec5SDimitry Andric   /// methods should return the value returned by this function.
473e8d8bef9SDimitry Andric   Instruction *eraseInstFromFunction(Instruction &I) override {
4740b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "IC: ERASE " << I << '\n');
4750b57cec5SDimitry Andric     assert(I.use_empty() && "Cannot erase instruction that is used!");
4765ffd83dbSDimitry Andric     salvageDebugInfo(I);
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric     // Make sure that we reprocess all operands now that we reduced their
4790b57cec5SDimitry Andric     // use counts.
48006c3fb27SDimitry Andric     SmallVector<Value *> Ops(I.operands());
4815ffd83dbSDimitry Andric     Worklist.remove(&I);
4825f757f3fSDimitry Andric     DC.removeValue(&I);
4830b57cec5SDimitry Andric     I.eraseFromParent();
48406c3fb27SDimitry Andric     for (Value *Op : Ops)
48506c3fb27SDimitry Andric       Worklist.handleUseCountDecrement(Op);
4860b57cec5SDimitry Andric     MadeIRChange = true;
4870b57cec5SDimitry Andric     return nullptr; // Don't do anything with FI
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   OverflowResult computeOverflow(
4910b57cec5SDimitry Andric       Instruction::BinaryOps BinaryOp, bool IsSigned,
4920b57cec5SDimitry Andric       Value *LHS, Value *RHS, Instruction *CxtI) const;
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   /// Performs a few simplifications for operators which are associative
4950b57cec5SDimitry Andric   /// or commutative.
4960b57cec5SDimitry Andric   bool SimplifyAssociativeOrCommutative(BinaryOperator &I);
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   /// Tries to simplify binary operations which some other binary
4990b57cec5SDimitry Andric   /// operation distributes over.
5000b57cec5SDimitry Andric   ///
5010b57cec5SDimitry Andric   /// It does this by either by factorizing out common terms (eg "(A*B)+(A*C)"
5020b57cec5SDimitry Andric   /// -> "A*(B+C)") or expanding out if this results in simplifications (eg: "A
5030b57cec5SDimitry Andric   /// & (B | C) -> (A&B) | (A&C)" if this is a win).  Returns the simplified
5040b57cec5SDimitry Andric   /// value, or null if it didn't simplify.
505bdd1243dSDimitry Andric   Value *foldUsingDistributiveLaws(BinaryOperator &I);
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   /// Tries to simplify add operations using the definition of remainder.
5080b57cec5SDimitry Andric   ///
5090b57cec5SDimitry Andric   /// The definition of remainder is X % C = X - (X / C ) * C. The add
5100b57cec5SDimitry Andric   /// expression X % C0 + (( X / C0 ) % C1) * C0 can be simplified to
5110b57cec5SDimitry Andric   /// X % (C0 * C1)
5120b57cec5SDimitry Andric   Value *SimplifyAddWithRemainder(BinaryOperator &I);
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   // Binary Op helper for select operations where the expression can be
5150b57cec5SDimitry Andric   // efficiently reorganized.
5160b57cec5SDimitry Andric   Value *SimplifySelectsFeedingBinaryOp(BinaryOperator &I, Value *LHS,
5170b57cec5SDimitry Andric                                         Value *RHS);
5180b57cec5SDimitry Andric 
5197a6dacacSDimitry Andric   // If `I` has operand `(ctpop (not x))`, fold `I` with `(sub nuw nsw
5207a6dacacSDimitry Andric   // BitWidth(x), (ctpop x))`.
5217a6dacacSDimitry Andric   Instruction *tryFoldInstWithCtpopWithNot(Instruction *I);
5227a6dacacSDimitry Andric 
52306c3fb27SDimitry Andric   // (Binop1 (Binop2 (logic_shift X, C), C1), (logic_shift Y, C))
52406c3fb27SDimitry Andric   //    -> (logic_shift (Binop1 (Binop2 X, inv_logic_shift(C1, C)), Y), C)
52506c3fb27SDimitry Andric   // (Binop1 (Binop2 (logic_shift X, Amt), Mask), (logic_shift Y, Amt))
52606c3fb27SDimitry Andric   //    -> (BinOp (logic_shift (BinOp X, Y)), Mask)
52706c3fb27SDimitry Andric   Instruction *foldBinOpShiftWithShift(BinaryOperator &I);
52806c3fb27SDimitry Andric 
52906c3fb27SDimitry Andric   /// Tries to simplify binops of select and cast of the select condition.
53006c3fb27SDimitry Andric   ///
53106c3fb27SDimitry Andric   /// (Binop (cast C), (select C, T, F))
53206c3fb27SDimitry Andric   ///    -> (select C, C0, C1)
53306c3fb27SDimitry Andric   Instruction *foldBinOpOfSelectAndCastOfSelectCondition(BinaryOperator &I);
53406c3fb27SDimitry Andric 
5350b57cec5SDimitry Andric   /// This tries to simplify binary operations by factorizing out common terms
5360b57cec5SDimitry Andric   /// (e. g. "(A*B)+(A*C)" -> "A*(B+C)").
537bdd1243dSDimitry Andric   Value *tryFactorizationFolds(BinaryOperator &I);
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   /// Match a select chain which produces one of three values based on whether
5400b57cec5SDimitry Andric   /// the LHS is less than, equal to, or greater than RHS respectively.
5410b57cec5SDimitry Andric   /// Return true if we matched a three way compare idiom. The LHS, RHS, Less,
5420b57cec5SDimitry Andric   /// Equal and Greater values are saved in the matching process and returned to
5430b57cec5SDimitry Andric   /// the caller.
5440b57cec5SDimitry Andric   bool matchThreeWayIntCompare(SelectInst *SI, Value *&LHS, Value *&RHS,
5450b57cec5SDimitry Andric                                ConstantInt *&Less, ConstantInt *&Equal,
5460b57cec5SDimitry Andric                                ConstantInt *&Greater);
5470b57cec5SDimitry Andric 
548*0fca6ea1SDimitry Andric   /// Attempts to replace I with a simpler value based on the demanded
5490b57cec5SDimitry Andric   /// bits.
550*0fca6ea1SDimitry Andric   Value *SimplifyDemandedUseBits(Instruction *I, const APInt &DemandedMask,
551*0fca6ea1SDimitry Andric                                  KnownBits &Known, unsigned Depth,
552*0fca6ea1SDimitry Andric                                  const SimplifyQuery &Q);
553*0fca6ea1SDimitry Andric   using InstCombiner::SimplifyDemandedBits;
5540b57cec5SDimitry Andric   bool SimplifyDemandedBits(Instruction *I, unsigned Op,
5550b57cec5SDimitry Andric                             const APInt &DemandedMask, KnownBits &Known,
556*0fca6ea1SDimitry Andric                             unsigned Depth, const SimplifyQuery &Q) override;
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   /// Helper routine of SimplifyDemandedUseBits. It computes KnownZero/KnownOne
5590b57cec5SDimitry Andric   /// bits. It also tries to handle simplifications that can be done based on
5600b57cec5SDimitry Andric   /// DemandedMask, but without modifying the Instruction.
5610b57cec5SDimitry Andric   Value *SimplifyMultipleUseDemandedBits(Instruction *I,
5620b57cec5SDimitry Andric                                          const APInt &DemandedMask,
563*0fca6ea1SDimitry Andric                                          KnownBits &Known, unsigned Depth,
564*0fca6ea1SDimitry Andric                                          const SimplifyQuery &Q);
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   /// Helper routine of SimplifyDemandedUseBits. It tries to simplify demanded
5670b57cec5SDimitry Andric   /// bit for "r1 = shr x, c1; r2 = shl r1, c2" instruction sequence.
5680b57cec5SDimitry Andric   Value *simplifyShrShlDemandedBits(
5690b57cec5SDimitry Andric       Instruction *Shr, const APInt &ShrOp1, Instruction *Shl,
5700b57cec5SDimitry Andric       const APInt &ShlOp1, const APInt &DemandedMask, KnownBits &Known);
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   /// Tries to simplify operands to an integer instruction based on its
5730b57cec5SDimitry Andric   /// demanded bits.
5740b57cec5SDimitry Andric   bool SimplifyDemandedInstructionBits(Instruction &Inst);
5755f757f3fSDimitry Andric   bool SimplifyDemandedInstructionBits(Instruction &Inst, KnownBits &Known);
5760b57cec5SDimitry Andric 
577972a253aSDimitry Andric   Value *SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
578cb14a3feSDimitry Andric                                     APInt &PoisonElts, unsigned Depth = 0,
579e8d8bef9SDimitry Andric                                     bool AllowMultipleUsers = false) override;
5800b57cec5SDimitry Andric 
581*0fca6ea1SDimitry Andric   /// Attempts to replace V with a simpler value based on the demanded
582*0fca6ea1SDimitry Andric   /// floating-point classes
583*0fca6ea1SDimitry Andric   Value *SimplifyDemandedUseFPClass(Value *V, FPClassTest DemandedMask,
584*0fca6ea1SDimitry Andric                                     KnownFPClass &Known, unsigned Depth,
585*0fca6ea1SDimitry Andric                                     Instruction *CxtI);
586*0fca6ea1SDimitry Andric   bool SimplifyDemandedFPClass(Instruction *I, unsigned Op,
587*0fca6ea1SDimitry Andric                                FPClassTest DemandedMask, KnownFPClass &Known,
588*0fca6ea1SDimitry Andric                                unsigned Depth = 0);
589*0fca6ea1SDimitry Andric 
5900b57cec5SDimitry Andric   /// Canonicalize the position of binops relative to shufflevector.
5910b57cec5SDimitry Andric   Instruction *foldVectorBinop(BinaryOperator &Inst);
5925ffd83dbSDimitry Andric   Instruction *foldVectorSelect(SelectInst &Sel);
5930eae32dcSDimitry Andric   Instruction *foldSelectShuffle(ShuffleVectorInst &Shuf);
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   /// Given a binary operator, cast instruction, or select which has a PHI node
5960b57cec5SDimitry Andric   /// as operand #0, see if we can fold the instruction into the PHI (which is
5970b57cec5SDimitry Andric   /// only possible if all operands to the PHI are constants).
5980b57cec5SDimitry Andric   Instruction *foldOpIntoPhi(Instruction &I, PHINode *PN);
5990b57cec5SDimitry Andric 
60004eeddc0SDimitry Andric   /// For a binary operator with 2 phi operands, try to hoist the binary
60104eeddc0SDimitry Andric   /// operation before the phi. This can result in fewer instructions in
60204eeddc0SDimitry Andric   /// patterns where at least one set of phi operands simplifies.
60304eeddc0SDimitry Andric   /// Example:
60404eeddc0SDimitry Andric   /// BB3: binop (phi [X, BB1], [C1, BB2]), (phi [Y, BB1], [C2, BB2])
60504eeddc0SDimitry Andric   /// -->
60604eeddc0SDimitry Andric   /// BB1: BO = binop X, Y
60704eeddc0SDimitry Andric   /// BB3: phi [BO, BB1], [(binop C1, C2), BB2]
60804eeddc0SDimitry Andric   Instruction *foldBinopWithPhiOperands(BinaryOperator &BO);
60904eeddc0SDimitry Andric 
6100b57cec5SDimitry Andric   /// Given an instruction with a select as one operand and a constant as the
6110b57cec5SDimitry Andric   /// other operand, try to fold the binary operator into the select arguments.
6120b57cec5SDimitry Andric   /// This also works for Cast instructions, which obviously do not have a
6130b57cec5SDimitry Andric   /// second operand.
61481ad6265SDimitry Andric   Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
61581ad6265SDimitry Andric                                 bool FoldWithMultiUse = false);
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   /// This is a convenience wrapper function for the above two functions.
6180b57cec5SDimitry Andric   Instruction *foldBinOpIntoSelectOrPhi(BinaryOperator &I);
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   Instruction *foldAddWithConstant(BinaryOperator &Add);
6210b57cec5SDimitry Andric 
6225f757f3fSDimitry Andric   Instruction *foldSquareSumInt(BinaryOperator &I);
6235f757f3fSDimitry Andric   Instruction *foldSquareSumFP(BinaryOperator &I);
6245f757f3fSDimitry Andric 
6250b57cec5SDimitry Andric   /// Try to rotate an operation below a PHI node, using PHI nodes for
6260b57cec5SDimitry Andric   /// its operands.
627e8d8bef9SDimitry Andric   Instruction *foldPHIArgOpIntoPHI(PHINode &PN);
628e8d8bef9SDimitry Andric   Instruction *foldPHIArgBinOpIntoPHI(PHINode &PN);
629e8d8bef9SDimitry Andric   Instruction *foldPHIArgInsertValueInstructionIntoPHI(PHINode &PN);
630e8d8bef9SDimitry Andric   Instruction *foldPHIArgExtractValueInstructionIntoPHI(PHINode &PN);
631e8d8bef9SDimitry Andric   Instruction *foldPHIArgGEPIntoPHI(PHINode &PN);
632e8d8bef9SDimitry Andric   Instruction *foldPHIArgLoadIntoPHI(PHINode &PN);
633e8d8bef9SDimitry Andric   Instruction *foldPHIArgZextsIntoPHI(PHINode &PN);
634349cc55cSDimitry Andric   Instruction *foldPHIArgIntToPtrToPHI(PHINode &PN);
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   /// If an integer typed PHI has only one use which is an IntToPtr operation,
6370b57cec5SDimitry Andric   /// replace the PHI with an existing pointer typed PHI if it exists. Otherwise
6380b57cec5SDimitry Andric   /// insert a new pointer typed PHI and replace the original one.
639bdd1243dSDimitry Andric   bool foldIntegerTypedPHI(PHINode &PN);
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   /// Helper function for FoldPHIArgXIntoPHI() to set debug location for the
6420b57cec5SDimitry Andric   /// folded operation.
6430b57cec5SDimitry Andric   void PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN);
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   Instruction *foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
6460b57cec5SDimitry Andric                            ICmpInst::Predicate Cond, Instruction &I);
64781ad6265SDimitry Andric   Instruction *foldSelectICmp(ICmpInst::Predicate Pred, SelectInst *SI,
64881ad6265SDimitry Andric                               Value *RHS, const ICmpInst &I);
64906c3fb27SDimitry Andric   bool foldAllocaCmp(AllocaInst *Alloca);
65081ad6265SDimitry Andric   Instruction *foldCmpLoadFromIndexedGlobal(LoadInst *LI,
65181ad6265SDimitry Andric                                             GetElementPtrInst *GEP,
6520b57cec5SDimitry Andric                                             GlobalVariable *GV, CmpInst &ICI,
6530b57cec5SDimitry Andric                                             ConstantInt *AndCst = nullptr);
6540b57cec5SDimitry Andric   Instruction *foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI,
6550b57cec5SDimitry Andric                                     Constant *RHSC);
6560b57cec5SDimitry Andric   Instruction *foldICmpAddOpConst(Value *X, const APInt &C,
6570b57cec5SDimitry Andric                                   ICmpInst::Predicate Pred);
65881ad6265SDimitry Andric   Instruction *foldICmpWithCastOp(ICmpInst &ICmp);
65981ad6265SDimitry Andric   Instruction *foldICmpWithZextOrSext(ICmpInst &ICmp);
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   Instruction *foldICmpUsingKnownBits(ICmpInst &Cmp);
6620b57cec5SDimitry Andric   Instruction *foldICmpWithDominatingICmp(ICmpInst &Cmp);
6630b57cec5SDimitry Andric   Instruction *foldICmpWithConstant(ICmpInst &Cmp);
66406c3fb27SDimitry Andric   Instruction *foldICmpUsingBoolRange(ICmpInst &I);
6650b57cec5SDimitry Andric   Instruction *foldICmpInstWithConstant(ICmpInst &Cmp);
6660b57cec5SDimitry Andric   Instruction *foldICmpInstWithConstantNotInt(ICmpInst &Cmp);
667*0fca6ea1SDimitry Andric   Instruction *foldICmpInstWithConstantAllowPoison(ICmpInst &Cmp,
66881ad6265SDimitry Andric                                                    const APInt &C);
6698bcb0991SDimitry Andric   Instruction *foldICmpBinOp(ICmpInst &Cmp, const SimplifyQuery &SQ);
670647cbc5dSDimitry Andric   Instruction *foldICmpWithMinMax(Instruction &I, MinMaxIntrinsic *MinMax,
6715f757f3fSDimitry Andric                                   Value *Z, ICmpInst::Predicate Pred);
6720b57cec5SDimitry Andric   Instruction *foldICmpEquality(ICmpInst &Cmp);
6738bcb0991SDimitry Andric   Instruction *foldIRemByPowerOfTwoToBitTest(ICmpInst &I);
6748bcb0991SDimitry Andric   Instruction *foldSignBitTest(ICmpInst &I);
6750b57cec5SDimitry Andric   Instruction *foldICmpWithZero(ICmpInst &Cmp);
6760b57cec5SDimitry Andric 
677349cc55cSDimitry Andric   Value *foldMultiplicationOverflowCheck(ICmpInst &Cmp);
6788bcb0991SDimitry Andric 
67981ad6265SDimitry Andric   Instruction *foldICmpBinOpWithConstant(ICmpInst &Cmp, BinaryOperator *BO,
68081ad6265SDimitry Andric                                          const APInt &C);
6810b57cec5SDimitry Andric   Instruction *foldICmpSelectConstant(ICmpInst &Cmp, SelectInst *Select,
6820b57cec5SDimitry Andric                                       ConstantInt *C);
6830b57cec5SDimitry Andric   Instruction *foldICmpTruncConstant(ICmpInst &Cmp, TruncInst *Trunc,
6840b57cec5SDimitry Andric                                      const APInt &C);
6855f757f3fSDimitry Andric   Instruction *foldICmpTruncWithTruncOrExt(ICmpInst &Cmp,
6865f757f3fSDimitry Andric                                            const SimplifyQuery &Q);
6870b57cec5SDimitry Andric   Instruction *foldICmpAndConstant(ICmpInst &Cmp, BinaryOperator *And,
6880b57cec5SDimitry Andric                                    const APInt &C);
6890b57cec5SDimitry Andric   Instruction *foldICmpXorConstant(ICmpInst &Cmp, BinaryOperator *Xor,
6900b57cec5SDimitry Andric                                    const APInt &C);
6910b57cec5SDimitry Andric   Instruction *foldICmpOrConstant(ICmpInst &Cmp, BinaryOperator *Or,
6920b57cec5SDimitry Andric                                   const APInt &C);
6930b57cec5SDimitry Andric   Instruction *foldICmpMulConstant(ICmpInst &Cmp, BinaryOperator *Mul,
6940b57cec5SDimitry Andric                                    const APInt &C);
6950b57cec5SDimitry Andric   Instruction *foldICmpShlConstant(ICmpInst &Cmp, BinaryOperator *Shl,
6960b57cec5SDimitry Andric                                    const APInt &C);
6970b57cec5SDimitry Andric   Instruction *foldICmpShrConstant(ICmpInst &Cmp, BinaryOperator *Shr,
6980b57cec5SDimitry Andric                                    const APInt &C);
6998bcb0991SDimitry Andric   Instruction *foldICmpSRemConstant(ICmpInst &Cmp, BinaryOperator *UDiv,
7008bcb0991SDimitry Andric                                     const APInt &C);
7010b57cec5SDimitry Andric   Instruction *foldICmpUDivConstant(ICmpInst &Cmp, BinaryOperator *UDiv,
7020b57cec5SDimitry Andric                                     const APInt &C);
7030b57cec5SDimitry Andric   Instruction *foldICmpDivConstant(ICmpInst &Cmp, BinaryOperator *Div,
7040b57cec5SDimitry Andric                                    const APInt &C);
7050b57cec5SDimitry Andric   Instruction *foldICmpSubConstant(ICmpInst &Cmp, BinaryOperator *Sub,
7060b57cec5SDimitry Andric                                    const APInt &C);
7070b57cec5SDimitry Andric   Instruction *foldICmpAddConstant(ICmpInst &Cmp, BinaryOperator *Add,
7080b57cec5SDimitry Andric                                    const APInt &C);
7090b57cec5SDimitry Andric   Instruction *foldICmpAndConstConst(ICmpInst &Cmp, BinaryOperator *And,
7100b57cec5SDimitry Andric                                      const APInt &C1);
7110b57cec5SDimitry Andric   Instruction *foldICmpAndShift(ICmpInst &Cmp, BinaryOperator *And,
7120b57cec5SDimitry Andric                                 const APInt &C1, const APInt &C2);
713bdd1243dSDimitry Andric   Instruction *foldICmpXorShiftConst(ICmpInst &Cmp, BinaryOperator *Xor,
714bdd1243dSDimitry Andric                                      const APInt &C);
7150b57cec5SDimitry Andric   Instruction *foldICmpShrConstConst(ICmpInst &I, Value *ShAmt, const APInt &C1,
7160b57cec5SDimitry Andric                                      const APInt &C2);
7170b57cec5SDimitry Andric   Instruction *foldICmpShlConstConst(ICmpInst &I, Value *ShAmt, const APInt &C1,
7180b57cec5SDimitry Andric                                      const APInt &C2);
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric   Instruction *foldICmpBinOpEqualityWithConstant(ICmpInst &Cmp,
7210b57cec5SDimitry Andric                                                  BinaryOperator *BO,
7220b57cec5SDimitry Andric                                                  const APInt &C);
7230b57cec5SDimitry Andric   Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI, IntrinsicInst *II,
7240b57cec5SDimitry Andric                                              const APInt &C);
7250b57cec5SDimitry Andric   Instruction *foldICmpEqIntrinsicWithConstant(ICmpInst &ICI, IntrinsicInst *II,
7260b57cec5SDimitry Andric                                                const APInt &C);
727349cc55cSDimitry Andric   Instruction *foldICmpBitCast(ICmpInst &Cmp);
72806c3fb27SDimitry Andric   Instruction *foldICmpWithTrunc(ICmpInst &Cmp);
729647cbc5dSDimitry Andric   Instruction *foldICmpCommutative(ICmpInst::Predicate Pred, Value *Op0,
730647cbc5dSDimitry Andric                                    Value *Op1, ICmpInst &CxtI);
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   // Helpers of visitSelectInst().
733bdd1243dSDimitry Andric   Instruction *foldSelectOfBools(SelectInst &SI);
7340b57cec5SDimitry Andric   Instruction *foldSelectExtConst(SelectInst &Sel);
7350b57cec5SDimitry Andric   Instruction *foldSelectOpOp(SelectInst &SI, Instruction *TI, Instruction *FI);
7360b57cec5SDimitry Andric   Instruction *foldSelectIntoOp(SelectInst &SI, Value *, Value *);
7370b57cec5SDimitry Andric   Instruction *foldSPFofSPF(Instruction *Inner, SelectPatternFlavor SPF1,
7380b57cec5SDimitry Andric                             Value *A, Value *B, Instruction &Outer,
7390b57cec5SDimitry Andric                             SelectPatternFlavor SPF2, Value *C);
7400b57cec5SDimitry Andric   Instruction *foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI);
741e8d8bef9SDimitry Andric   Instruction *foldSelectValueEquivalence(SelectInst &SI, ICmpInst &ICI);
74206c3fb27SDimitry Andric   bool replaceInInstruction(Value *V, Value *Old, Value *New,
74306c3fb27SDimitry Andric                             unsigned Depth = 0);
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   Value *insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi,
7460b57cec5SDimitry Andric                          bool isSigned, bool Inside);
7470b57cec5SDimitry Andric   bool mergeStoreIntoSuccessor(StoreInst &SI);
7480b57cec5SDimitry Andric 
749fe6060f1SDimitry Andric   /// Given an initial instruction, check to see if it is the root of a
750e8d8bef9SDimitry Andric   /// bswap/bitreverse idiom. If so, return the equivalent bswap/bitreverse
751e8d8bef9SDimitry Andric   /// intrinsic.
752fe6060f1SDimitry Andric   Instruction *matchBSwapOrBitReverse(Instruction &I, bool MatchBSwaps,
753e8d8bef9SDimitry Andric                                       bool MatchBitReversals);
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   Instruction *SimplifyAnyMemTransfer(AnyMemTransferInst *MI);
7560b57cec5SDimitry Andric   Instruction *SimplifyAnyMemSet(AnyMemSetInst *MI);
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric   Value *EvaluateInDifferentType(Value *V, Type *Ty, bool isSigned);
7590b57cec5SDimitry Andric 
76006c3fb27SDimitry Andric   bool tryToSinkInstruction(Instruction *I, BasicBlock *DestBlock);
761*0fca6ea1SDimitry Andric   void tryToSinkInstructionDbgValues(
762*0fca6ea1SDimitry Andric       Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
763*0fca6ea1SDimitry Andric       BasicBlock *DestBlock, SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers);
764*0fca6ea1SDimitry Andric   void tryToSinkInstructionDbgVariableRecords(
765*0fca6ea1SDimitry Andric       Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock,
766*0fca6ea1SDimitry Andric       BasicBlock *DestBlock, SmallVectorImpl<DbgVariableRecord *> &DPUsers);
76706c3fb27SDimitry Andric 
76806c3fb27SDimitry Andric   bool removeInstructionsBeforeUnreachable(Instruction &I);
7695f757f3fSDimitry Andric   void addDeadEdge(BasicBlock *From, BasicBlock *To,
7705f757f3fSDimitry Andric                    SmallVectorImpl<BasicBlock *> &Worklist);
7715f757f3fSDimitry Andric   void handleUnreachableFrom(Instruction *I,
7725f757f3fSDimitry Andric                              SmallVectorImpl<BasicBlock *> &Worklist);
7735f757f3fSDimitry Andric   void handlePotentiallyDeadBlocks(SmallVectorImpl<BasicBlock *> &Worklist);
7745f757f3fSDimitry Andric   void handlePotentiallyDeadSuccessors(BasicBlock *BB, BasicBlock *LiveSucc);
77506c3fb27SDimitry Andric   void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser = nullptr);
7760b57cec5SDimitry Andric };
7770b57cec5SDimitry Andric 
7785ffd83dbSDimitry Andric class Negator final {
7795ffd83dbSDimitry Andric   /// Top-to-bottom, def-to-use negated instruction tree we produced.
7805ffd83dbSDimitry Andric   SmallVector<Instruction *, NegatorMaxNodesSSO> NewInstructions;
7815ffd83dbSDimitry Andric 
7825ffd83dbSDimitry Andric   using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>;
7835ffd83dbSDimitry Andric   BuilderTy Builder;
7845ffd83dbSDimitry Andric 
7855ffd83dbSDimitry Andric   const bool IsTrulyNegation;
7865ffd83dbSDimitry Andric 
7875ffd83dbSDimitry Andric   SmallDenseMap<Value *, Value *> NegationsCache;
7885ffd83dbSDimitry Andric 
7895f757f3fSDimitry Andric   Negator(LLVMContext &C, const DataLayout &DL, bool IsTrulyNegation);
7905ffd83dbSDimitry Andric 
7915ffd83dbSDimitry Andric #if LLVM_ENABLE_STATS
7925ffd83dbSDimitry Andric   unsigned NumValuesVisitedInThisNegator = 0;
7935ffd83dbSDimitry Andric   ~Negator();
7945ffd83dbSDimitry Andric #endif
7955ffd83dbSDimitry Andric 
7965ffd83dbSDimitry Andric   using Result = std::pair<ArrayRef<Instruction *> /*NewInstructions*/,
7975ffd83dbSDimitry Andric                            Value * /*NegatedRoot*/>;
7985ffd83dbSDimitry Andric 
799e8d8bef9SDimitry Andric   std::array<Value *, 2> getSortedOperandsOfBinOp(Instruction *I);
800e8d8bef9SDimitry Andric 
8015f757f3fSDimitry Andric   [[nodiscard]] Value *visitImpl(Value *V, bool IsNSW, unsigned Depth);
8025ffd83dbSDimitry Andric 
8035f757f3fSDimitry Andric   [[nodiscard]] Value *negate(Value *V, bool IsNSW, unsigned Depth);
8045ffd83dbSDimitry Andric 
8055ffd83dbSDimitry Andric   /// Recurse depth-first and attempt to sink the negation.
8065ffd83dbSDimitry Andric   /// FIXME: use worklist?
8075f757f3fSDimitry Andric   [[nodiscard]] std::optional<Result> run(Value *Root, bool IsNSW);
8085ffd83dbSDimitry Andric 
8095ffd83dbSDimitry Andric   Negator(const Negator &) = delete;
8105ffd83dbSDimitry Andric   Negator(Negator &&) = delete;
8115ffd83dbSDimitry Andric   Negator &operator=(const Negator &) = delete;
8125ffd83dbSDimitry Andric   Negator &operator=(Negator &&) = delete;
8135ffd83dbSDimitry Andric 
8145ffd83dbSDimitry Andric public:
8155ffd83dbSDimitry Andric   /// Attempt to negate \p Root. Retuns nullptr if negation can't be performed,
8165ffd83dbSDimitry Andric   /// otherwise returns negated value.
8175f757f3fSDimitry Andric   [[nodiscard]] static Value *Negate(bool LHSIsZero, bool IsNSW, Value *Root,
818e8d8bef9SDimitry Andric                                      InstCombinerImpl &IC);
8195ffd83dbSDimitry Andric };
8205ffd83dbSDimitry Andric 
8210b57cec5SDimitry Andric } // end namespace llvm
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric #undef DEBUG_TYPE
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric #endif // LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEINTERNAL_H
826