Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:23

0001 //===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===--------------------------------------------------------------------===//
0008 /// \file
0009 /// This contains common combine transformations that may be used in a combine
0010 /// pass,or by the target elsewhere.
0011 /// Targets can pick individual opcode transformations from the helper or use
0012 /// tryCombine which invokes all transformations. All of the transformations
0013 /// return true if the MachineInstruction changed and false otherwise.
0014 ///
0015 //===--------------------------------------------------------------------===//
0016 
0017 #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H
0018 #define LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H
0019 
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/SmallVector.h"
0022 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
0023 #include "llvm/CodeGen/GlobalISel/Utils.h"
0024 #include "llvm/CodeGen/Register.h"
0025 #include "llvm/CodeGenTypes/LowLevelType.h"
0026 #include "llvm/IR/InstrTypes.h"
0027 #include <functional>
0028 
0029 namespace llvm {
0030 
0031 class GISelChangeObserver;
0032 class APInt;
0033 class ConstantFP;
0034 class GPtrAdd;
0035 class GZExtLoad;
0036 class MachineIRBuilder;
0037 class MachineInstrBuilder;
0038 class MachineRegisterInfo;
0039 class MachineInstr;
0040 class MachineOperand;
0041 class GISelKnownBits;
0042 class MachineDominatorTree;
0043 class LegalizerInfo;
0044 struct LegalityQuery;
0045 class RegisterBank;
0046 class RegisterBankInfo;
0047 class TargetLowering;
0048 class TargetRegisterInfo;
0049 
0050 struct PreferredTuple {
0051   LLT Ty;                // The result type of the extend.
0052   unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT
0053   MachineInstr *MI;
0054 };
0055 
0056 struct IndexedLoadStoreMatchInfo {
0057   Register Addr;
0058   Register Base;
0059   Register Offset;
0060   bool RematOffset = false; // True if Offset is a constant that needs to be
0061                             // rematerialized before the new load/store.
0062   bool IsPre = false;
0063 };
0064 
0065 struct PtrAddChain {
0066   int64_t Imm;
0067   Register Base;
0068   const RegisterBank *Bank;
0069 };
0070 
0071 struct RegisterImmPair {
0072   Register Reg;
0073   int64_t Imm;
0074 };
0075 
0076 struct ShiftOfShiftedLogic {
0077   MachineInstr *Logic;
0078   MachineInstr *Shift2;
0079   Register LogicNonShiftReg;
0080   uint64_t ValSum;
0081 };
0082 
0083 using BuildFnTy = std::function<void(MachineIRBuilder &)>;
0084 
0085 using OperandBuildSteps =
0086     SmallVector<std::function<void(MachineInstrBuilder &)>, 4>;
0087 struct InstructionBuildSteps {
0088   unsigned Opcode = 0;          /// The opcode for the produced instruction.
0089   OperandBuildSteps OperandFns; /// Operands to be added to the instruction.
0090   InstructionBuildSteps() = default;
0091   InstructionBuildSteps(unsigned Opcode, const OperandBuildSteps &OperandFns)
0092       : Opcode(Opcode), OperandFns(OperandFns) {}
0093 };
0094 
0095 struct InstructionStepsMatchInfo {
0096   /// Describes instructions to be built during a combine.
0097   SmallVector<InstructionBuildSteps, 2> InstrsToBuild;
0098   InstructionStepsMatchInfo() = default;
0099   InstructionStepsMatchInfo(
0100       std::initializer_list<InstructionBuildSteps> InstrsToBuild)
0101       : InstrsToBuild(InstrsToBuild) {}
0102 };
0103 
0104 class CombinerHelper {
0105 protected:
0106   MachineIRBuilder &Builder;
0107   MachineRegisterInfo &MRI;
0108   GISelChangeObserver &Observer;
0109   GISelKnownBits *KB;
0110   MachineDominatorTree *MDT;
0111   bool IsPreLegalize;
0112   const LegalizerInfo *LI;
0113   const RegisterBankInfo *RBI;
0114   const TargetRegisterInfo *TRI;
0115 
0116 public:
0117   CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B,
0118                  bool IsPreLegalize,
0119                  GISelKnownBits *KB = nullptr,
0120                  MachineDominatorTree *MDT = nullptr,
0121                  const LegalizerInfo *LI = nullptr);
0122 
0123   GISelKnownBits *getKnownBits() const {
0124     return KB;
0125   }
0126 
0127   MachineIRBuilder &getBuilder() const {
0128     return Builder;
0129   }
0130 
0131   const TargetLowering &getTargetLowering() const;
0132 
0133   const MachineFunction &getMachineFunction() const;
0134 
0135   const DataLayout &getDataLayout() const;
0136 
0137   LLVMContext &getContext() const;
0138 
0139   /// \returns true if the combiner is running pre-legalization.
0140   bool isPreLegalize() const;
0141 
0142   /// \returns true if \p Query is legal on the target.
0143   bool isLegal(const LegalityQuery &Query) const;
0144 
0145   /// \return true if the combine is running prior to legalization, or if \p
0146   /// Query is legal on the target.
0147   bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const;
0148 
0149   /// \return true if the combine is running prior to legalization, or if \p Ty
0150   /// is a legal integer constant type on the target.
0151   bool isConstantLegalOrBeforeLegalizer(const LLT Ty) const;
0152 
0153   /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes
0154   void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const;
0155 
0156   /// Replace a single register operand with a new register and inform the
0157   /// observer of the changes.
0158   void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp,
0159                         Register ToReg) const;
0160 
0161   /// Replace the opcode in instruction with a new opcode and inform the
0162   /// observer of the changes.
0163   void replaceOpcodeWith(MachineInstr &FromMI, unsigned ToOpcode) const;
0164 
0165   /// Get the register bank of \p Reg.
0166   /// If Reg has not been assigned a register, a register class,
0167   /// or a register bank, then this returns nullptr.
0168   ///
0169   /// \pre Reg.isValid()
0170   const RegisterBank *getRegBank(Register Reg) const;
0171 
0172   /// Set the register bank of \p Reg.
0173   /// Does nothing if the RegBank is null.
0174   /// This is the counterpart to getRegBank.
0175   void setRegBank(Register Reg, const RegisterBank *RegBank) const;
0176 
0177   /// If \p MI is COPY, try to combine it.
0178   /// Returns true if MI changed.
0179   bool tryCombineCopy(MachineInstr &MI) const;
0180   bool matchCombineCopy(MachineInstr &MI) const;
0181   void applyCombineCopy(MachineInstr &MI) const;
0182 
0183   /// Returns true if \p DefMI precedes \p UseMI or they are the same
0184   /// instruction. Both must be in the same basic block.
0185   bool isPredecessor(const MachineInstr &DefMI,
0186                      const MachineInstr &UseMI) const;
0187 
0188   /// Returns true if \p DefMI dominates \p UseMI. By definition an
0189   /// instruction dominates itself.
0190   ///
0191   /// If we haven't been provided with a MachineDominatorTree during
0192   /// construction, this function returns a conservative result that tracks just
0193   /// a single basic block.
0194   bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI) const;
0195 
0196   /// If \p MI is extend that consumes the result of a load, try to combine it.
0197   /// Returns true if MI changed.
0198   bool tryCombineExtendingLoads(MachineInstr &MI) const;
0199   bool matchCombineExtendingLoads(MachineInstr &MI,
0200                                   PreferredTuple &MatchInfo) const;
0201   void applyCombineExtendingLoads(MachineInstr &MI,
0202                                   PreferredTuple &MatchInfo) const;
0203 
0204   /// Match (and (load x), mask) -> zextload x
0205   bool matchCombineLoadWithAndMask(MachineInstr &MI,
0206                                    BuildFnTy &MatchInfo) const;
0207 
0208   /// Combine a G_EXTRACT_VECTOR_ELT of a load into a narrowed
0209   /// load.
0210   bool matchCombineExtractedVectorLoad(MachineInstr &MI,
0211                                        BuildFnTy &MatchInfo) const;
0212 
0213   bool matchCombineIndexedLoadStore(MachineInstr &MI,
0214                                     IndexedLoadStoreMatchInfo &MatchInfo) const;
0215   void applyCombineIndexedLoadStore(MachineInstr &MI,
0216                                     IndexedLoadStoreMatchInfo &MatchInfo) const;
0217 
0218   bool matchSextTruncSextLoad(MachineInstr &MI) const;
0219   void applySextTruncSextLoad(MachineInstr &MI) const;
0220 
0221   /// Match sext_inreg(load p), imm -> sextload p
0222   bool matchSextInRegOfLoad(MachineInstr &MI,
0223                             std::tuple<Register, unsigned> &MatchInfo) const;
0224   void applySextInRegOfLoad(MachineInstr &MI,
0225                             std::tuple<Register, unsigned> &MatchInfo) const;
0226 
0227   /// Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM
0228   /// when their source operands are identical.
0229   bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const;
0230   void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const;
0231 
0232   /// If a brcond's true block is not the fallthrough, make it so by inverting
0233   /// the condition and swapping operands.
0234   bool matchOptBrCondByInvertingCond(MachineInstr &MI,
0235                                      MachineInstr *&BrCond) const;
0236   void applyOptBrCondByInvertingCond(MachineInstr &MI,
0237                                      MachineInstr *&BrCond) const;
0238 
0239   /// If \p MI is G_CONCAT_VECTORS, try to combine it.
0240   /// Returns true if MI changed.
0241   /// Right now, we support:
0242   /// - concat_vector(undef, undef) => undef
0243   /// - concat_vector(build_vector(A, B), build_vector(C, D)) =>
0244   ///   build_vector(A, B, C, D)
0245   /// ==========================================================
0246   /// Check if the G_CONCAT_VECTORS \p MI is undef or if it
0247   /// can be flattened into a build_vector.
0248   /// In the first case \p Ops will be empty
0249   /// In the second case \p Ops will contain the operands
0250   /// needed to produce the flattened build_vector.
0251   ///
0252   /// \pre MI.getOpcode() == G_CONCAT_VECTORS.
0253   bool matchCombineConcatVectors(MachineInstr &MI,
0254                                  SmallVector<Register> &Ops) const;
0255   /// Replace \p MI with a flattened build_vector with \p Ops
0256   /// or an implicit_def if \p Ops is empty.
0257   void applyCombineConcatVectors(MachineInstr &MI,
0258                                  SmallVector<Register> &Ops) const;
0259 
0260   bool matchCombineShuffleConcat(MachineInstr &MI,
0261                                  SmallVector<Register> &Ops) const;
0262   /// Replace \p MI with a flattened build_vector with \p Ops
0263   /// or an implicit_def if \p Ops is empty.
0264   void applyCombineShuffleConcat(MachineInstr &MI,
0265                                  SmallVector<Register> &Ops) const;
0266 
0267   /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
0268   /// Returns true if MI changed.
0269   ///
0270   /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
0271   bool tryCombineShuffleVector(MachineInstr &MI) const;
0272   /// Check if the G_SHUFFLE_VECTOR \p MI can be replaced by a
0273   /// concat_vectors.
0274   /// \p Ops will contain the operands needed to produce the flattened
0275   /// concat_vectors.
0276   ///
0277   /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
0278   bool matchCombineShuffleVector(MachineInstr &MI,
0279                                  SmallVectorImpl<Register> &Ops) const;
0280   /// Replace \p MI with a concat_vectors with \p Ops.
0281   void applyCombineShuffleVector(MachineInstr &MI,
0282                                  const ArrayRef<Register> Ops) const;
0283   bool matchShuffleToExtract(MachineInstr &MI) const;
0284   void applyShuffleToExtract(MachineInstr &MI) const;
0285 
0286   /// Optimize memcpy intrinsics et al, e.g. constant len calls.
0287   /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline.
0288   ///
0289   /// For example (pre-indexed):
0290   ///
0291   ///     $addr = G_PTR_ADD $base, $offset
0292   ///     [...]
0293   ///     $val = G_LOAD $addr
0294   ///     [...]
0295   ///     $whatever = COPY $addr
0296   ///
0297   /// -->
0298   ///
0299   ///     $val, $addr = G_INDEXED_LOAD $base, $offset, 1 (IsPre)
0300   ///     [...]
0301   ///     $whatever = COPY $addr
0302   ///
0303   /// or (post-indexed):
0304   ///
0305   ///     G_STORE $val, $base
0306   ///     [...]
0307   ///     $addr = G_PTR_ADD $base, $offset
0308   ///     [...]
0309   ///     $whatever = COPY $addr
0310   ///
0311   /// -->
0312   ///
0313   ///     $addr = G_INDEXED_STORE $val, $base, $offset
0314   ///     [...]
0315   ///     $whatever = COPY $addr
0316   bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0) const;
0317 
0318   bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const;
0319   void applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const;
0320 
0321   /// Fold (shift (shift base, x), y) -> (shift base (x+y))
0322   bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const;
0323   void applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const;
0324 
0325   /// If we have a shift-by-constant of a bitwise logic op that itself has a
0326   /// shift-by-constant operand with identical opcode, we may be able to convert
0327   /// that into 2 independent shifts followed by the logic op.
0328   bool matchShiftOfShiftedLogic(MachineInstr &MI,
0329                                 ShiftOfShiftedLogic &MatchInfo) const;
0330   void applyShiftOfShiftedLogic(MachineInstr &MI,
0331                                 ShiftOfShiftedLogic &MatchInfo) const;
0332 
0333   bool matchCommuteShift(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0334 
0335   /// Transform a multiply by a power-of-2 value to a left shift.
0336   bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const;
0337   void applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const;
0338 
0339   // Transform a G_SUB with constant on the RHS to G_ADD.
0340   bool matchCombineSubToAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0341 
0342   // Transform a G_SHL with an extended source into a narrower shift if
0343   // possible.
0344   bool matchCombineShlOfExtend(MachineInstr &MI,
0345                                RegisterImmPair &MatchData) const;
0346   void applyCombineShlOfExtend(MachineInstr &MI,
0347                                const RegisterImmPair &MatchData) const;
0348 
0349   /// Fold away a merge of an unmerge of the corresponding values.
0350   bool matchCombineMergeUnmerge(MachineInstr &MI, Register &MatchInfo) const;
0351 
0352   /// Reduce a shift by a constant to an unmerge and a shift on a half sized
0353   /// type. This will not produce a shift smaller than \p TargetShiftSize.
0354   bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize,
0355                                   unsigned &ShiftVal) const;
0356   void applyCombineShiftToUnmerge(MachineInstr &MI,
0357                                   const unsigned &ShiftVal) const;
0358   bool tryCombineShiftToUnmerge(MachineInstr &MI,
0359                                 unsigned TargetShiftAmount) const;
0360 
0361   /// Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z.
0362   bool matchCombineUnmergeMergeToPlainValues(
0363       MachineInstr &MI, SmallVectorImpl<Register> &Operands) const;
0364   void applyCombineUnmergeMergeToPlainValues(
0365       MachineInstr &MI, SmallVectorImpl<Register> &Operands) const;
0366 
0367   /// Transform G_UNMERGE Constant -> Constant1, Constant2, ...
0368   bool matchCombineUnmergeConstant(MachineInstr &MI,
0369                                    SmallVectorImpl<APInt> &Csts) const;
0370   void applyCombineUnmergeConstant(MachineInstr &MI,
0371                                    SmallVectorImpl<APInt> &Csts) const;
0372 
0373   /// Transform G_UNMERGE G_IMPLICIT_DEF -> G_IMPLICIT_DEF, G_IMPLICIT_DEF, ...
0374   bool matchCombineUnmergeUndef(
0375       MachineInstr &MI,
0376       std::function<void(MachineIRBuilder &)> &MatchInfo) const;
0377 
0378   /// Transform X, Y<dead> = G_UNMERGE Z -> X = G_TRUNC Z.
0379   bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const;
0380   void applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const;
0381 
0382   /// Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0
0383   bool matchCombineUnmergeZExtToZExt(MachineInstr &MI) const;
0384   void applyCombineUnmergeZExtToZExt(MachineInstr &MI) const;
0385 
0386   /// Transform fp_instr(cst) to constant result of the fp operation.
0387   void applyCombineConstantFoldFpUnary(MachineInstr &MI,
0388                                        const ConstantFP *Cst) const;
0389 
0390   /// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space.
0391   bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg) const;
0392   void applyCombineI2PToP2I(MachineInstr &MI, Register &Reg) const;
0393 
0394   /// Transform PtrToInt(IntToPtr(x)) to x.
0395   void applyCombineP2IToI2P(MachineInstr &MI, Register &Reg) const;
0396 
0397   /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y)
0398   /// Transform G_ADD y, (G_PTRTOINT x) -> G_PTRTOINT (G_PTR_ADD x, y)
0399   bool
0400   matchCombineAddP2IToPtrAdd(MachineInstr &MI,
0401                              std::pair<Register, bool> &PtrRegAndCommute) const;
0402   void
0403   applyCombineAddP2IToPtrAdd(MachineInstr &MI,
0404                              std::pair<Register, bool> &PtrRegAndCommute) const;
0405 
0406   // Transform G_PTR_ADD (G_PTRTOINT C1), C2 -> C1 + C2
0407   bool matchCombineConstPtrAddToI2P(MachineInstr &MI, APInt &NewCst) const;
0408   void applyCombineConstPtrAddToI2P(MachineInstr &MI, APInt &NewCst) const;
0409 
0410   /// Transform anyext(trunc(x)) to x.
0411   bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg) const;
0412 
0413   /// Transform zext(trunc(x)) to x.
0414   bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg) const;
0415 
0416   /// Transform trunc (shl x, K) to shl (trunc x), K
0417   ///    if K < VT.getScalarSizeInBits().
0418   ///
0419   /// Transforms trunc ([al]shr x, K) to (trunc ([al]shr (MidVT (trunc x)), K))
0420   ///    if K <= (MidVT.getScalarSizeInBits() - VT.getScalarSizeInBits())
0421   /// MidVT is obtained by finding a legal type between the trunc's src and dst
0422   /// types.
0423   bool
0424   matchCombineTruncOfShift(MachineInstr &MI,
0425                            std::pair<MachineInstr *, LLT> &MatchInfo) const;
0426   void
0427   applyCombineTruncOfShift(MachineInstr &MI,
0428                            std::pair<MachineInstr *, LLT> &MatchInfo) const;
0429 
0430   /// Return true if any explicit use operand on \p MI is defined by a
0431   /// G_IMPLICIT_DEF.
0432   bool matchAnyExplicitUseIsUndef(MachineInstr &MI) const;
0433 
0434   /// Return true if all register explicit use operands on \p MI are defined by
0435   /// a G_IMPLICIT_DEF.
0436   bool matchAllExplicitUsesAreUndef(MachineInstr &MI) const;
0437 
0438   /// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask.
0439   bool matchUndefShuffleVectorMask(MachineInstr &MI) const;
0440 
0441   /// Return true if a G_STORE instruction \p MI is storing an undef value.
0442   bool matchUndefStore(MachineInstr &MI) const;
0443 
0444   /// Return true if a G_SELECT instruction \p MI has an undef comparison.
0445   bool matchUndefSelectCmp(MachineInstr &MI) const;
0446 
0447   /// Return true if a G_{EXTRACT,INSERT}_VECTOR_ELT has an out of range index.
0448   bool matchInsertExtractVecEltOutOfBounds(MachineInstr &MI) const;
0449 
0450   /// Return true if a G_SELECT instruction \p MI has a constant comparison. If
0451   /// true, \p OpIdx will store the operand index of the known selected value.
0452   bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx) const;
0453 
0454   /// Replace an instruction with a G_FCONSTANT with value \p C.
0455   void replaceInstWithFConstant(MachineInstr &MI, double C) const;
0456 
0457   /// Replace an instruction with an G_FCONSTANT with value \p CFP.
0458   void replaceInstWithFConstant(MachineInstr &MI, ConstantFP *CFP) const;
0459 
0460   /// Replace an instruction with a G_CONSTANT with value \p C.
0461   void replaceInstWithConstant(MachineInstr &MI, int64_t C) const;
0462 
0463   /// Replace an instruction with a G_CONSTANT with value \p C.
0464   void replaceInstWithConstant(MachineInstr &MI, APInt C) const;
0465 
0466   /// Replace an instruction with a G_IMPLICIT_DEF.
0467   void replaceInstWithUndef(MachineInstr &MI) const;
0468 
0469   /// Delete \p MI and replace all of its uses with its \p OpIdx-th operand.
0470   void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const;
0471 
0472   /// Delete \p MI and replace all of its uses with \p Replacement.
0473   void replaceSingleDefInstWithReg(MachineInstr &MI,
0474                                    Register Replacement) const;
0475 
0476   /// @brief Replaces the shift amount in \p MI with ShiftAmt % BW
0477   /// @param MI
0478   void applyFunnelShiftConstantModulo(MachineInstr &MI) const;
0479 
0480   /// Return true if \p MOP1 and \p MOP2 are register operands are defined by
0481   /// equivalent instructions.
0482   bool matchEqualDefs(const MachineOperand &MOP1,
0483                       const MachineOperand &MOP2) const;
0484 
0485   /// Return true if \p MOP is defined by a G_CONSTANT or splat with a value equal to
0486   /// \p C.
0487   bool matchConstantOp(const MachineOperand &MOP, int64_t C) const;
0488 
0489   /// Return true if \p MOP is defined by a G_FCONSTANT or splat with a value exactly
0490   /// equal to \p C.
0491   bool matchConstantFPOp(const MachineOperand &MOP, double C) const;
0492 
0493   /// @brief Checks if constant at \p ConstIdx is larger than \p MI 's bitwidth
0494   /// @param ConstIdx Index of the constant
0495   bool matchConstantLargerBitWidth(MachineInstr &MI, unsigned ConstIdx) const;
0496 
0497   /// Optimize (cond ? x : x) -> x
0498   bool matchSelectSameVal(MachineInstr &MI) const;
0499 
0500   /// Optimize (x op x) -> x
0501   bool matchBinOpSameVal(MachineInstr &MI) const;
0502 
0503   /// Check if operand \p OpIdx is zero.
0504   bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx) const;
0505 
0506   /// Check if operand \p OpIdx is undef.
0507   bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const;
0508 
0509   /// Check if operand \p OpIdx is known to be a power of 2.
0510   bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
0511                                           unsigned OpIdx) const;
0512 
0513   /// Erase \p MI
0514   void eraseInst(MachineInstr &MI) const;
0515 
0516   /// Return true if MI is a G_ADD which can be simplified to a G_SUB.
0517   bool matchSimplifyAddToSub(MachineInstr &MI,
0518                              std::tuple<Register, Register> &MatchInfo) const;
0519   void applySimplifyAddToSub(MachineInstr &MI,
0520                              std::tuple<Register, Register> &MatchInfo) const;
0521 
0522   /// Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
0523   bool matchHoistLogicOpWithSameOpcodeHands(
0524       MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const;
0525 
0526   /// Replace \p MI with a series of instructions described in \p MatchInfo.
0527   void applyBuildInstructionSteps(MachineInstr &MI,
0528                                   InstructionStepsMatchInfo &MatchInfo) const;
0529 
0530   /// Match ashr (shl x, C), C -> sext_inreg (C)
0531   bool matchAshrShlToSextInreg(MachineInstr &MI,
0532                                std::tuple<Register, int64_t> &MatchInfo) const;
0533   void applyAshShlToSextInreg(MachineInstr &MI,
0534                               std::tuple<Register, int64_t> &MatchInfo) const;
0535 
0536   /// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
0537   bool matchOverlappingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0538 
0539   /// \return true if \p MI is a G_AND instruction whose operands are x and y
0540   /// where x & y == x or x & y == y. (E.g., one of operands is all-ones value.)
0541   ///
0542   /// \param [in] MI - The G_AND instruction.
0543   /// \param [out] Replacement - A register the G_AND should be replaced with on
0544   /// success.
0545   bool matchRedundantAnd(MachineInstr &MI, Register &Replacement) const;
0546 
0547   /// \return true if \p MI is a G_OR instruction whose operands are x and y
0548   /// where x | y == x or x | y == y. (E.g., one of operands is all-zeros
0549   /// value.)
0550   ///
0551   /// \param [in] MI - The G_OR instruction.
0552   /// \param [out] Replacement - A register the G_OR should be replaced with on
0553   /// success.
0554   bool matchRedundantOr(MachineInstr &MI, Register &Replacement) const;
0555 
0556   /// \return true if \p MI is a G_SEXT_INREG that can be erased.
0557   bool matchRedundantSExtInReg(MachineInstr &MI) const;
0558 
0559   /// Combine inverting a result of a compare into the opposite cond code.
0560   bool matchNotCmp(MachineInstr &MI,
0561                    SmallVectorImpl<Register> &RegsToNegate) const;
0562   void applyNotCmp(MachineInstr &MI,
0563                    SmallVectorImpl<Register> &RegsToNegate) const;
0564 
0565   /// Fold (xor (and x, y), y) -> (and (not x), y)
0566   ///{
0567   bool matchXorOfAndWithSameReg(MachineInstr &MI,
0568                                 std::pair<Register, Register> &MatchInfo) const;
0569   void applyXorOfAndWithSameReg(MachineInstr &MI,
0570                                 std::pair<Register, Register> &MatchInfo) const;
0571   ///}
0572 
0573   /// Combine G_PTR_ADD with nullptr to G_INTTOPTR
0574   bool matchPtrAddZero(MachineInstr &MI) const;
0575   void applyPtrAddZero(MachineInstr &MI) const;
0576 
0577   /// Combine G_UREM x, (known power of 2) to an add and bitmasking.
0578   void applySimplifyURemByPow2(MachineInstr &MI) const;
0579 
0580   /// Push a binary operator through a select on constants.
0581   ///
0582   /// binop (select cond, K0, K1), K2 ->
0583   ///   select cond, (binop K0, K2), (binop K1, K2)
0584   bool matchFoldBinOpIntoSelect(MachineInstr &MI, unsigned &SelectOpNo) const;
0585   void applyFoldBinOpIntoSelect(MachineInstr &MI,
0586                                 const unsigned &SelectOpNo) const;
0587 
0588   bool matchCombineInsertVecElts(MachineInstr &MI,
0589                                  SmallVectorImpl<Register> &MatchInfo) const;
0590 
0591   void applyCombineInsertVecElts(MachineInstr &MI,
0592                                  SmallVectorImpl<Register> &MatchInfo) const;
0593 
0594   /// Match expression trees of the form
0595   ///
0596   /// \code
0597   ///  sN *a = ...
0598   ///  sM val = a[0] | (a[1] << N) | (a[2] << 2N) | (a[3] << 3N) ...
0599   /// \endcode
0600   ///
0601   /// And check if the tree can be replaced with a M-bit load + possibly a
0602   /// bswap.
0603   bool matchLoadOrCombine(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0604 
0605   bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const;
0606   void applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const;
0607 
0608   bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const;
0609   void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const;
0610 
0611   bool matchExtractAllEltsFromBuildVector(
0612       MachineInstr &MI,
0613       SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo) const;
0614   void applyExtractAllEltsFromBuildVector(
0615       MachineInstr &MI,
0616       SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo) const;
0617 
0618   /// Use a function which takes in a MachineIRBuilder to perform a combine.
0619   /// By default, it erases the instruction \p MI from the function.
0620   void applyBuildFn(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0621   /// Use a function which takes in a MachineIRBuilder to perform a combine.
0622   /// This variant does not erase \p MI after calling the build function.
0623   void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0624 
0625   bool matchOrShiftToFunnelShift(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0626   bool matchFunnelShiftToRotate(MachineInstr &MI) const;
0627   void applyFunnelShiftToRotate(MachineInstr &MI) const;
0628   bool matchRotateOutOfRange(MachineInstr &MI) const;
0629   void applyRotateOutOfRange(MachineInstr &MI) const;
0630 
0631   bool matchUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const;
0632   void applyUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const;
0633 
0634   /// \returns true if a G_ICMP instruction \p MI can be replaced with a true
0635   /// or false constant based off of KnownBits information.
0636   bool matchICmpToTrueFalseKnownBits(MachineInstr &MI,
0637                                      int64_t &MatchInfo) const;
0638 
0639   /// \returns true if a G_ICMP \p MI can be replaced with its LHS based off of
0640   /// KnownBits information.
0641   bool matchICmpToLHSKnownBits(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0642 
0643   /// \returns true if (and (or x, c1), c2) can be replaced with (and x, c2)
0644   bool matchAndOrDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0645 
0646   bool matchBitfieldExtractFromSExtInReg(MachineInstr &MI,
0647                                          BuildFnTy &MatchInfo) const;
0648   /// Match: and (lshr x, cst), mask -> ubfx x, cst, width
0649   bool matchBitfieldExtractFromAnd(MachineInstr &MI,
0650                                    BuildFnTy &MatchInfo) const;
0651 
0652   /// Match: shr (shl x, n), k -> sbfx/ubfx x, pos, width
0653   bool matchBitfieldExtractFromShr(MachineInstr &MI,
0654                                    BuildFnTy &MatchInfo) const;
0655 
0656   /// Match: shr (and x, n), k -> ubfx x, pos, width
0657   bool matchBitfieldExtractFromShrAnd(MachineInstr &MI,
0658                                       BuildFnTy &MatchInfo) const;
0659 
0660   // Helpers for reassociation:
0661   bool matchReassocConstantInnerRHS(GPtrAdd &MI, MachineInstr *RHS,
0662                                     BuildFnTy &MatchInfo) const;
0663   bool matchReassocFoldConstantsInSubTree(GPtrAdd &MI, MachineInstr *LHS,
0664                                           MachineInstr *RHS,
0665                                           BuildFnTy &MatchInfo) const;
0666   bool matchReassocConstantInnerLHS(GPtrAdd &MI, MachineInstr *LHS,
0667                                     MachineInstr *RHS,
0668                                     BuildFnTy &MatchInfo) const;
0669   /// Reassociate pointer calculations with G_ADD involved, to allow better
0670   /// addressing mode usage.
0671   bool matchReassocPtrAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0672 
0673   /// Try to reassociate to reassociate operands of a commutative binop.
0674   bool tryReassocBinOp(unsigned Opc, Register DstReg, Register Op0,
0675                        Register Op1, BuildFnTy &MatchInfo) const;
0676   /// Reassociate commutative binary operations like G_ADD.
0677   bool matchReassocCommBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0678 
0679   /// Do constant folding when opportunities are exposed after MIR building.
0680   bool matchConstantFoldCastOp(MachineInstr &MI, APInt &MatchInfo) const;
0681 
0682   /// Do constant folding when opportunities are exposed after MIR building.
0683   bool matchConstantFoldBinOp(MachineInstr &MI, APInt &MatchInfo) const;
0684 
0685   /// Do constant FP folding when opportunities are exposed after MIR building.
0686   bool matchConstantFoldFPBinOp(MachineInstr &MI, ConstantFP *&MatchInfo) const;
0687 
0688   /// Constant fold G_FMA/G_FMAD.
0689   bool matchConstantFoldFMA(MachineInstr &MI, ConstantFP *&MatchInfo) const;
0690 
0691   /// \returns true if it is possible to narrow the width of a scalar binop
0692   /// feeding a G_AND instruction \p MI.
0693   bool matchNarrowBinopFeedingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0694 
0695   /// Given an G_UDIV \p MI expressing a divide by constant, return an
0696   /// expression that implements it by multiplying by a magic number.
0697   /// Ref: "Hacker's Delight" or "The PowerPC Compiler Writer's Guide".
0698   MachineInstr *buildUDivUsingMul(MachineInstr &MI) const;
0699   /// Combine G_UDIV by constant into a multiply by magic constant.
0700   bool matchUDivByConst(MachineInstr &MI) const;
0701   void applyUDivByConst(MachineInstr &MI) const;
0702 
0703   /// Given an G_SDIV \p MI expressing a signed divide by constant, return an
0704   /// expression that implements it by multiplying by a magic number.
0705   /// Ref: "Hacker's Delight" or "The PowerPC Compiler Writer's Guide".
0706   MachineInstr *buildSDivUsingMul(MachineInstr &MI) const;
0707   bool matchSDivByConst(MachineInstr &MI) const;
0708   void applySDivByConst(MachineInstr &MI) const;
0709 
0710   /// Given an G_SDIV \p MI expressing a signed divided by a pow2 constant,
0711   /// return expressions that implements it by shifting.
0712   bool matchDivByPow2(MachineInstr &MI, bool IsSigned) const;
0713   void applySDivByPow2(MachineInstr &MI) const;
0714   /// Given an G_UDIV \p MI expressing an unsigned divided by a pow2 constant,
0715   /// return expressions that implements it by shifting.
0716   void applyUDivByPow2(MachineInstr &MI) const;
0717 
0718   // G_UMULH x, (1 << c)) -> x >> (bitwidth - c)
0719   bool matchUMulHToLShr(MachineInstr &MI) const;
0720   void applyUMulHToLShr(MachineInstr &MI) const;
0721 
0722   /// Try to transform \p MI by using all of the above
0723   /// combine functions. Returns true if changed.
0724   bool tryCombine(MachineInstr &MI) const;
0725 
0726   /// Emit loads and stores that perform the given memcpy.
0727   /// Assumes \p MI is a G_MEMCPY_INLINE
0728   /// TODO: implement dynamically sized inline memcpy,
0729   ///       and rename: s/bool tryEmit/void emit/
0730   bool tryEmitMemcpyInline(MachineInstr &MI) const;
0731 
0732   /// Match:
0733   ///   (G_UMULO x, 2) -> (G_UADDO x, x)
0734   ///   (G_SMULO x, 2) -> (G_SADDO x, x)
0735   bool matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0736 
0737   /// Match:
0738   /// (G_*MULO x, 0) -> 0 + no carry out
0739   bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0740 
0741   /// Match:
0742   /// (G_*ADDE x, y, 0) -> (G_*ADDO x, y)
0743   /// (G_*SUBE x, y, 0) -> (G_*SUBO x, y)
0744   bool matchAddEToAddO(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0745 
0746   /// Transform (fadd x, fneg(y)) -> (fsub x, y)
0747   ///           (fadd fneg(x), y) -> (fsub y, x)
0748   ///           (fsub x, fneg(y)) -> (fadd x, y)
0749   ///           (fmul fneg(x), fneg(y)) -> (fmul x, y)
0750   ///           (fdiv fneg(x), fneg(y)) -> (fdiv x, y)
0751   ///           (fmad fneg(x), fneg(y), z) -> (fmad x, y, z)
0752   ///           (fma fneg(x), fneg(y), z) -> (fma x, y, z)
0753   bool matchRedundantNegOperands(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0754 
0755   bool matchFsubToFneg(MachineInstr &MI, Register &MatchInfo) const;
0756   void applyFsubToFneg(MachineInstr &MI, Register &MatchInfo) const;
0757 
0758   bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally,
0759                            bool &HasFMAD, bool &Aggressive,
0760                            bool CanReassociate = false) const;
0761 
0762   /// Transform (fadd (fmul x, y), z) -> (fma x, y, z)
0763   ///           (fadd (fmul x, y), z) -> (fmad x, y, z)
0764   bool matchCombineFAddFMulToFMadOrFMA(MachineInstr &MI,
0765                                        BuildFnTy &MatchInfo) const;
0766 
0767   /// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
0768   ///           (fadd (fpext (fmul x, y)), z) -> (fmad (fpext x), (fpext y), z)
0769   bool matchCombineFAddFpExtFMulToFMadOrFMA(MachineInstr &MI,
0770                                             BuildFnTy &MatchInfo) const;
0771 
0772   /// Transform (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z))
0773   ///          (fadd (fmad x, y, (fmul u, v)), z) -> (fmad x, y, (fmad u, v, z))
0774   bool matchCombineFAddFMAFMulToFMadOrFMA(MachineInstr &MI,
0775                                           BuildFnTy &MatchInfo) const;
0776 
0777   // Transform (fadd (fma x, y, (fpext (fmul u, v))), z)
0778   //            -> (fma x, y, (fma (fpext u), (fpext v), z))
0779   //           (fadd (fmad x, y, (fpext (fmul u, v))), z)
0780   //            -> (fmad x, y, (fmad (fpext u), (fpext v), z))
0781   bool
0782   matchCombineFAddFpExtFMulToFMadOrFMAAggressive(MachineInstr &MI,
0783                                                  BuildFnTy &MatchInfo) const;
0784 
0785   /// Transform (fsub (fmul x, y), z) -> (fma x, y, -z)
0786   ///           (fsub (fmul x, y), z) -> (fmad x, y, -z)
0787   bool matchCombineFSubFMulToFMadOrFMA(MachineInstr &MI,
0788                                        BuildFnTy &MatchInfo) const;
0789 
0790   /// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z))
0791   ///           (fsub (fneg (fmul, x, y)), z) -> (fmad (fneg x), y, (fneg z))
0792   bool matchCombineFSubFNegFMulToFMadOrFMA(MachineInstr &MI,
0793                                            BuildFnTy &MatchInfo) const;
0794 
0795   /// Transform (fsub (fpext (fmul x, y)), z)
0796   ///           -> (fma (fpext x), (fpext y), (fneg z))
0797   ///           (fsub (fpext (fmul x, y)), z)
0798   ///           -> (fmad (fpext x), (fpext y), (fneg z))
0799   bool matchCombineFSubFpExtFMulToFMadOrFMA(MachineInstr &MI,
0800                                             BuildFnTy &MatchInfo) const;
0801 
0802   /// Transform (fsub (fpext (fneg (fmul x, y))), z)
0803   ///           -> (fneg (fma (fpext x), (fpext y), z))
0804   ///           (fsub (fpext (fneg (fmul x, y))), z)
0805   ///           -> (fneg (fmad (fpext x), (fpext y), z))
0806   bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI,
0807                                                 BuildFnTy &MatchInfo) const;
0808 
0809   bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info) const;
0810 
0811   /// Transform G_ADD(x, G_SUB(y, x)) to y.
0812   /// Transform G_ADD(G_SUB(y, x), x) to y.
0813   bool matchAddSubSameReg(MachineInstr &MI, Register &Src) const;
0814 
0815   bool matchBuildVectorIdentityFold(MachineInstr &MI,
0816                                     Register &MatchInfo) const;
0817   bool matchTruncBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const;
0818   bool matchTruncLshrBuildVectorFold(MachineInstr &MI,
0819                                      Register &MatchInfo) const;
0820 
0821   /// Transform:
0822   ///   (x + y) - y -> x
0823   ///   (x + y) - x -> y
0824   ///   x - (y + x) -> 0 - y
0825   ///   x - (x + z) -> 0 - z
0826   bool matchSubAddSameReg(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0827 
0828   /// \returns true if it is possible to simplify a select instruction \p MI
0829   /// to a min/max instruction of some sort.
0830   bool matchSimplifySelectToMinMax(MachineInstr &MI,
0831                                    BuildFnTy &MatchInfo) const;
0832 
0833   /// Transform:
0834   ///   (X + Y) == X -> Y == 0
0835   ///   (X - Y) == X -> Y == 0
0836   ///   (X ^ Y) == X -> Y == 0
0837   ///   (X + Y) != X -> Y != 0
0838   ///   (X - Y) != X -> Y != 0
0839   ///   (X ^ Y) != X -> Y != 0
0840   bool matchRedundantBinOpInEquality(MachineInstr &MI,
0841                                      BuildFnTy &MatchInfo) const;
0842 
0843   /// Match shifts greater or equal to the range (the bitwidth of the result
0844   /// datatype, or the effective bitwidth of the source value).
0845   bool matchShiftsTooBig(MachineInstr &MI,
0846                          std::optional<int64_t> &MatchInfo) const;
0847 
0848   /// Match constant LHS ops that should be commuted.
0849   bool matchCommuteConstantToRHS(MachineInstr &MI) const;
0850 
0851   /// Combine sext of trunc.
0852   bool matchSextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0853 
0854   /// Combine zext of trunc.
0855   bool matchZextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0856 
0857   /// Combine zext nneg to sext.
0858   bool matchNonNegZext(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0859 
0860   /// Match constant LHS FP ops that should be commuted.
0861   bool matchCommuteFPConstantToRHS(MachineInstr &MI) const;
0862 
0863   // Given a binop \p MI, commute operands 1 and 2.
0864   void applyCommuteBinOpOperands(MachineInstr &MI) const;
0865 
0866   /// Combine select to integer min/max.
0867   bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0868 
0869   /// Tranform (neg (min/max x, (neg x))) into (max/min x, (neg x)).
0870   bool matchSimplifyNegMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0871 
0872   /// Combine selects.
0873   bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0874 
0875   /// Combine ands.
0876   bool matchAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0877 
0878   /// Combine ors.
0879   bool matchOr(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0880 
0881   /// trunc (binop X, C) --> binop (trunc X, trunc C).
0882   bool matchNarrowBinop(const MachineInstr &TruncMI,
0883                         const MachineInstr &BinopMI,
0884                         BuildFnTy &MatchInfo) const;
0885 
0886   bool matchCastOfInteger(const MachineInstr &CastMI, APInt &MatchInfo) const;
0887 
0888   /// Combine addos.
0889   bool matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0890 
0891   /// Combine extract vector element.
0892   bool matchExtractVectorElement(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0893 
0894   /// Combine extract vector element with a build vector on the vector register.
0895   bool matchExtractVectorElementWithBuildVector(const MachineInstr &MI,
0896                                                 const MachineInstr &MI2,
0897                                                 BuildFnTy &MatchInfo) const;
0898 
0899   /// Combine extract vector element with a build vector trunc on the vector
0900   /// register.
0901   bool
0902   matchExtractVectorElementWithBuildVectorTrunc(const MachineOperand &MO,
0903                                                 BuildFnTy &MatchInfo) const;
0904 
0905   /// Combine extract vector element with a shuffle vector on the vector
0906   /// register.
0907   bool matchExtractVectorElementWithShuffleVector(const MachineInstr &MI,
0908                                                   const MachineInstr &MI2,
0909                                                   BuildFnTy &MatchInfo) const;
0910 
0911   /// Combine extract vector element with a insert vector element on the vector
0912   /// register and different indices.
0913   bool
0914   matchExtractVectorElementWithDifferentIndices(const MachineOperand &MO,
0915                                                 BuildFnTy &MatchInfo) const;
0916 
0917   /// Remove references to rhs if it is undef
0918   bool matchShuffleUndefRHS(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0919 
0920   /// Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not
0921   /// reference a.
0922   bool matchShuffleDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const;
0923 
0924   /// Use a function which takes in a MachineIRBuilder to perform a combine.
0925   /// By default, it erases the instruction def'd on \p MO from the function.
0926   void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0927 
0928   /// Match FPOWI if it's safe to extend it into a series of multiplications.
0929   bool matchFPowIExpansion(MachineInstr &MI, int64_t Exponent) const;
0930 
0931   /// Expands FPOWI into a series of multiplications and a division if the
0932   /// exponent is negative.
0933   void applyExpandFPowI(MachineInstr &MI, int64_t Exponent) const;
0934 
0935   /// Combine insert vector element OOB.
0936   bool matchInsertVectorElementOOB(MachineInstr &MI,
0937                                    BuildFnTy &MatchInfo) const;
0938 
0939   bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI,
0940                                              BuildFnTy &MatchInfo) const;
0941 
0942   bool matchAddOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0943 
0944   bool matchMulOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0945 
0946   bool matchSubOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0947 
0948   bool matchShlOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
0949 
0950   /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x).
0951   bool matchTruncateOfExt(const MachineInstr &Root, const MachineInstr &ExtMI,
0952                           BuildFnTy &MatchInfo) const;
0953 
0954   bool matchCastOfSelect(const MachineInstr &Cast, const MachineInstr &SelectMI,
0955                          BuildFnTy &MatchInfo) const;
0956   bool matchFoldAPlusC1MinusC2(const MachineInstr &MI,
0957                                BuildFnTy &MatchInfo) const;
0958 
0959   bool matchFoldC2MinusAPlusC1(const MachineInstr &MI,
0960                                BuildFnTy &MatchInfo) const;
0961 
0962   bool matchFoldAMinusC1MinusC2(const MachineInstr &MI,
0963                                 BuildFnTy &MatchInfo) const;
0964 
0965   bool matchFoldC1Minus2MinusC2(const MachineInstr &MI,
0966                                 BuildFnTy &MatchInfo) const;
0967 
0968   // fold ((A-C1)+C2) -> (A+(C2-C1))
0969   bool matchFoldAMinusC1PlusC2(const MachineInstr &MI,
0970                                BuildFnTy &MatchInfo) const;
0971 
0972   bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
0973                      BuildFnTy &MatchInfo) const;
0974 
0975   bool matchCastOfBuildVector(const MachineInstr &CastMI,
0976                               const MachineInstr &BVMI,
0977                               BuildFnTy &MatchInfo) const;
0978 
0979   bool matchCanonicalizeICmp(const MachineInstr &MI,
0980                              BuildFnTy &MatchInfo) const;
0981   bool matchCanonicalizeFCmp(const MachineInstr &MI,
0982                              BuildFnTy &MatchInfo) const;
0983 
0984   // unmerge_values(anyext(build vector)) -> build vector(anyext)
0985   bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
0986                                            BuildFnTy &MatchInfo) const;
0987 
0988   // merge_values(_, undef) -> anyext
0989   bool matchMergeXAndUndef(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
0990 
0991   // merge_values(_, zero) -> zext
0992   bool matchMergeXAndZero(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
0993 
0994   // overflow sub
0995   bool matchSuboCarryOut(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
0996 
0997 private:
0998   /// Checks for legality of an indexed variant of \p LdSt.
0999   bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
1000   /// Given a non-indexed load or store instruction \p MI, find an offset that
1001   /// can be usefully and legally folded into it as a post-indexing operation.
1002   ///
1003   /// \returns true if a candidate is found.
1004   bool findPostIndexCandidate(GLoadStore &MI, Register &Addr, Register &Base,
1005                               Register &Offset, bool &RematOffset) const;
1006 
1007   /// Given a non-indexed load or store instruction \p MI, find an offset that
1008   /// can be usefully and legally folded into it as a pre-indexing operation.
1009   ///
1010   /// \returns true if a candidate is found.
1011   bool findPreIndexCandidate(GLoadStore &MI, Register &Addr, Register &Base,
1012                              Register &Offset) const;
1013 
1014   /// Helper function for matchLoadOrCombine. Searches for Registers
1015   /// which may have been produced by a load instruction + some arithmetic.
1016   ///
1017   /// \param [in] Root - The search root.
1018   ///
1019   /// \returns The Registers found during the search.
1020   std::optional<SmallVector<Register, 8>>
1021   findCandidatesForLoadOrCombine(const MachineInstr *Root) const;
1022 
1023   /// Helper function for matchLoadOrCombine.
1024   ///
1025   /// Checks if every register in \p RegsToVisit is defined by a load
1026   /// instruction + some arithmetic.
1027   ///
1028   /// \param [out] MemOffset2Idx - Maps the byte positions each load ends up
1029   /// at to the index of the load.
1030   /// \param [in] MemSizeInBits - The number of bits each load should produce.
1031   ///
1032   /// \returns On success, a 3-tuple containing lowest-index load found, the
1033   /// lowest index, and the last load in the sequence.
1034   std::optional<std::tuple<GZExtLoad *, int64_t, GZExtLoad *>>
1035   findLoadOffsetsForLoadOrCombine(
1036       SmallDenseMap<int64_t, int64_t, 8> &MemOffset2Idx,
1037       const SmallVector<Register, 8> &RegsToVisit,
1038       const unsigned MemSizeInBits) const;
1039 
1040   /// Examines the G_PTR_ADD instruction \p PtrAdd and determines if performing
1041   /// a re-association of its operands would break an existing legal addressing
1042   /// mode that the address computation currently represents.
1043   bool reassociationCanBreakAddressingModePattern(MachineInstr &PtrAdd) const;
1044 
1045   /// Behavior when a floating point min/max is given one NaN and one
1046   /// non-NaN as input.
1047   enum class SelectPatternNaNBehaviour {
1048     NOT_APPLICABLE = 0, /// NaN behavior not applicable.
1049     RETURNS_NAN,        /// Given one NaN input, returns the NaN.
1050     RETURNS_OTHER,      /// Given one NaN input, returns the non-NaN.
1051     RETURNS_ANY /// Given one NaN input, can return either (or both operands are
1052                 /// known non-NaN.)
1053   };
1054 
1055   /// \returns which of \p LHS and \p RHS would be the result of a non-equality
1056   /// floating point comparison where one of \p LHS and \p RHS may be NaN.
1057   ///
1058   /// If both \p LHS and \p RHS may be NaN, returns
1059   /// SelectPatternNaNBehaviour::NOT_APPLICABLE.
1060   SelectPatternNaNBehaviour
1061   computeRetValAgainstNaN(Register LHS, Register RHS,
1062                           bool IsOrderedComparison) const;
1063 
1064   /// Determines the floating point min/max opcode which should be used for
1065   /// a G_SELECT fed by a G_FCMP with predicate \p Pred.
1066   ///
1067   /// \returns 0 if this G_SELECT should not be combined to a floating point
1068   /// min or max. If it should be combined, returns one of
1069   ///
1070   /// * G_FMAXNUM
1071   /// * G_FMAXIMUM
1072   /// * G_FMINNUM
1073   /// * G_FMINIMUM
1074   ///
1075   /// Helper function for matchFPSelectToMinMax.
1076   unsigned getFPMinMaxOpcForSelect(CmpInst::Predicate Pred, LLT DstTy,
1077                                    SelectPatternNaNBehaviour VsNaNRetVal) const;
1078 
1079   /// Handle floating point cases for matchSimplifySelectToMinMax.
1080   ///
1081   /// E.g.
1082   ///
1083   /// select (fcmp uge x, 1.0) x, 1.0 -> fmax x, 1.0
1084   /// select (fcmp uge x, 1.0) 1.0, x -> fminnm x, 1.0
1085   bool matchFPSelectToMinMax(Register Dst, Register Cond, Register TrueVal,
1086                              Register FalseVal, BuildFnTy &MatchInfo) const;
1087 
1088   /// Try to fold selects to logical operations.
1089   bool tryFoldBoolSelectToLogic(GSelect *Select, BuildFnTy &MatchInfo) const;
1090 
1091   bool tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo) const;
1092 
1093   bool isOneOrOneSplat(Register Src, bool AllowUndefs) const;
1094   bool isZeroOrZeroSplat(Register Src, bool AllowUndefs) const;
1095   bool isConstantSplatVector(Register Src, int64_t SplatValue,
1096                              bool AllowUndefs) const;
1097   bool isConstantOrConstantVectorI(Register Src) const;
1098 
1099   std::optional<APInt> getConstantOrConstantSplatVector(Register Src) const;
1100 
1101   /// Fold (icmp Pred1 V1, C1) && (icmp Pred2 V2, C2)
1102   /// or   (icmp Pred1 V1, C1) || (icmp Pred2 V2, C2)
1103   /// into a single comparison using range-based reasoning.
1104   bool tryFoldAndOrOrICmpsUsingRanges(GLogicalBinOp *Logic,
1105                                       BuildFnTy &MatchInfo) const;
1106 
1107   // Simplify (cmp cc0 x, y) (&& or ||) (cmp cc1 x, y) -> cmp cc2 x, y.
1108   bool tryFoldLogicOfFCmps(GLogicalBinOp *Logic, BuildFnTy &MatchInfo) const;
1109 
1110   bool isCastFree(unsigned Opcode, LLT ToTy, LLT FromTy) const;
1111 
1112   bool constantFoldICmp(const GICmp &ICmp, const GIConstant &LHSCst,
1113                         const GIConstant &RHSCst, BuildFnTy &MatchInfo) const;
1114   bool constantFoldFCmp(const GFCmp &FCmp, const GFConstant &LHSCst,
1115                         const GFConstant &RHSCst, BuildFnTy &MatchInfo) const;
1116 };
1117 } // namespace llvm
1118 
1119 #endif