xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 //===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===--------------------------------------------------------------------===//
8 /// \file
9 /// This contains common combine transformations that may be used in a combine
10 /// pass,or by the target elsewhere.
11 /// Targets can pick individual opcode transformations from the helper or use
12 /// tryCombine which invokes all transformations. All of the transformations
13 /// return true if the MachineInstruction changed and false otherwise.
14 ///
15 //===--------------------------------------------------------------------===//
16 
17 #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H
18 #define LLVM_CODEGEN_GLOBALISEL_COMBINERHELPER_H
19 
20 #include "llvm/ADT/APFloat.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/CodeGen/LowLevelType.h"
23 #include "llvm/CodeGen/Register.h"
24 #include "llvm/Support/Alignment.h"
25 
26 namespace llvm {
27 
28 class GISelChangeObserver;
29 class MachineIRBuilder;
30 class MachineInstrBuilder;
31 class MachineRegisterInfo;
32 class MachineInstr;
33 class MachineOperand;
34 class GISelKnownBits;
35 class MachineDominatorTree;
36 class LegalizerInfo;
37 struct LegalityQuery;
38 class TargetLowering;
39 
40 struct PreferredTuple {
41   LLT Ty;                // The result type of the extend.
42   unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT
43   MachineInstr *MI;
44 };
45 
46 struct IndexedLoadStoreMatchInfo {
47   Register Addr;
48   Register Base;
49   Register Offset;
50   bool IsPre;
51 };
52 
53 struct PtrAddChain {
54   int64_t Imm;
55   Register Base;
56 };
57 
58 struct RegisterImmPair {
59   Register Reg;
60   int64_t Imm;
61 };
62 
63 struct ShiftOfShiftedLogic {
64   MachineInstr *Logic;
65   MachineInstr *Shift2;
66   Register LogicNonShiftReg;
67   uint64_t ValSum;
68 };
69 
70 using OperandBuildSteps =
71     SmallVector<std::function<void(MachineInstrBuilder &)>, 4>;
72 struct InstructionBuildSteps {
73   unsigned Opcode = 0;          /// The opcode for the produced instruction.
74   OperandBuildSteps OperandFns; /// Operands to be added to the instruction.
75   InstructionBuildSteps() = default;
InstructionBuildStepsInstructionBuildSteps76   InstructionBuildSteps(unsigned Opcode, const OperandBuildSteps &OperandFns)
77       : Opcode(Opcode), OperandFns(OperandFns) {}
78 };
79 
80 struct InstructionStepsMatchInfo {
81   /// Describes instructions to be built during a combine.
82   SmallVector<InstructionBuildSteps, 2> InstrsToBuild;
83   InstructionStepsMatchInfo() = default;
InstructionStepsMatchInfoInstructionStepsMatchInfo84   InstructionStepsMatchInfo(
85       std::initializer_list<InstructionBuildSteps> InstrsToBuild)
86       : InstrsToBuild(InstrsToBuild) {}
87 };
88 
89 class CombinerHelper {
90 protected:
91   MachineIRBuilder &Builder;
92   MachineRegisterInfo &MRI;
93   GISelChangeObserver &Observer;
94   GISelKnownBits *KB;
95   MachineDominatorTree *MDT;
96   const LegalizerInfo *LI;
97 
98 public:
99   CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B,
100                  GISelKnownBits *KB = nullptr,
101                  MachineDominatorTree *MDT = nullptr,
102                  const LegalizerInfo *LI = nullptr);
103 
getKnownBits()104   GISelKnownBits *getKnownBits() const {
105     return KB;
106   }
107 
108   const TargetLowering &getTargetLowering() const;
109 
110   /// \return true if the combine is running prior to legalization, or if \p
111   /// Query is legal on the target.
112   bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const;
113 
114   /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes
115   void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const;
116 
117   /// Replace a single register operand with a new register and inform the
118   /// observer of the changes.
119   void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp,
120                         Register ToReg) const;
121 
122   /// If \p MI is COPY, try to combine it.
123   /// Returns true if MI changed.
124   bool tryCombineCopy(MachineInstr &MI);
125   bool matchCombineCopy(MachineInstr &MI);
126   void applyCombineCopy(MachineInstr &MI);
127 
128   /// Returns true if \p DefMI precedes \p UseMI or they are the same
129   /// instruction. Both must be in the same basic block.
130   bool isPredecessor(const MachineInstr &DefMI, const MachineInstr &UseMI);
131 
132   /// Returns true if \p DefMI dominates \p UseMI. By definition an
133   /// instruction dominates itself.
134   ///
135   /// If we haven't been provided with a MachineDominatorTree during
136   /// construction, this function returns a conservative result that tracks just
137   /// a single basic block.
138   bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI);
139 
140   /// If \p MI is extend that consumes the result of a load, try to combine it.
141   /// Returns true if MI changed.
142   bool tryCombineExtendingLoads(MachineInstr &MI);
143   bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo);
144   void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo);
145 
146   /// Combine \p MI into a pre-indexed or post-indexed load/store operation if
147   /// legal and the surrounding code makes it useful.
148   bool tryCombineIndexedLoadStore(MachineInstr &MI);
149   bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo);
150   void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo);
151 
152   bool matchSextTruncSextLoad(MachineInstr &MI);
153   bool applySextTruncSextLoad(MachineInstr &MI);
154 
155   /// Match sext_inreg(load p), imm -> sextload p
156   bool matchSextInRegOfLoad(MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo);
157   bool applySextInRegOfLoad(MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo);
158 
159   /// Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM
160   /// when their source operands are identical.
161   bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI);
162   void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI);
163 
164   /// If a brcond's true block is not the fallthrough, make it so by inverting
165   /// the condition and swapping operands.
166   bool matchOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond);
167   void applyOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond);
168 
169   /// If \p MI is G_CONCAT_VECTORS, try to combine it.
170   /// Returns true if MI changed.
171   /// Right now, we support:
172   /// - concat_vector(undef, undef) => undef
173   /// - concat_vector(build_vector(A, B), build_vector(C, D)) =>
174   ///   build_vector(A, B, C, D)
175   ///
176   /// \pre MI.getOpcode() == G_CONCAT_VECTORS.
177   bool tryCombineConcatVectors(MachineInstr &MI);
178   /// Check if the G_CONCAT_VECTORS \p MI is undef or if it
179   /// can be flattened into a build_vector.
180   /// In the first case \p IsUndef will be true.
181   /// In the second case \p Ops will contain the operands needed
182   /// to produce the flattened build_vector.
183   ///
184   /// \pre MI.getOpcode() == G_CONCAT_VECTORS.
185   bool matchCombineConcatVectors(MachineInstr &MI, bool &IsUndef,
186                                  SmallVectorImpl<Register> &Ops);
187   /// Replace \p MI with a flattened build_vector with \p Ops or an
188   /// implicit_def if IsUndef is true.
189   void applyCombineConcatVectors(MachineInstr &MI, bool IsUndef,
190                                  const ArrayRef<Register> Ops);
191 
192   /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
193   /// Returns true if MI changed.
194   ///
195   /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
196   bool tryCombineShuffleVector(MachineInstr &MI);
197   /// Check if the G_SHUFFLE_VECTOR \p MI can be replaced by a
198   /// concat_vectors.
199   /// \p Ops will contain the operands needed to produce the flattened
200   /// concat_vectors.
201   ///
202   /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
203   bool matchCombineShuffleVector(MachineInstr &MI,
204                                  SmallVectorImpl<Register> &Ops);
205   /// Replace \p MI with a concat_vectors with \p Ops.
206   void applyCombineShuffleVector(MachineInstr &MI,
207                                  const ArrayRef<Register> Ops);
208 
209   /// Optimize memcpy intrinsics et al, e.g. constant len calls.
210   /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline.
211   ///
212   /// For example (pre-indexed):
213   ///
214   ///     $addr = G_PTR_ADD $base, $offset
215   ///     [...]
216   ///     $val = G_LOAD $addr
217   ///     [...]
218   ///     $whatever = COPY $addr
219   ///
220   /// -->
221   ///
222   ///     $val, $addr = G_INDEXED_LOAD $base, $offset, 1 (IsPre)
223   ///     [...]
224   ///     $whatever = COPY $addr
225   ///
226   /// or (post-indexed):
227   ///
228   ///     G_STORE $val, $base
229   ///     [...]
230   ///     $addr = G_PTR_ADD $base, $offset
231   ///     [...]
232   ///     $whatever = COPY $addr
233   ///
234   /// -->
235   ///
236   ///     $addr = G_INDEXED_STORE $val, $base, $offset
237   ///     [...]
238   ///     $whatever = COPY $addr
239   bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0);
240 
241   bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo);
242   bool applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo);
243 
244   /// Fold (shift (shift base, x), y) -> (shift base (x+y))
245   bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo);
246   bool applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo);
247 
248   /// If we have a shift-by-constant of a bitwise logic op that itself has a
249   /// shift-by-constant operand with identical opcode, we may be able to convert
250   /// that into 2 independent shifts followed by the logic op.
251   bool matchShiftOfShiftedLogic(MachineInstr &MI,
252                                 ShiftOfShiftedLogic &MatchInfo);
253   bool applyShiftOfShiftedLogic(MachineInstr &MI,
254                                 ShiftOfShiftedLogic &MatchInfo);
255 
256   /// Transform a multiply by a power-of-2 value to a left shift.
257   bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal);
258   bool applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal);
259 
260   // Transform a G_SHL with an extended source into a narrower shift if
261   // possible.
262   bool matchCombineShlOfExtend(MachineInstr &MI, RegisterImmPair &MatchData);
263   bool applyCombineShlOfExtend(MachineInstr &MI,
264                                const RegisterImmPair &MatchData);
265 
266   /// Reduce a shift by a constant to an unmerge and a shift on a half sized
267   /// type. This will not produce a shift smaller than \p TargetShiftSize.
268   bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize,
269                                  unsigned &ShiftVal);
270   bool applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal);
271   bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount);
272 
273   /// Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z.
274   bool
275   matchCombineUnmergeMergeToPlainValues(MachineInstr &MI,
276                                         SmallVectorImpl<Register> &Operands);
277   bool
278   applyCombineUnmergeMergeToPlainValues(MachineInstr &MI,
279                                         SmallVectorImpl<Register> &Operands);
280 
281   /// Transform G_UNMERGE Constant -> Constant1, Constant2, ...
282   bool matchCombineUnmergeConstant(MachineInstr &MI,
283                                    SmallVectorImpl<APInt> &Csts);
284   bool applyCombineUnmergeConstant(MachineInstr &MI,
285                                    SmallVectorImpl<APInt> &Csts);
286 
287   /// Transform X, Y<dead> = G_UNMERGE Z -> X = G_TRUNC Z.
288   bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI);
289   bool applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI);
290 
291   /// Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0
292   bool matchCombineUnmergeZExtToZExt(MachineInstr &MI);
293   bool applyCombineUnmergeZExtToZExt(MachineInstr &MI);
294 
295   /// Transform fp_instr(cst) to constant result of the fp operation.
296   bool matchCombineConstantFoldFpUnary(MachineInstr &MI,
297                                        Optional<APFloat> &Cst);
298   bool applyCombineConstantFoldFpUnary(MachineInstr &MI,
299                                        Optional<APFloat> &Cst);
300 
301   /// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space.
302   bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg);
303   bool applyCombineI2PToP2I(MachineInstr &MI, Register &Reg);
304 
305   /// Transform PtrToInt(IntToPtr(x)) to x.
306   bool matchCombineP2IToI2P(MachineInstr &MI, Register &Reg);
307   bool applyCombineP2IToI2P(MachineInstr &MI, Register &Reg);
308 
309   /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y)
310   /// Transform G_ADD y, (G_PTRTOINT x) -> G_PTRTOINT (G_PTR_ADD x, y)
311   bool matchCombineAddP2IToPtrAdd(MachineInstr &MI,
312                                   std::pair<Register, bool> &PtrRegAndCommute);
313   bool applyCombineAddP2IToPtrAdd(MachineInstr &MI,
314                                   std::pair<Register, bool> &PtrRegAndCommute);
315 
316   // Transform G_PTR_ADD (G_PTRTOINT C1), C2 -> C1 + C2
317   bool matchCombineConstPtrAddToI2P(MachineInstr &MI, int64_t &NewCst);
318   bool applyCombineConstPtrAddToI2P(MachineInstr &MI, int64_t &NewCst);
319 
320   /// Transform anyext(trunc(x)) to x.
321   bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg);
322   bool applyCombineAnyExtTrunc(MachineInstr &MI, Register &Reg);
323 
324   /// Transform zext(trunc(x)) to x.
325   bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg);
326 
327   /// Transform [asz]ext([asz]ext(x)) to [asz]ext x.
328   bool matchCombineExtOfExt(MachineInstr &MI,
329                             std::tuple<Register, unsigned> &MatchInfo);
330   bool applyCombineExtOfExt(MachineInstr &MI,
331                             std::tuple<Register, unsigned> &MatchInfo);
332 
333   /// Transform fneg(fneg(x)) to x.
334   bool matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg);
335 
336   /// Match fabs(fabs(x)) to fabs(x).
337   bool matchCombineFAbsOfFAbs(MachineInstr &MI, Register &Src);
338   bool applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src);
339 
340   /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x).
341   bool matchCombineTruncOfExt(MachineInstr &MI,
342                               std::pair<Register, unsigned> &MatchInfo);
343   bool applyCombineTruncOfExt(MachineInstr &MI,
344                               std::pair<Register, unsigned> &MatchInfo);
345 
346   /// Transform trunc (shl x, K) to shl (trunc x),
347   /// K => K < VT.getScalarSizeInBits().
348   bool matchCombineTruncOfShl(MachineInstr &MI,
349                               std::pair<Register, Register> &MatchInfo);
350   bool applyCombineTruncOfShl(MachineInstr &MI,
351                               std::pair<Register, Register> &MatchInfo);
352 
353   /// Transform G_MUL(x, -1) to G_SUB(0, x)
354   bool applyCombineMulByNegativeOne(MachineInstr &MI);
355 
356   /// Return true if any explicit use operand on \p MI is defined by a
357   /// G_IMPLICIT_DEF.
358   bool matchAnyExplicitUseIsUndef(MachineInstr &MI);
359 
360   /// Return true if all register explicit use operands on \p MI are defined by
361   /// a G_IMPLICIT_DEF.
362   bool matchAllExplicitUsesAreUndef(MachineInstr &MI);
363 
364   /// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask.
365   bool matchUndefShuffleVectorMask(MachineInstr &MI);
366 
367   /// Return true if a G_STORE instruction \p MI is storing an undef value.
368   bool matchUndefStore(MachineInstr &MI);
369 
370   /// Return true if a G_SELECT instruction \p MI has an undef comparison.
371   bool matchUndefSelectCmp(MachineInstr &MI);
372 
373   /// Return true if a G_SELECT instruction \p MI has a constant comparison. If
374   /// true, \p OpIdx will store the operand index of the known selected value.
375   bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx);
376 
377   /// Replace an instruction with a G_FCONSTANT with value \p C.
378   bool replaceInstWithFConstant(MachineInstr &MI, double C);
379 
380   /// Replace an instruction with a G_CONSTANT with value \p C.
381   bool replaceInstWithConstant(MachineInstr &MI, int64_t C);
382 
383   /// Replace an instruction with a G_IMPLICIT_DEF.
384   bool replaceInstWithUndef(MachineInstr &MI);
385 
386   /// Delete \p MI and replace all of its uses with its \p OpIdx-th operand.
387   bool replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx);
388 
389   /// Delete \p MI and replace all of its uses with \p Replacement.
390   bool replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement);
391 
392   /// Return true if \p MOP1 and \p MOP2 are register operands are defined by
393   /// equivalent instructions.
394   bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2);
395 
396   /// Return true if \p MOP is defined by a G_CONSTANT with a value equal to
397   /// \p C.
398   bool matchConstantOp(const MachineOperand &MOP, int64_t C);
399 
400   /// Optimize (cond ? x : x) -> x
401   bool matchSelectSameVal(MachineInstr &MI);
402 
403   /// Optimize (x op x) -> x
404   bool matchBinOpSameVal(MachineInstr &MI);
405 
406   /// Check if operand \p OpIdx is zero.
407   bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx);
408 
409   /// Check if operand \p OpIdx is undef.
410   bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx);
411 
412   /// Check if operand \p OpIdx is known to be a power of 2.
413   bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI, unsigned OpIdx);
414 
415   /// Erase \p MI
416   bool eraseInst(MachineInstr &MI);
417 
418   /// Return true if MI is a G_ADD which can be simplified to a G_SUB.
419   bool matchSimplifyAddToSub(MachineInstr &MI,
420                              std::tuple<Register, Register> &MatchInfo);
421   bool applySimplifyAddToSub(MachineInstr &MI,
422                              std::tuple<Register, Register> &MatchInfo);
423 
424   /// Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
425   bool
426   matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI,
427                                        InstructionStepsMatchInfo &MatchInfo);
428 
429   /// Replace \p MI with a series of instructions described in \p MatchInfo.
430   bool applyBuildInstructionSteps(MachineInstr &MI,
431                                   InstructionStepsMatchInfo &MatchInfo);
432 
433   /// Match ashr (shl x, C), C -> sext_inreg (C)
434   bool matchAshrShlToSextInreg(MachineInstr &MI,
435                                std::tuple<Register, int64_t> &MatchInfo);
436   bool applyAshShlToSextInreg(MachineInstr &MI,
437                               std::tuple<Register, int64_t> &MatchInfo);
438   /// \return true if \p MI is a G_AND instruction whose operands are x and y
439   /// where x & y == x or x & y == y. (E.g., one of operands is all-ones value.)
440   ///
441   /// \param [in] MI - The G_AND instruction.
442   /// \param [out] Replacement - A register the G_AND should be replaced with on
443   /// success.
444   bool matchRedundantAnd(MachineInstr &MI, Register &Replacement);
445 
446   /// \return true if \p MI is a G_OR instruction whose operands are x and y
447   /// where x | y == x or x | y == y. (E.g., one of operands is all-zeros
448   /// value.)
449   ///
450   /// \param [in] MI - The G_OR instruction.
451   /// \param [out] Replacement - A register the G_OR should be replaced with on
452   /// success.
453   bool matchRedundantOr(MachineInstr &MI, Register &Replacement);
454 
455   /// \return true if \p MI is a G_SEXT_INREG that can be erased.
456   bool matchRedundantSExtInReg(MachineInstr &MI);
457 
458   /// Combine inverting a result of a compare into the opposite cond code.
459   bool matchNotCmp(MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate);
460   bool applyNotCmp(MachineInstr &MI, SmallVectorImpl<Register> &RegsToNegate);
461 
462   /// Fold (xor (and x, y), y) -> (and (not x), y)
463   ///{
464   bool matchXorOfAndWithSameReg(MachineInstr &MI,
465                                 std::pair<Register, Register> &MatchInfo);
466   bool applyXorOfAndWithSameReg(MachineInstr &MI,
467                                 std::pair<Register, Register> &MatchInfo);
468   ///}
469 
470   /// Combine G_PTR_ADD with nullptr to G_INTTOPTR
471   bool matchPtrAddZero(MachineInstr &MI);
472   bool applyPtrAddZero(MachineInstr &MI);
473 
474   /// Combine G_UREM x, (known power of 2) to an add and bitmasking.
475   bool applySimplifyURemByPow2(MachineInstr &MI);
476 
477   bool matchCombineInsertVecElts(MachineInstr &MI,
478                                  SmallVectorImpl<Register> &MatchInfo);
479 
480   bool applyCombineInsertVecElts(MachineInstr &MI,
481                              SmallVectorImpl<Register> &MatchInfo);
482 
483   /// Match expression trees of the form
484   ///
485   /// \code
486   ///  sN *a = ...
487   ///  sM val = a[0] | (a[1] << N) | (a[2] << 2N) | (a[3] << 3N) ...
488   /// \endcode
489   ///
490   /// And check if the tree can be replaced with a M-bit load + possibly a
491   /// bswap.
492   bool matchLoadOrCombine(MachineInstr &MI,
493                           std::function<void(MachineIRBuilder &)> &MatchInfo);
494 
495   bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI);
496   bool applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI);
497 
498   bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg);
499   void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg);
500 
501   bool matchExtractAllEltsFromBuildVector(
502       MachineInstr &MI,
503       SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo);
504   void applyExtractAllEltsFromBuildVector(
505       MachineInstr &MI,
506       SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo);
507 
508   /// Use a function which takes in a MachineIRBuilder to perform a combine.
509   bool applyBuildFn(MachineInstr &MI,
510                     std::function<void(MachineIRBuilder &)> &MatchInfo);
511   bool matchFunnelShiftToRotate(MachineInstr &MI);
512   void applyFunnelShiftToRotate(MachineInstr &MI);
513   bool matchRotateOutOfRange(MachineInstr &MI);
514   void applyRotateOutOfRange(MachineInstr &MI);
515 
516   /// \returns true if a G_ICMP instruction \p MI can be replaced with a true
517   /// or false constant based off of KnownBits information.
518   bool matchICmpToTrueFalseKnownBits(MachineInstr &MI, int64_t &MatchInfo);
519 
520   /// Try to transform \p MI by using all of the above
521   /// combine functions. Returns true if changed.
522   bool tryCombine(MachineInstr &MI);
523 
524 private:
525   // Memcpy family optimization helpers.
526   bool optimizeMemcpy(MachineInstr &MI, Register Dst, Register Src,
527                       unsigned KnownLen, Align DstAlign, Align SrcAlign,
528                       bool IsVolatile);
529   bool optimizeMemmove(MachineInstr &MI, Register Dst, Register Src,
530                        unsigned KnownLen, Align DstAlign, Align SrcAlign,
531                        bool IsVolatile);
532   bool optimizeMemset(MachineInstr &MI, Register Dst, Register Val,
533                       unsigned KnownLen, Align DstAlign, bool IsVolatile);
534 
535   /// Given a non-indexed load or store instruction \p MI, find an offset that
536   /// can be usefully and legally folded into it as a post-indexing operation.
537   ///
538   /// \returns true if a candidate is found.
539   bool findPostIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base,
540                               Register &Offset);
541 
542   /// Given a non-indexed load or store instruction \p MI, find an offset that
543   /// can be usefully and legally folded into it as a pre-indexing operation.
544   ///
545   /// \returns true if a candidate is found.
546   bool findPreIndexCandidate(MachineInstr &MI, Register &Addr, Register &Base,
547                              Register &Offset);
548 
549   /// Helper function for matchLoadOrCombine. Searches for Registers
550   /// which may have been produced by a load instruction + some arithmetic.
551   ///
552   /// \param [in] Root - The search root.
553   ///
554   /// \returns The Registers found during the search.
555   Optional<SmallVector<Register, 8>>
556   findCandidatesForLoadOrCombine(const MachineInstr *Root) const;
557 
558   /// Helper function for matchLoadOrCombine.
559   ///
560   /// Checks if every register in \p RegsToVisit is defined by a load
561   /// instruction + some arithmetic.
562   ///
563   /// \param [out] MemOffset2Idx - Maps the byte positions each load ends up
564   /// at to the index of the load.
565   /// \param [in] MemSizeInBits - The number of bits each load should produce.
566   ///
567   /// \returns The lowest-index load found and the lowest index on success.
568   Optional<std::pair<MachineInstr *, int64_t>> findLoadOffsetsForLoadOrCombine(
569       SmallDenseMap<int64_t, int64_t, 8> &MemOffset2Idx,
570       const SmallVector<Register, 8> &RegsToVisit,
571       const unsigned MemSizeInBits);
572 };
573 } // namespace llvm
574 
575 #endif
576