LLVM 22.0.0git
CombinerHelper.h
Go to the documentation of this file.
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/DenseMap.h"
26#include "llvm/IR/InstrTypes.h"
27#include <functional>
28
29namespace llvm {
30
32class APInt;
33class ConstantFP;
34class GPtrAdd;
35class GZExtLoad;
39class MachineInstr;
40class MachineOperand;
43class LegalizerInfo;
44struct LegalityQuery;
45class RegisterBank;
47class TargetLowering;
49
51 LLT Ty; // The result type of the extend.
52 unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT
54};
55
60 bool RematOffset = false; // True if Offset is a constant that needs to be
61 // rematerialized before the new load/store.
62 bool IsPre = false;
63};
64
66 int64_t Imm;
69 unsigned Flags;
70};
71
74 int64_t Imm;
75};
76
83
92
93using BuildFnTy = std::function<void(MachineIRBuilder &)>;
94
96 SmallVector<std::function<void(MachineInstrBuilder &)>, 4>;
98 unsigned Opcode = 0; /// The opcode for the produced instruction.
99 OperandBuildSteps OperandFns; /// Operands to be added to the instruction.
103};
104
106 /// Describes instructions to be built during a combine.
110 std::initializer_list<InstructionBuildSteps> InstrsToBuild)
112};
113
115protected:
125
126public:
128 bool IsPreLegalize, GISelValueTracking *VT = nullptr,
129 MachineDominatorTree *MDT = nullptr,
130 const LegalizerInfo *LI = nullptr);
131
133
135 return Builder;
136 }
137
138 const TargetLowering &getTargetLowering() const;
139
140 const MachineFunction &getMachineFunction() const;
141
142 const DataLayout &getDataLayout() const;
143
144 LLVMContext &getContext() const;
145
146 /// \returns true if the combiner is running pre-legalization.
147 bool isPreLegalize() const;
148
149 /// \returns true if \p Query is legal on the target.
150 bool isLegal(const LegalityQuery &Query) const;
151
152 /// \return true if the combine is running prior to legalization, or if \p
153 /// Query is legal on the target.
154 bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const;
155
156 /// \return true if \p Query is legal on the target, or if \p Query will
157 /// perform WidenScalar action on the target.
158 bool isLegalOrHasWidenScalar(const LegalityQuery &Query) const;
159
160 /// \return true if the combine is running prior to legalization, or if \p Ty
161 /// is a legal integer constant type on the target.
162 bool isConstantLegalOrBeforeLegalizer(const LLT Ty) const;
163
164 /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes
165 void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const;
166
167 /// Replace a single register operand with a new register and inform the
168 /// observer of the changes.
170 Register ToReg) const;
171
172 /// Replace the opcode in instruction with a new opcode and inform the
173 /// observer of the changes.
174 void replaceOpcodeWith(MachineInstr &FromMI, unsigned ToOpcode) const;
175
176 /// Get the register bank of \p Reg.
177 /// If Reg has not been assigned a register, a register class,
178 /// or a register bank, then this returns nullptr.
179 ///
180 /// \pre Reg.isValid()
181 const RegisterBank *getRegBank(Register Reg) const;
182
183 /// Set the register bank of \p Reg.
184 /// Does nothing if the RegBank is null.
185 /// This is the counterpart to getRegBank.
186 void setRegBank(Register Reg, const RegisterBank *RegBank) const;
187
188 /// If \p MI is COPY, try to combine it.
189 /// Returns true if MI changed.
190 bool tryCombineCopy(MachineInstr &MI) const;
191 bool matchCombineCopy(MachineInstr &MI) const;
192 void applyCombineCopy(MachineInstr &MI) const;
193
194 /// Returns true if \p DefMI precedes \p UseMI or they are the same
195 /// instruction. Both must be in the same basic block.
196 bool isPredecessor(const MachineInstr &DefMI,
197 const MachineInstr &UseMI) const;
198
199 /// Returns true if \p DefMI dominates \p UseMI. By definition an
200 /// instruction dominates itself.
201 ///
202 /// If we haven't been provided with a MachineDominatorTree during
203 /// construction, this function returns a conservative result that tracks just
204 /// a single basic block.
205 bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI) const;
206
207 /// If \p MI is extend that consumes the result of a load, try to combine it.
208 /// Returns true if MI changed.
211 PreferredTuple &MatchInfo) const;
213 PreferredTuple &MatchInfo) const;
214
215 /// Match (and (load x), mask) -> zextload x
217 BuildFnTy &MatchInfo) const;
218
219 /// Combine a G_EXTRACT_VECTOR_ELT of a load into a narrowed
220 /// load.
222 BuildFnTy &MatchInfo) const;
223
225 IndexedLoadStoreMatchInfo &MatchInfo) const;
227 IndexedLoadStoreMatchInfo &MatchInfo) const;
228
231
232 /// Match sext_inreg(load p), imm -> sextload p
234 std::tuple<Register, unsigned> &MatchInfo) const;
236 std::tuple<Register, unsigned> &MatchInfo) const;
237
238 /// Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM
239 /// when their source operands are identical.
240 bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const;
241 void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const;
242
243 /// If a brcond's true block is not the fallthrough, make it so by inverting
244 /// the condition and swapping operands.
246 MachineInstr *&BrCond) const;
248 MachineInstr *&BrCond) const;
249
250 /// If \p MI is G_CONCAT_VECTORS, try to combine it.
251 /// Returns true if MI changed.
252 /// Right now, we support:
253 /// - concat_vector(undef, undef) => undef
254 /// - concat_vector(build_vector(A, B), build_vector(C, D)) =>
255 /// build_vector(A, B, C, D)
256 /// ==========================================================
257 /// Check if the G_CONCAT_VECTORS \p MI is undef or if it
258 /// can be flattened into a build_vector.
259 /// In the first case \p Ops will be empty
260 /// In the second case \p Ops will contain the operands
261 /// needed to produce the flattened build_vector.
262 ///
263 /// \pre MI.getOpcode() == G_CONCAT_VECTORS.
266 /// Replace \p MI with a flattened build_vector with \p Ops
267 /// or an implicit_def if \p Ops is empty.
270
273 /// Replace \p MI with a flattened build_vector with \p Ops
274 /// or an implicit_def if \p Ops is empty.
277
278 /// Replace \p MI with a build_vector.
280
281 /// Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
282 /// Returns true if MI changed.
283 ///
284 /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
286 /// Check if the G_SHUFFLE_VECTOR \p MI can be replaced by a
287 /// concat_vectors.
288 /// \p Ops will contain the operands needed to produce the flattened
289 /// concat_vectors.
290 ///
291 /// \pre MI.getOpcode() == G_SHUFFLE_VECTOR.
294 /// Replace \p MI with a concat_vectors with \p Ops.
296 const ArrayRef<Register> Ops) const;
297
298 /// Optimize memcpy intrinsics et al, e.g. constant len calls.
299 /// /p MaxLen if non-zero specifies the max length of a mem libcall to inline.
300 ///
301 /// For example (pre-indexed):
302 ///
303 /// $addr = G_PTR_ADD $base, $offset
304 /// [...]
305 /// $val = G_LOAD $addr
306 /// [...]
307 /// $whatever = COPY $addr
308 ///
309 /// -->
310 ///
311 /// $val, $addr = G_INDEXED_LOAD $base, $offset, 1 (IsPre)
312 /// [...]
313 /// $whatever = COPY $addr
314 ///
315 /// or (post-indexed):
316 ///
317 /// G_STORE $val, $base
318 /// [...]
319 /// $addr = G_PTR_ADD $base, $offset
320 /// [...]
321 /// $whatever = COPY $addr
322 ///
323 /// -->
324 ///
325 /// $addr = G_INDEXED_STORE $val, $base, $offset
326 /// [...]
327 /// $whatever = COPY $addr
328 bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0) const;
329
330 bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const;
331 void applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const;
332
333 /// Fold (shift (shift base, x), y) -> (shift base (x+y))
334 bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const;
335 void applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const;
336
337 /// If we have a shift-by-constant of a bitwise logic op that itself has a
338 /// shift-by-constant operand with identical opcode, we may be able to convert
339 /// that into 2 independent shifts followed by the logic op.
341 ShiftOfShiftedLogic &MatchInfo) const;
343 ShiftOfShiftedLogic &MatchInfo) const;
344
345 bool matchCommuteShift(MachineInstr &MI, BuildFnTy &MatchInfo) const;
346
347 /// Fold (lshr (trunc (lshr x, C1)), C2) -> trunc (shift x, (C1 + C2))
349 MachineInstr &ShiftMI) const;
351 LshrOfTruncOfLshr &MatchInfo) const;
352
353 /// Transform a multiply by a power-of-2 value to a left shift.
354 bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const;
355 void applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const;
356
357 // Transform a G_SUB with constant on the RHS to G_ADD.
358 bool matchCombineSubToAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
359
360 // Transform a G_SHL with an extended source into a narrower shift if
361 // possible.
363 RegisterImmPair &MatchData) const;
365 const RegisterImmPair &MatchData) const;
366
367 /// Fold away a merge of an unmerge of the corresponding values.
368 bool matchCombineMergeUnmerge(MachineInstr &MI, Register &MatchInfo) const;
369
370 /// Reduce a shift by a constant to an unmerge and a shift on a half sized
371 /// type. This will not produce a shift smaller than \p TargetShiftSize.
372 bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize,
373 unsigned &ShiftVal) const;
375 const unsigned &ShiftVal) const;
377 unsigned TargetShiftAmount) const;
378
379 /// Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z.
381 MachineInstr &MI, SmallVectorImpl<Register> &Operands) const;
383 MachineInstr &MI, SmallVectorImpl<Register> &Operands) const;
384
385 /// Transform G_UNMERGE Constant -> Constant1, Constant2, ...
387 SmallVectorImpl<APInt> &Csts) const;
389 SmallVectorImpl<APInt> &Csts) const;
390
391 /// Transform G_UNMERGE G_IMPLICIT_DEF -> G_IMPLICIT_DEF, G_IMPLICIT_DEF, ...
394 std::function<void(MachineIRBuilder &)> &MatchInfo) const;
395
396 /// Transform X, Y<dead> = G_UNMERGE Z -> X = G_TRUNC Z.
399
400 /// Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0
403
404 /// Transform fp_instr(cst) to constant result of the fp operation.
406 const ConstantFP *Cst) const;
407
408 /// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space.
411
412 /// Transform PtrToInt(IntToPtr(x)) to x.
414
415 /// Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y)
416 /// Transform G_ADD y, (G_PTRTOINT x) -> G_PTRTOINT (G_PTR_ADD x, y)
417 bool
419 std::pair<Register, bool> &PtrRegAndCommute) const;
420 void
422 std::pair<Register, bool> &PtrRegAndCommute) const;
423
424 // Transform G_PTR_ADD (G_PTRTOINT C1), C2 -> C1 + C2
427
428 /// Transform anyext(trunc(x)) to x.
430
431 /// Transform zext(trunc(x)) to x.
433
434 /// Transform trunc (shl x, K) to shl (trunc x), K
435 /// if K < VT.getScalarSizeInBits().
436 ///
437 /// Transforms trunc ([al]shr x, K) to (trunc ([al]shr (MidVT (trunc x)), K))
438 /// if K <= (MidVT.getScalarSizeInBits() - VT.getScalarSizeInBits())
439 /// MidVT is obtained by finding a legal type between the trunc's src and dst
440 /// types.
441 bool
443 std::pair<MachineInstr *, LLT> &MatchInfo) const;
444 void
446 std::pair<MachineInstr *, LLT> &MatchInfo) const;
447
448 /// Return true if any explicit use operand on \p MI is defined by a
449 /// G_IMPLICIT_DEF.
451
452 /// Return true if all register explicit use operands on \p MI are defined by
453 /// a G_IMPLICIT_DEF.
455
456 /// Return true if a G_SHUFFLE_VECTOR instruction \p MI has an undef mask.
458
459 /// Return true if a G_STORE instruction \p MI is storing an undef value.
460 bool matchUndefStore(MachineInstr &MI) const;
461
462 /// Return true if a G_SELECT instruction \p MI has an undef comparison.
464
465 /// Return true if a G_{EXTRACT,INSERT}_VECTOR_ELT has an out of range index.
467
468 /// Return true if a G_SELECT instruction \p MI has a constant comparison. If
469 /// true, \p OpIdx will store the operand index of the known selected value.
470 bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx) const;
471
472 /// Replace an instruction with a G_FCONSTANT with value \p C.
473 void replaceInstWithFConstant(MachineInstr &MI, double C) const;
474
475 /// Replace an instruction with an G_FCONSTANT with value \p CFP.
477
478 /// Replace an instruction with a G_CONSTANT with value \p C.
479 void replaceInstWithConstant(MachineInstr &MI, int64_t C) const;
480
481 /// Replace an instruction with a G_CONSTANT with value \p C.
483
484 /// Replace an instruction with a G_IMPLICIT_DEF.
486
487 /// Delete \p MI and replace all of its uses with its \p OpIdx-th operand.
489
490 /// Delete \p MI and replace all of its uses with \p Replacement.
492 Register Replacement) const;
493
494 /// @brief Replaces the shift amount in \p MI with ShiftAmt % BW
495 /// @param MI
497
498 /// Return true if \p MOP1 and \p MOP2 are register operands are defined by
499 /// equivalent instructions.
500 bool matchEqualDefs(const MachineOperand &MOP1,
501 const MachineOperand &MOP2) const;
502
503 /// Return true if \p MOP is defined by a G_CONSTANT or splat with a value equal to
504 /// \p C.
505 bool matchConstantOp(const MachineOperand &MOP, int64_t C) const;
506
507 /// Return true if \p MOP is defined by a G_FCONSTANT or splat with a value exactly
508 /// equal to \p C.
509 bool matchConstantFPOp(const MachineOperand &MOP, double C) const;
510
511 /// @brief Checks if constant at \p ConstIdx is larger than \p MI 's bitwidth
512 /// @param ConstIdx Index of the constant
513 bool matchConstantLargerBitWidth(MachineInstr &MI, unsigned ConstIdx) const;
514
515 /// Optimize (cond ? x : x) -> x
517
518 /// Optimize (x op x) -> x
519 bool matchBinOpSameVal(MachineInstr &MI) const;
520
521 /// Check if operand \p OpIdx is zero.
522 bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx) const;
523
524 /// Check if operand \p OpIdx is undef.
525 bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const;
526
527 /// Check if operand \p OpIdx is known to be a power of 2.
529 unsigned OpIdx) const;
530
531 /// Erase \p MI
532 void eraseInst(MachineInstr &MI) const;
533
534 /// Return true if MI is a G_ADD which can be simplified to a G_SUB.
536 std::tuple<Register, Register> &MatchInfo) const;
538 std::tuple<Register, Register> &MatchInfo) const;
539
540 /// Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
542 MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const;
543
544 /// Replace \p MI with a series of instructions described in \p MatchInfo.
546 InstructionStepsMatchInfo &MatchInfo) const;
547
548 /// Match ashr (shl x, C), C -> sext_inreg (C)
550 std::tuple<Register, int64_t> &MatchInfo) const;
552 std::tuple<Register, int64_t> &MatchInfo) const;
553
554 /// Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0
555 bool matchOverlappingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
556
557 /// \return true if \p MI is a G_AND instruction whose operands are x and y
558 /// where x & y == x or x & y == y. (E.g., one of operands is all-ones value.)
559 ///
560 /// \param [in] MI - The G_AND instruction.
561 /// \param [out] Replacement - A register the G_AND should be replaced with on
562 /// success.
563 bool matchRedundantAnd(MachineInstr &MI, Register &Replacement) const;
564
565 /// \return true if \p MI is a G_OR instruction whose operands are x and y
566 /// where x | y == x or x | y == y. (E.g., one of operands is all-zeros
567 /// value.)
568 ///
569 /// \param [in] MI - The G_OR instruction.
570 /// \param [out] Replacement - A register the G_OR should be replaced with on
571 /// success.
572 bool matchRedundantOr(MachineInstr &MI, Register &Replacement) const;
573
574 /// \return true if \p MI is a G_SEXT_INREG that can be erased.
576
577 /// Combine inverting a result of a compare into the opposite cond code.
579 SmallVectorImpl<Register> &RegsToNegate) const;
581 SmallVectorImpl<Register> &RegsToNegate) const;
582
583 /// Fold (xor (and x, y), y) -> (and (not x), y)
584 ///{
586 std::pair<Register, Register> &MatchInfo) const;
588 std::pair<Register, Register> &MatchInfo) const;
589 ///}
590
591 /// Combine G_PTR_ADD with nullptr to G_INTTOPTR
592 bool matchPtrAddZero(MachineInstr &MI) const;
593 void applyPtrAddZero(MachineInstr &MI) const;
594
595 /// Combine G_UREM x, (known power of 2) to an add and bitmasking.
597
598 /// Push a binary operator through a select on constants.
599 ///
600 /// binop (select cond, K0, K1), K2 ->
601 /// select cond, (binop K0, K2), (binop K1, K2)
602 bool matchFoldBinOpIntoSelect(MachineInstr &MI, unsigned &SelectOpNo) const;
604 const unsigned &SelectOpNo) const;
605
607 SmallVectorImpl<Register> &MatchInfo) const;
608
610 SmallVectorImpl<Register> &MatchInfo) const;
611
612 /// Match expression trees of the form
613 ///
614 /// \code
615 /// sN *a = ...
616 /// sM val = a[0] | (a[1] << N) | (a[2] << 2N) | (a[3] << 3N) ...
617 /// \endcode
618 ///
619 /// And check if the tree can be replaced with a M-bit load + possibly a
620 /// bswap.
621 bool matchLoadOrCombine(MachineInstr &MI, BuildFnTy &MatchInfo) const;
622
625
628
631 SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo) const;
634 SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo) const;
635
636 /// Use a function which takes in a MachineIRBuilder to perform a combine.
637 /// By default, it erases the instruction \p MI from the function.
638 void applyBuildFn(MachineInstr &MI, BuildFnTy &MatchInfo) const;
639 /// Use a function which takes in a MachineIRBuilder to perform a combine.
640 /// This variant does not erase \p MI after calling the build function.
641 void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo) const;
642
643 bool matchOrShiftToFunnelShift(MachineInstr &MI, bool AllowScalarConstants,
644 BuildFnTy &MatchInfo) const;
649
650 bool matchUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const;
651 void applyUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const;
652
653 /// \returns true if a G_ICMP instruction \p MI can be replaced with a true
654 /// or false constant based off of KnownBits information.
656 int64_t &MatchInfo) const;
657
658 /// \returns true if a G_ICMP \p MI can be replaced with its LHS based off of
659 /// KnownBits information.
660 bool matchICmpToLHSKnownBits(MachineInstr &MI, BuildFnTy &MatchInfo) const;
661
662 /// \returns true if (and (or x, c1), c2) can be replaced with (and x, c2)
663 bool matchAndOrDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const;
664
666 BuildFnTy &MatchInfo) const;
667 /// Match: and (lshr x, cst), mask -> ubfx x, cst, width
669 BuildFnTy &MatchInfo) const;
670
671 /// Match: shr (shl x, n), k -> sbfx/ubfx x, pos, width
673 BuildFnTy &MatchInfo) const;
674
675 /// Match: shr (and x, n), k -> ubfx x, pos, width
677 BuildFnTy &MatchInfo) const;
678
679 // Helpers for reassociation:
681 BuildFnTy &MatchInfo) const;
684 BuildFnTy &MatchInfo) const;
687 BuildFnTy &MatchInfo) const;
688 /// Reassociate pointer calculations with G_ADD involved, to allow better
689 /// addressing mode usage.
690 bool matchReassocPtrAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
691
692 /// Try to reassociate to reassociate operands of a commutative binop.
693 bool tryReassocBinOp(unsigned Opc, Register DstReg, Register Op0,
694 Register Op1, BuildFnTy &MatchInfo) const;
695 /// Reassociate commutative binary operations like G_ADD.
696 bool matchReassocCommBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const;
697
698 /// Do constant folding when opportunities are exposed after MIR building.
699 bool matchConstantFoldCastOp(MachineInstr &MI, APInt &MatchInfo) const;
700
701 /// Do constant folding when opportunities are exposed after MIR building.
702 bool matchConstantFoldBinOp(MachineInstr &MI, APInt &MatchInfo) const;
703
704 /// Do constant FP folding when opportunities are exposed after MIR building.
705 bool matchConstantFoldFPBinOp(MachineInstr &MI, ConstantFP *&MatchInfo) const;
706
707 /// Constant fold G_FMA/G_FMAD.
708 bool matchConstantFoldFMA(MachineInstr &MI, ConstantFP *&MatchInfo) const;
709
710 /// \returns true if it is possible to narrow the width of a scalar binop
711 /// feeding a G_AND instruction \p MI.
712 bool matchNarrowBinopFeedingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
713
714 /// Given an G_UDIV \p MI or G_UREM \p MI expressing a divide by constant,
715 /// return an expression that implements it by multiplying by a magic number.
716 /// Ref: "Hacker's Delight" or "The PowerPC Compiler Writer's Guide".
718 /// Combine G_UDIV or G_UREM by constant into a multiply by magic constant.
721
722 /// Given an G_SDIV \p MI or G_SREM \p MI expressing a signed divide by
723 /// constant, return an expression that implements it by multiplying by a
724 /// magic number. Ref: "Hacker's Delight" or "The PowerPC Compiler Writer's
725 /// Guide".
727 /// Combine G_SDIV or G_SREM by constant into a multiply by magic constant.
730
731 /// Given an G_SDIV \p MI expressing a signed divided by a pow2 constant,
732 /// return expressions that implements it by shifting.
733 bool matchDivByPow2(MachineInstr &MI, bool IsSigned) const;
734 void applySDivByPow2(MachineInstr &MI) const;
735 /// Given an G_UDIV \p MI expressing an unsigned divided by a pow2 constant,
736 /// return expressions that implements it by shifting.
737 void applyUDivByPow2(MachineInstr &MI) const;
738
739 // G_UMULH x, (1 << c)) -> x >> (bitwidth - c)
740 bool matchUMulHToLShr(MachineInstr &MI) const;
741 void applyUMulHToLShr(MachineInstr &MI) const;
742
743 // Combine trunc(smin(smax(x, C1), C2)) -> truncssat_s(x)
744 // or trunc(smax(smin(x, C2), C1)) -> truncssat_s(x).
745 bool matchTruncSSatS(MachineInstr &MI, Register &MatchInfo) const;
746 void applyTruncSSatS(MachineInstr &MI, Register &MatchInfo) const;
747
748 // Combine trunc(smin(smax(x, 0), C)) -> truncssat_u(x)
749 // or trunc(smax(smin(x, C), 0)) -> truncssat_u(x)
750 // or trunc(umin(smax(x, 0), C)) -> truncssat_u(x)
751 bool matchTruncSSatU(MachineInstr &MI, Register &MatchInfo) const;
752 void applyTruncSSatU(MachineInstr &MI, Register &MatchInfo) const;
753
754 // Combine trunc(umin(x, C)) -> truncusat_u(x).
755 bool matchTruncUSatU(MachineInstr &MI, MachineInstr &MinMI) const;
756
757 // Combine truncusat_u(fptoui(x)) -> fptoui_sat(x)
759
760 /// Try to transform \p MI by using all of the above
761 /// combine functions. Returns true if changed.
763
764 /// Emit loads and stores that perform the given memcpy.
765 /// Assumes \p MI is a G_MEMCPY_INLINE
766 /// TODO: implement dynamically sized inline memcpy,
767 /// and rename: s/bool tryEmit/void emit/
769
770 /// Match:
771 /// (G_UMULO x, 2) -> (G_UADDO x, x)
772 /// (G_SMULO x, 2) -> (G_SADDO x, x)
773 bool matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo) const;
774
775 /// Match:
776 /// (G_*MULO x, 0) -> 0 + no carry out
777 bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) const;
778
779 /// Match:
780 /// (G_*ADDE x, y, 0) -> (G_*ADDO x, y)
781 /// (G_*SUBE x, y, 0) -> (G_*SUBO x, y)
782 bool matchAddEToAddO(MachineInstr &MI, BuildFnTy &MatchInfo) const;
783
784 /// Transform (fadd x, fneg(y)) -> (fsub x, y)
785 /// (fadd fneg(x), y) -> (fsub y, x)
786 /// (fsub x, fneg(y)) -> (fadd x, y)
787 /// (fmul fneg(x), fneg(y)) -> (fmul x, y)
788 /// (fdiv fneg(x), fneg(y)) -> (fdiv x, y)
789 /// (fmad fneg(x), fneg(y), z) -> (fmad x, y, z)
790 /// (fma fneg(x), fneg(y), z) -> (fma x, y, z)
791 bool matchRedundantNegOperands(MachineInstr &MI, BuildFnTy &MatchInfo) const;
792
793 bool matchFsubToFneg(MachineInstr &MI, Register &MatchInfo) const;
794 void applyFsubToFneg(MachineInstr &MI, Register &MatchInfo) const;
795
796 bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally,
797 bool &HasFMAD, bool &Aggressive,
798 bool CanReassociate = false) const;
799
800 /// Transform (fadd (fmul x, y), z) -> (fma x, y, z)
801 /// (fadd (fmul x, y), z) -> (fmad x, y, z)
803 BuildFnTy &MatchInfo) const;
804
805 /// Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z)
806 /// (fadd (fpext (fmul x, y)), z) -> (fmad (fpext x), (fpext y), z)
808 BuildFnTy &MatchInfo) const;
809
810 /// Transform (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z))
811 /// (fadd (fmad x, y, (fmul u, v)), z) -> (fmad x, y, (fmad u, v, z))
813 BuildFnTy &MatchInfo) const;
814
815 // Transform (fadd (fma x, y, (fpext (fmul u, v))), z)
816 // -> (fma x, y, (fma (fpext u), (fpext v), z))
817 // (fadd (fmad x, y, (fpext (fmul u, v))), z)
818 // -> (fmad x, y, (fmad (fpext u), (fpext v), z))
819 bool
821 BuildFnTy &MatchInfo) const;
822
823 /// Transform (fsub (fmul x, y), z) -> (fma x, y, -z)
824 /// (fsub (fmul x, y), z) -> (fmad x, y, -z)
826 BuildFnTy &MatchInfo) const;
827
828 /// Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z))
829 /// (fsub (fneg (fmul, x, y)), z) -> (fmad (fneg x), y, (fneg z))
831 BuildFnTy &MatchInfo) const;
832
833 /// Transform (fsub (fpext (fmul x, y)), z)
834 /// -> (fma (fpext x), (fpext y), (fneg z))
835 /// (fsub (fpext (fmul x, y)), z)
836 /// -> (fmad (fpext x), (fpext y), (fneg z))
838 BuildFnTy &MatchInfo) const;
839
840 /// Transform (fsub (fpext (fneg (fmul x, y))), z)
841 /// -> (fneg (fma (fpext x), (fpext y), z))
842 /// (fsub (fpext (fneg (fmul x, y))), z)
843 /// -> (fneg (fmad (fpext x), (fpext y), z))
845 BuildFnTy &MatchInfo) const;
846
847 bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info) const;
848
850 SmallVector<MachineInstr *> &MatchInfo) const;
852
853 /// Transform G_ADD(x, G_SUB(y, x)) to y.
854 /// Transform G_ADD(G_SUB(y, x), x) to y.
855 bool matchAddSubSameReg(MachineInstr &MI, Register &Src) const;
856
858 Register &MatchInfo) const;
859 bool matchTruncBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const;
861 Register &MatchInfo) const;
862
863 /// Transform:
864 /// (x + y) - y -> x
865 /// (x + y) - x -> y
866 /// x - (y + x) -> 0 - y
867 /// x - (x + z) -> 0 - z
868 bool matchSubAddSameReg(MachineInstr &MI, BuildFnTy &MatchInfo) const;
869
870 /// \returns true if it is possible to simplify a select instruction \p MI
871 /// to a min/max instruction of some sort.
873 BuildFnTy &MatchInfo) const;
874
875 /// Transform:
876 /// (X + Y) == X -> Y == 0
877 /// (X - Y) == X -> Y == 0
878 /// (X ^ Y) == X -> Y == 0
879 /// (X + Y) != X -> Y != 0
880 /// (X - Y) != X -> Y != 0
881 /// (X ^ Y) != X -> Y != 0
883 BuildFnTy &MatchInfo) const;
884
885 /// Match shifts greater or equal to the range (the bitwidth of the result
886 /// datatype, or the effective bitwidth of the source value).
888 std::optional<int64_t> &MatchInfo) const;
889
890 /// Match constant LHS ops that should be commuted.
892
893 /// Combine sext of trunc.
894 bool matchSextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
895
896 /// Combine zext of trunc.
897 bool matchZextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
898
899 /// Combine zext nneg to sext.
900 bool matchNonNegZext(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
901
902 /// Match constant LHS FP ops that should be commuted.
904
905 // Given a binop \p MI, commute operands 1 and 2.
907
908 /// Combine select to integer min/max.
909 bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
910
911 /// Tranform (neg (min/max x, (neg x))) into (max/min x, (neg x)).
912 bool matchSimplifyNegMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const;
913
914 /// Combine selects.
915 bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const;
916
917 /// Combine ands.
918 bool matchAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const;
919
920 /// Combine ors.
921 bool matchOr(MachineInstr &MI, BuildFnTy &MatchInfo) const;
922
923 /// trunc (binop X, C) --> binop (trunc X, trunc C).
924 bool matchNarrowBinop(const MachineInstr &TruncMI,
925 const MachineInstr &BinopMI,
926 BuildFnTy &MatchInfo) const;
927
928 bool matchCastOfInteger(const MachineInstr &CastMI, APInt &MatchInfo) const;
929
930 /// Combine addos.
931 bool matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) const;
932
933 /// Combine extract vector element.
934 bool matchExtractVectorElement(MachineInstr &MI, BuildFnTy &MatchInfo) const;
935
936 /// Combine extract vector element with a build vector on the vector register.
938 const MachineInstr &MI2,
939 BuildFnTy &MatchInfo) const;
940
941 /// Combine extract vector element with a build vector trunc on the vector
942 /// register.
943 bool
945 BuildFnTy &MatchInfo) const;
946
947 /// Combine extract vector element with a shuffle vector on the vector
948 /// register.
950 const MachineInstr &MI2,
951 BuildFnTy &MatchInfo) const;
952
953 /// Combine extract vector element with a insert vector element on the vector
954 /// register and different indices.
955 bool
957 BuildFnTy &MatchInfo) const;
958
959 /// Remove references to rhs if it is undef
960 bool matchShuffleUndefRHS(MachineInstr &MI, BuildFnTy &MatchInfo) const;
961
962 /// Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not
963 /// reference a.
964 bool matchShuffleDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const;
965
966 /// Use a function which takes in a MachineIRBuilder to perform a combine.
967 /// By default, it erases the instruction def'd on \p MO from the function.
968 void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
969
970 /// Match FPOWI if it's safe to extend it into a series of multiplications.
971 bool matchFPowIExpansion(MachineInstr &MI, int64_t Exponent) const;
972
973 /// Expands FPOWI into a series of multiplications and a division if the
974 /// exponent is negative.
975 void applyExpandFPowI(MachineInstr &MI, int64_t Exponent) const;
976
977 /// Combine insert vector element OOB.
979 BuildFnTy &MatchInfo) const;
980
982 BuildFnTy &MatchInfo) const;
983
984 bool matchAddOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
985
986 bool matchMulOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
987
988 bool matchSubOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
989
990 bool matchShlOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
991
992 /// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x).
993 bool matchTruncateOfExt(const MachineInstr &Root, const MachineInstr &ExtMI,
994 BuildFnTy &MatchInfo) const;
995
996 bool matchCastOfSelect(const MachineInstr &Cast, const MachineInstr &SelectMI,
997 BuildFnTy &MatchInfo) const;
999 BuildFnTy &MatchInfo) const;
1000
1002 BuildFnTy &MatchInfo) const;
1003
1005 BuildFnTy &MatchInfo) const;
1006
1008 BuildFnTy &MatchInfo) const;
1009
1010 // fold ((A-C1)+C2) -> (A+(C2-C1))
1012 BuildFnTy &MatchInfo) const;
1013
1014 bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
1015 BuildFnTy &MatchInfo) const;
1016
1017 bool matchCastOfBuildVector(const MachineInstr &CastMI,
1018 const MachineInstr &BVMI,
1019 BuildFnTy &MatchInfo) const;
1020
1022 BuildFnTy &MatchInfo) const;
1024 BuildFnTy &MatchInfo) const;
1025
1026 // unmerge_values(anyext(build vector)) -> build vector(anyext)
1028 BuildFnTy &MatchInfo) const;
1029
1030 // merge_values(_, undef) -> anyext
1031 bool matchMergeXAndUndef(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
1032
1033 // merge_values(_, zero) -> zext
1034 bool matchMergeXAndZero(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
1035
1036 // overflow sub
1037 bool matchSuboCarryOut(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
1038
1039 // (sext_inreg (sext_inreg x, K0), K1)
1041 BuildFnTy &MatchInfo) const;
1042
1043private:
1044 /// Checks for legality of an indexed variant of \p LdSt.
1045 bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
1046 /// Given a non-indexed load or store instruction \p MI, find an offset that
1047 /// can be usefully and legally folded into it as a post-indexing operation.
1048 ///
1049 /// \returns true if a candidate is found.
1050 bool findPostIndexCandidate(GLoadStore &MI, Register &Addr, Register &Base,
1051 Register &Offset, bool &RematOffset) const;
1052
1053 /// Given a non-indexed load or store instruction \p MI, find an offset that
1054 /// can be usefully and legally folded into it as a pre-indexing operation.
1055 ///
1056 /// \returns true if a candidate is found.
1057 bool findPreIndexCandidate(GLoadStore &MI, Register &Addr, Register &Base,
1058 Register &Offset) const;
1059
1060 /// Helper function for matchLoadOrCombine. Searches for Registers
1061 /// which may have been produced by a load instruction + some arithmetic.
1062 ///
1063 /// \param [in] Root - The search root.
1064 ///
1065 /// \returns The Registers found during the search.
1066 std::optional<SmallVector<Register, 8>>
1067 findCandidatesForLoadOrCombine(const MachineInstr *Root) const;
1068
1069 /// Helper function for matchLoadOrCombine.
1070 ///
1071 /// Checks if every register in \p RegsToVisit is defined by a load
1072 /// instruction + some arithmetic.
1073 ///
1074 /// \param [out] MemOffset2Idx - Maps the byte positions each load ends up
1075 /// at to the index of the load.
1076 /// \param [in] MemSizeInBits - The number of bits each load should produce.
1077 ///
1078 /// \returns On success, a 3-tuple containing lowest-index load found, the
1079 /// lowest index, and the last load in the sequence.
1080 std::optional<std::tuple<GZExtLoad *, int64_t, GZExtLoad *>>
1081 findLoadOffsetsForLoadOrCombine(
1083 const SmallVector<Register, 8> &RegsToVisit,
1084 const unsigned MemSizeInBits) const;
1085
1086 /// Examines the G_PTR_ADD instruction \p PtrAdd and determines if performing
1087 /// a re-association of its operands would break an existing legal addressing
1088 /// mode that the address computation currently represents.
1089 bool reassociationCanBreakAddressingModePattern(MachineInstr &PtrAdd) const;
1090
1091 /// Behavior when a floating point min/max is given one NaN and one
1092 /// non-NaN as input.
1093 enum class SelectPatternNaNBehaviour {
1094 NOT_APPLICABLE = 0, /// NaN behavior not applicable.
1095 RETURNS_NAN, /// Given one NaN input, returns the NaN.
1096 RETURNS_OTHER, /// Given one NaN input, returns the non-NaN.
1097 RETURNS_ANY /// Given one NaN input, can return either (or both operands are
1098 /// known non-NaN.)
1099 };
1100
1101 /// \returns which of \p LHS and \p RHS would be the result of a non-equality
1102 /// floating point comparison where one of \p LHS and \p RHS may be NaN.
1103 ///
1104 /// If both \p LHS and \p RHS may be NaN, returns
1105 /// SelectPatternNaNBehaviour::NOT_APPLICABLE.
1106 SelectPatternNaNBehaviour
1107 computeRetValAgainstNaN(Register LHS, Register RHS,
1108 bool IsOrderedComparison) const;
1109
1110 /// Determines the floating point min/max opcode which should be used for
1111 /// a G_SELECT fed by a G_FCMP with predicate \p Pred.
1112 ///
1113 /// \returns 0 if this G_SELECT should not be combined to a floating point
1114 /// min or max. If it should be combined, returns one of
1115 ///
1116 /// * G_FMAXNUM
1117 /// * G_FMAXIMUM
1118 /// * G_FMINNUM
1119 /// * G_FMINIMUM
1120 ///
1121 /// Helper function for matchFPSelectToMinMax.
1122 unsigned getFPMinMaxOpcForSelect(CmpInst::Predicate Pred, LLT DstTy,
1123 SelectPatternNaNBehaviour VsNaNRetVal) const;
1124
1125 /// Handle floating point cases for matchSimplifySelectToMinMax.
1126 ///
1127 /// E.g.
1128 ///
1129 /// select (fcmp uge x, 1.0) x, 1.0 -> fmax x, 1.0
1130 /// select (fcmp uge x, 1.0) 1.0, x -> fminnm x, 1.0
1131 bool matchFPSelectToMinMax(Register Dst, Register Cond, Register TrueVal,
1132 Register FalseVal, BuildFnTy &MatchInfo) const;
1133
1134 /// Try to fold selects to logical operations.
1135 bool tryFoldBoolSelectToLogic(GSelect *Select, BuildFnTy &MatchInfo) const;
1136
1137 bool tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo) const;
1138
1139 bool isOneOrOneSplat(Register Src, bool AllowUndefs) const;
1140 bool isZeroOrZeroSplat(Register Src, bool AllowUndefs) const;
1141 bool isConstantSplatVector(Register Src, int64_t SplatValue,
1142 bool AllowUndefs) const;
1143 bool isConstantOrConstantVectorI(Register Src) const;
1144
1145 std::optional<APInt> getConstantOrConstantSplatVector(Register Src) const;
1146
1147 /// Fold (icmp Pred1 V1, C1) && (icmp Pred2 V2, C2)
1148 /// or (icmp Pred1 V1, C1) || (icmp Pred2 V2, C2)
1149 /// into a single comparison using range-based reasoning.
1150 bool tryFoldAndOrOrICmpsUsingRanges(GLogicalBinOp *Logic,
1151 BuildFnTy &MatchInfo) const;
1152
1153 // Simplify (cmp cc0 x, y) (&& or ||) (cmp cc1 x, y) -> cmp cc2 x, y.
1154 bool tryFoldLogicOfFCmps(GLogicalBinOp *Logic, BuildFnTy &MatchInfo) const;
1155
1156 bool isCastFree(unsigned Opcode, LLT ToTy, LLT FromTy) const;
1157
1158 bool constantFoldICmp(const GICmp &ICmp, const GIConstant &LHSCst,
1159 const GIConstant &RHSCst, BuildFnTy &MatchInfo) const;
1160 bool constantFoldFCmp(const GFCmp &FCmp, const GFConstant &LHSCst,
1161 const GFConstant &RHSCst, BuildFnTy &MatchInfo) const;
1162};
1163} // namespace llvm
1164
1165#endif
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
AMDGPU Register Bank Select
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
This file defines the DenseMap class.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Implement a low-level type suitable for MachineInstr level instruction selection.
Register Reg
MachineInstr unsigned OpIdx
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo) const
bool matchCommuteShift(MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchRepeatedFPDivisor(MachineInstr &MI, SmallVector< MachineInstr * > &MatchInfo) const
bool matchFoldC2MinusAPlusC1(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchLoadOrCombine(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match expression trees of the form.
bool tryCombine(MachineInstr &MI) const
Try to transform MI by using all of the above combine functions.
const RegisterBank * getRegBank(Register Reg) const
Get the register bank of Reg.
void applyPtrAddZero(MachineInstr &MI) const
bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2) const
Return true if MOP1 and MOP2 are register operands are defined by equivalent instructions.
void applyUDivOrURemByConst(MachineInstr &MI) const
bool matchConstantFoldBinOp(MachineInstr &MI, APInt &MatchInfo) const
Do constant folding when opportunities are exposed after MIR building.
void applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const
bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchSelectSameVal(MachineInstr &MI) const
Optimize (cond ? x : x) -> x.
bool matchAddEToAddO(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_*ADDE x, y, 0) -> (G_*ADDO x, y) (G_*SUBE x, y, 0) -> (G_*SUBO x, y)
bool matchReassocConstantInnerRHS(GPtrAdd &MI, MachineInstr *RHS, BuildFnTy &MatchInfo) const
bool matchBitfieldExtractFromShr(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: shr (shl x, n), k -> sbfx/ubfx x, pos, width.
bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchTruncSSatU(MachineInstr &MI, Register &MatchInfo) const
void applySimplifyURemByPow2(MachineInstr &MI) const
Combine G_UREM x, (known power of 2) to an add and bitmasking.
bool matchCombineUnmergeZExtToZExt(MachineInstr &MI) const
Transform X, Y = G_UNMERGE(G_ZEXT(Z)) -> X = G_ZEXT(Z); Y = G_CONSTANT 0.
bool matchPtrAddZero(MachineInstr &MI) const
}
void applyCombineConcatVectors(MachineInstr &MI, SmallVector< Register > &Ops) const
Replace MI with a flattened build_vector with Ops or an implicit_def if Ops is empty.
void applyXorOfAndWithSameReg(MachineInstr &MI, std::pair< Register, Register > &MatchInfo) const
bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally, bool &HasFMAD, bool &Aggressive, bool CanReassociate=false) const
bool matchFoldAPlusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const
void applyCombineUnmergeConstant(MachineInstr &MI, SmallVectorImpl< APInt > &Csts) const
bool matchShiftsTooBig(MachineInstr &MI, std::optional< int64_t > &MatchInfo) const
Match shifts greater or equal to the range (the bitwidth of the result datatype, or the effective bit...
bool matchCombineFAddFpExtFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) (fadd (fpext (fmul x,...
bool matchCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const
void applyCombineShuffleConcat(MachineInstr &MI, SmallVector< Register > &Ops) const
Replace MI with a flattened build_vector with Ops or an implicit_def if Ops is empty.
void replaceSingleDefInstWithReg(MachineInstr &MI, Register Replacement) const
Delete MI and replace all of its uses with Replacement.
void applyCombineShuffleToBuildVector(MachineInstr &MI) const
Replace MI with a build_vector.
bool matchZextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine zext of trunc.
bool matchCombineExtractedVectorLoad(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine a G_EXTRACT_VECTOR_ELT of a load into a narrowed load.
void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const
MachineRegisterInfo::replaceRegWith() and inform the observer of the changes.
void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, Register ToReg) const
Replace a single register operand with a new register and inform the observer of the changes.
bool matchReassocCommBinOp(MachineInstr &MI, BuildFnTy &MatchInfo) const
Reassociate commutative binary operations like G_ADD.
bool matchExtractVectorElementWithBuildVectorTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine extract vector element with a build vector trunc on the vector register.
void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
bool matchCommuteConstantToRHS(MachineInstr &MI) const
Match constant LHS ops that should be commuted.
const DataLayout & getDataLayout() const
bool matchBinOpSameVal(MachineInstr &MI) const
Optimize (x op x) -> x.
bool matchSimplifyNegMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const
Tranform (neg (min/max x, (neg x))) into (max/min x, (neg x)).
bool matchCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const
Try to combine G_[SU]DIV and G_[SU]REM into a single G_[SU]DIVREM when their source operands are iden...
bool matchNonNegZext(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine zext nneg to sext.
void applyUMulHToLShr(MachineInstr &MI) const
void applyNotCmp(MachineInstr &MI, SmallVectorImpl< Register > &RegsToNegate) const
bool matchShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const
Fold (shift (shift base, x), y) -> (shift base (x+y))
void applyCombineI2PToP2I(MachineInstr &MI, Register &Reg) const
bool matchTruncLshrBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const
bool matchAllExplicitUsesAreUndef(MachineInstr &MI) const
Return true if all register explicit use operands on MI are defined by a G_IMPLICIT_DEF.
bool isPredecessor(const MachineInstr &DefMI, const MachineInstr &UseMI) const
Returns true if DefMI precedes UseMI or they are the same instruction.
bool matchPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const
bool matchTruncSSatS(MachineInstr &MI, Register &MatchInfo) const
const TargetLowering & getTargetLowering() const
bool matchExtractVectorElementWithDifferentIndices(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine extract vector element with a insert vector element on the vector register and different indi...
bool matchShuffleUndefRHS(MachineInstr &MI, BuildFnTy &MatchInfo) const
Remove references to rhs if it is undef.
void applyBuildInstructionSteps(MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const
Replace MI with a series of instructions described in MatchInfo.
void applySDivByPow2(MachineInstr &MI) const
void applySimplifyAddToSub(MachineInstr &MI, std::tuple< Register, Register > &MatchInfo) const
void applyUDivByPow2(MachineInstr &MI) const
Given an G_UDIV MI expressing an unsigned divided by a pow2 constant, return expressions that impleme...
bool matchOr(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine ors.
bool matchLshrOfTruncOfLshr(MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo, MachineInstr &ShiftMI) const
Fold (lshr (trunc (lshr x, C1)), C2) -> trunc (shift x, (C1 + C2))
bool matchInsertVectorElementOOB(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine insert vector element OOB.
bool matchSimplifyAddToSub(MachineInstr &MI, std::tuple< Register, Register > &MatchInfo) const
Return true if MI is a G_ADD which can be simplified to a G_SUB.
void replaceInstWithConstant(MachineInstr &MI, int64_t C) const
Replace an instruction with a G_CONSTANT with value C.
bool tryEmitMemcpyInline(MachineInstr &MI) const
Emit loads and stores that perform the given memcpy.
bool matchCombineFSubFpExtFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), (fneg z)) (fsub (fpext (fmul x,...
void applyFsubToFneg(MachineInstr &MI, Register &MatchInfo) const
bool matchConstantLargerBitWidth(MachineInstr &MI, unsigned ConstIdx) const
Checks if constant at ConstIdx is larger than MI 's bitwidth.
GISelValueTracking * getValueTracking() const
void applyCombineCopy(MachineInstr &MI) const
bool matchExtractVectorElement(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine extract vector element.
bool matchSextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine sext of trunc.
bool matchAddSubSameReg(MachineInstr &MI, Register &Src) const
Transform G_ADD(x, G_SUB(y, x)) to y.
bool matchCombineShlOfExtend(MachineInstr &MI, RegisterImmPair &MatchData) const
bool matchMergeXAndZero(const MachineInstr &MI, BuildFnTy &MatchInfo) const
void applyCombineAddP2IToPtrAdd(MachineInstr &MI, std::pair< Register, bool > &PtrRegAndCommute) const
bool matchCombineFSubFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fmul x, y), z) -> (fma x, y, -z) (fsub (fmul x, y), z) -> (fmad x,...
bool matchCombineFAddFMAFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fma x, y, (fmul u, v)), z) -> (fma x, y, (fma u, v, z)) (fadd (fmad x,...
bool matchSextTruncSextLoad(MachineInstr &MI) const
bool matchMulOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchCombineMergeUnmerge(MachineInstr &MI, Register &MatchInfo) const
Fold away a merge of an unmerge of the corresponding values.
bool matchCombineInsertVecElts(MachineInstr &MI, SmallVectorImpl< Register > &MatchInfo) const
bool matchDivByPow2(MachineInstr &MI, bool IsSigned) const
Given an G_SDIV MI expressing a signed divided by a pow2 constant, return expressions that implements...
bool matchAddOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchNarrowBinopFeedingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchShlOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchRedundantNegOperands(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd x, fneg(y)) -> (fsub x, y) (fadd fneg(x), y) -> (fsub y, x) (fsub x,...
bool matchCombineLoadWithAndMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match (and (load x), mask) -> zextload x.
bool matchCombineFAddFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fadd (fmul x, y), z) -> (fma x, y, z) (fadd (fmul x, y), z) -> (fmad x,...
bool matchCombineCopy(MachineInstr &MI) const
bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const
void applyShiftImmedChain(MachineInstr &MI, RegisterImmPair &MatchInfo) const
bool matchXorOfAndWithSameReg(MachineInstr &MI, std::pair< Register, Register > &MatchInfo) const
Fold (xor (and x, y), y) -> (and (not x), y) {.
bool matchCombineShuffleVector(MachineInstr &MI, SmallVectorImpl< Register > &Ops) const
Check if the G_SHUFFLE_VECTOR MI can be replaced by a concat_vectors.
void applyCombineConstPtrAddToI2P(MachineInstr &MI, APInt &NewCst) const
bool matchTruncateOfExt(const MachineInstr &Root, const MachineInstr &ExtMI, BuildFnTy &MatchInfo) const
Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x).
bool matchCombineAddP2IToPtrAdd(MachineInstr &MI, std::pair< Register, bool > &PtrRegAndCommute) const
Transform G_ADD (G_PTRTOINT x), y -> G_PTRTOINT (G_PTR_ADD x, y) Transform G_ADD y,...
void replaceInstWithFConstant(MachineInstr &MI, double C) const
Replace an instruction with a G_FCONSTANT with value C.
bool matchMergeXAndUndef(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchFunnelShiftToRotate(MachineInstr &MI) const
Match an FSHL or FSHR that can be combined to a ROTR or ROTL rotate.
bool matchOrShiftToFunnelShift(MachineInstr &MI, bool AllowScalarConstants, BuildFnTy &MatchInfo) const
bool matchRedundantSExtInReg(MachineInstr &MI) const
void replaceOpcodeWith(MachineInstr &FromMI, unsigned ToOpcode) const
Replace the opcode in instruction with a new opcode and inform the observer of the changes.
void applyFunnelShiftConstantModulo(MachineInstr &MI) const
Replaces the shift amount in MI with ShiftAmt % BW.
bool matchOperandIsZero(MachineInstr &MI, unsigned OpIdx) const
Check if operand OpIdx is zero.
bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
void applyCombineShlOfExtend(MachineInstr &MI, const RegisterImmPair &MatchData) const
void applyUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const
CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B, bool IsPreLegalize, GISelValueTracking *VT=nullptr, MachineDominatorTree *MDT=nullptr, const LegalizerInfo *LI=nullptr)
bool matchShuffleDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
Turn shuffle a, b, mask -> shuffle undef, b, mask iff mask does not reference a.
bool matchCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const
Transform a multiply by a power-of-2 value to a left shift.
bool matchCombineConstPtrAddToI2P(MachineInstr &MI, APInt &NewCst) const
bool matchCombineUnmergeUndef(MachineInstr &MI, std::function< void(MachineIRBuilder &)> &MatchInfo) const
Transform G_UNMERGE G_IMPLICIT_DEF -> G_IMPLICIT_DEF, G_IMPLICIT_DEF, ...
void applyFoldBinOpIntoSelect(MachineInstr &MI, const unsigned &SelectOpNo) const
SelectOperand is the operand in binary operator MI that is the select to fold.
bool matchFoldAMinusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo) const
void applyCombineIndexedLoadStore(MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) const
bool matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_UMULO x, 2) -> (G_UADDO x, x) (G_SMULO x, 2) -> (G_SADDO x, x)
bool matchCombineShuffleConcat(MachineInstr &MI, SmallVector< Register > &Ops) const
void applySextInRegOfLoad(MachineInstr &MI, std::tuple< Register, unsigned > &MatchInfo) const
bool tryCombineCopy(MachineInstr &MI) const
If MI is COPY, try to combine it.
bool matchTruncUSatU(MachineInstr &MI, MachineInstr &MinMI) const
bool matchICmpToLHSKnownBits(MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI, BuildFnTy &MatchInfo) const
bool matchReassocPtrAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Reassociate pointer calculations with G_ADD involved, to allow better addressing mode usage.
bool matchCanonicalizeFCmp(const MachineInstr &MI, BuildFnTy &MatchInfo) const
void applyCombineShuffleVector(MachineInstr &MI, const ArrayRef< Register > Ops) const
Replace MI with a concat_vectors with Ops.
bool matchUndefShuffleVectorMask(MachineInstr &MI) const
Return true if a G_SHUFFLE_VECTOR instruction MI has an undef mask.
bool matchAnyExplicitUseIsUndef(MachineInstr &MI) const
Return true if any explicit use operand on MI is defined by a G_IMPLICIT_DEF.
bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg) const
Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space.
bool matchCombineSubToAdd(MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchShiftOfShiftedLogic(MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const
If we have a shift-by-constant of a bitwise logic op that itself has a shift-by-constant operand with...
bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI, unsigned OpIdx) const
Check if operand OpIdx is known to be a power of 2.
bool matchCombineConcatVectors(MachineInstr &MI, SmallVector< Register > &Ops) const
If MI is G_CONCAT_VECTORS, try to combine it.
bool matchInsertExtractVecEltOutOfBounds(MachineInstr &MI) const
Return true if a G_{EXTRACT,INSERT}_VECTOR_ELT has an out of range index.
bool matchExtractVectorElementWithShuffleVector(const MachineInstr &MI, const MachineInstr &MI2, BuildFnTy &MatchInfo) const
Combine extract vector element with a shuffle vector on the vector register.
bool matchExtractAllEltsFromBuildVector(MachineInstr &MI, SmallVectorImpl< std::pair< Register, MachineInstr * > > &MatchInfo) const
LLVMContext & getContext() const
void applyPtrAddImmedChain(MachineInstr &MI, PtrAddChain &MatchInfo) const
bool isConstantLegalOrBeforeLegalizer(const LLT Ty) const
bool matchNotCmp(MachineInstr &MI, SmallVectorImpl< Register > &RegsToNegate) const
Combine inverting a result of a compare into the opposite cond code.
bool matchSextInRegOfLoad(MachineInstr &MI, std::tuple< Register, unsigned > &MatchInfo) const
Match sext_inreg(load p), imm -> sextload p.
bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine select to integer min/max.
void applyCombineConstantFoldFpUnary(MachineInstr &MI, const ConstantFP *Cst) const
Transform fp_instr(cst) to constant result of the fp operation.
bool isLegal(const LegalityQuery &Query) const
bool matchICmpToTrueFalseKnownBits(MachineInstr &MI, int64_t &MatchInfo) const
bool tryReassocBinOp(unsigned Opc, Register DstReg, Register Op0, Register Op1, BuildFnTy &MatchInfo) const
Try to reassociate to reassociate operands of a commutative binop.
void eraseInst(MachineInstr &MI) const
Erase MI.
bool matchConstantFoldFPBinOp(MachineInstr &MI, ConstantFP *&MatchInfo) const
Do constant FP folding when opportunities are exposed after MIR building.
void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
bool matchUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const
bool matchUndefStore(MachineInstr &MI) const
Return true if a G_STORE instruction MI is storing an undef value.
MachineRegisterInfo & MRI
void applyCombineP2IToI2P(MachineInstr &MI, Register &Reg) const
Transform PtrToInt(IntToPtr(x)) to x.
void applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI) const
bool matchConstantFPOp(const MachineOperand &MOP, double C) const
Return true if MOP is defined by a G_FCONSTANT or splat with a value exactly equal to C.
MachineInstr * buildUDivOrURemUsingMul(MachineInstr &MI) const
Given an G_UDIV MI or G_UREM MI expressing a divide by constant, return an expression that implements...
void applyExtractVecEltBuildVec(MachineInstr &MI, Register &Reg) const
bool matchFoldBinOpIntoSelect(MachineInstr &MI, unsigned &SelectOpNo) const
Push a binary operator through a select on constants.
bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount) const
bool tryCombineExtendingLoads(MachineInstr &MI) const
If MI is extend that consumes the result of a load, try to combine it.
bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const
bool matchBuildVectorIdentityFold(MachineInstr &MI, Register &MatchInfo) const
bool matchBitfieldExtractFromShrAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: shr (and x, n), k -> ubfx x, pos, width.
void applyTruncSSatS(MachineInstr &MI, Register &MatchInfo) const
bool matchConstantFoldCastOp(MachineInstr &MI, APInt &MatchInfo) const
Do constant folding when opportunities are exposed after MIR building.
bool tryCombineShuffleVector(MachineInstr &MI) const
Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
void applyRotateOutOfRange(MachineInstr &MI) const
bool matchReassocFoldConstantsInSubTree(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
bool matchHoistLogicOpWithSameOpcodeHands(MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) const
Match (logic_op (op x...), (op y...)) -> (op (logic_op x, y))
bool matchBitfieldExtractFromAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: and (lshr x, cst), mask -> ubfx x, cst, width.
bool matchBitfieldExtractFromSExtInReg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Form a G_SBFX from a G_SEXT_INREG fed by a right shift.
bool matchNarrowBinop(const MachineInstr &TruncMI, const MachineInstr &BinopMI, BuildFnTy &MatchInfo) const
trunc (binop X, C) --> binop (trunc X, trunc C).
bool matchUndefSelectCmp(MachineInstr &MI) const
Return true if a G_SELECT instruction MI has an undef comparison.
bool matchAndOrDisjointMask(MachineInstr &MI, BuildFnTy &MatchInfo) const
void replaceInstWithUndef(MachineInstr &MI) const
Replace an instruction with a G_IMPLICIT_DEF.
bool matchRedundantBinOpInEquality(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform: (X + Y) == X -> Y == 0 (X - Y) == X -> Y == 0 (X ^ Y) == X -> Y == 0 (X + Y) !...
bool matchOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond) const
If a brcond's true block is not the fallthrough, make it so by inverting the condition and swapping o...
bool matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine addos.
void applyAshShlToSextInreg(MachineInstr &MI, std::tuple< Register, int64_t > &MatchInfo) const
bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine selects.
bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo) const
bool matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) const
Transform X, Y<dead> = G_UNMERGE Z -> X = G_TRUNC Z.
bool matchFsubToFneg(MachineInstr &MI, Register &MatchInfo) const
bool matchRotateOutOfRange(MachineInstr &MI) const
void applyExpandFPowI(MachineInstr &MI, int64_t Exponent) const
Expands FPOWI into a series of multiplications and a division if the exponent is negative.
void setRegBank(Register Reg, const RegisterBank *RegBank) const
Set the register bank of Reg.
bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx) const
Return true if a G_SELECT instruction MI has a constant comparison.
bool matchCommuteFPConstantToRHS(MachineInstr &MI) const
Match constant LHS FP ops that should be commuted.
void applyCombineDivRem(MachineInstr &MI, MachineInstr *&OtherMI) const
bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info) const
bool matchRedundantOr(MachineInstr &MI, Register &Replacement) const
void applyTruncSSatU(MachineInstr &MI, Register &MatchInfo) const
bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fpext (fneg (fmul x, y))), z) -> (fneg (fma (fpext x), (fpext y),...
bool matchTruncBuildVectorFold(MachineInstr &MI, Register &MatchInfo) const
bool matchSubOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
void applyCombineTruncOfShift(MachineInstr &MI, std::pair< MachineInstr *, LLT > &MatchInfo) const
bool matchConstantOp(const MachineOperand &MOP, int64_t C) const
Return true if MOP is defined by a G_CONSTANT or splat with a value equal to C.
const LegalizerInfo * LI
void applyCombineMulToShl(MachineInstr &MI, unsigned &ShiftVal) const
bool matchUMulHToLShr(MachineInstr &MI) const
MachineDominatorTree * MDT
MachineIRBuilder & getBuilder() const
void applyFunnelShiftToRotate(MachineInstr &MI) const
bool matchSimplifySelectToMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const
void applyRepeatedFPDivisor(SmallVector< MachineInstr * > &MatchInfo) const
bool matchTruncUSatUToFPTOUISat(MachineInstr &MI, MachineInstr &SrcMI) const
const RegisterBankInfo * RBI
bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) const
Match: (G_*MULO x, 0) -> 0 + no carry out.
GISelValueTracking * VT
bool matchCombineUnmergeConstant(MachineInstr &MI, SmallVectorImpl< APInt > &Csts) const
Transform G_UNMERGE Constant -> Constant1, Constant2, ...
void applyShiftOfShiftedLogic(MachineInstr &MI, ShiftOfShiftedLogic &MatchInfo) const
const TargetRegisterInfo * TRI
bool matchRedundantAnd(MachineInstr &MI, Register &Replacement) const
bool dominates(const MachineInstr &DefMI, const MachineInstr &UseMI) const
Returns true if DefMI dominates UseMI.
GISelChangeObserver & Observer
void applyBuildFn(MachineInstr &MI, BuildFnTy &MatchInfo) const
Use a function which takes in a MachineIRBuilder to perform a combine.
bool matchCombineTruncOfShift(MachineInstr &MI, std::pair< MachineInstr *, LLT > &MatchInfo) const
Transform trunc (shl x, K) to shl (trunc x), K if K < VT.getScalarSizeInBits().
bool matchCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftSize, unsigned &ShiftVal) const
Reduce a shift by a constant to an unmerge and a shift on a half sized type.
bool matchUDivOrURemByConst(MachineInstr &MI) const
Combine G_UDIV or G_UREM by constant into a multiply by magic constant.
bool matchAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine ands.
bool matchSuboCarryOut(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchRedundantSextInReg(MachineInstr &Root, MachineInstr &Other, BuildFnTy &MatchInfo) const
bool matchConstantFoldFMA(MachineInstr &MI, ConstantFP *&MatchInfo) const
Constant fold G_FMA/G_FMAD.
bool matchCombineFSubFNegFMulToFMadOrFMA(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform (fsub (fneg (fmul, x, y)), z) -> (fma (fneg x), y, (fneg z)) (fsub (fneg (fmul,...
bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg) const
Transform zext(trunc(x)) to x.
bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const
Check if operand OpIdx is undef.
void applyLshrOfTruncOfLshr(MachineInstr &MI, LshrOfTruncOfLshr &MatchInfo) const
bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0) const
Optimize memcpy intrinsics et al, e.g.
bool matchFreezeOfSingleMaybePoisonOperand(MachineInstr &MI, BuildFnTy &MatchInfo) const
void applySDivOrSRemByConst(MachineInstr &MI) const
MachineInstr * buildSDivOrSRemUsingMul(MachineInstr &MI) const
Given an G_SDIV MI or G_SREM MI expressing a signed divide by constant, return an expression that imp...
bool isLegalOrHasWidenScalar(const LegalityQuery &Query) const
bool matchCanonicalizeICmp(const MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchCastOfBuildVector(const MachineInstr &CastMI, const MachineInstr &BVMI, BuildFnTy &MatchInfo) const
bool matchSubAddSameReg(MachineInstr &MI, BuildFnTy &MatchInfo) const
Transform: (x + y) - y -> x (x + y) - x -> y x - (y + x) -> 0 - y x - (x + z) -> 0 - z.
bool matchReassocConstantInnerLHS(GPtrAdd &MI, MachineInstr *LHS, MachineInstr *RHS, BuildFnTy &MatchInfo) const
bool matchCastOfInteger(const MachineInstr &CastMI, APInt &MatchInfo) const
bool matchOverlappingAnd(MachineInstr &MI, BuildFnTy &MatchInfo) const
Fold and(and(x, C1), C2) -> C1&C2 ? and(x, C1&C2) : 0.
bool matchCombineAnyExtTrunc(MachineInstr &MI, Register &Reg) const
Transform anyext(trunc(x)) to x.
void applyExtractAllEltsFromBuildVector(MachineInstr &MI, SmallVectorImpl< std::pair< Register, MachineInstr * > > &MatchInfo) const
MachineIRBuilder & Builder
void applyCommuteBinOpOperands(MachineInstr &MI) const
void replaceSingleDefInstWithOperand(MachineInstr &MI, unsigned OpIdx) const
Delete MI and replace all of its uses with its OpIdx-th operand.
void applySextTruncSextLoad(MachineInstr &MI) const
const MachineFunction & getMachineFunction() const
bool matchCombineFAddFpExtFMulToFMadOrFMAAggressive(MachineInstr &MI, BuildFnTy &MatchInfo) const
bool matchExtractVectorElementWithBuildVector(const MachineInstr &MI, const MachineInstr &MI2, BuildFnTy &MatchInfo) const
Combine extract vector element with a build vector on the vector register.
bool matchSDivOrSRemByConst(MachineInstr &MI) const
Combine G_SDIV or G_SREM by constant into a multiply by magic constant.
void applyOptBrCondByInvertingCond(MachineInstr &MI, MachineInstr *&BrCond) const
void applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal) const
bool matchCastOfSelect(const MachineInstr &Cast, const MachineInstr &SelectMI, BuildFnTy &MatchInfo) const
bool matchFPowIExpansion(MachineInstr &MI, int64_t Exponent) const
Match FPOWI if it's safe to extend it into a series of multiplications.
void applyCombineInsertVecElts(MachineInstr &MI, SmallVectorImpl< Register > &MatchInfo) const
bool matchCombineUnmergeMergeToPlainValues(MachineInstr &MI, SmallVectorImpl< Register > &Operands) const
Transform <ty,...> G_UNMERGE(G_MERGE ty X, Y, Z) -> ty X, Y, Z.
void applyCombineUnmergeMergeToPlainValues(MachineInstr &MI, SmallVectorImpl< Register > &Operands) const
bool matchAshrShlToSextInreg(MachineInstr &MI, std::tuple< Register, int64_t > &MatchInfo) const
Match ashr (shl x, C), C -> sext_inreg (C)
void applyCombineUnmergeZExtToZExt(MachineInstr &MI) const
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:277
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
Represent a G_FCMP.
An floating-point-like constant.
Definition Utils.h:691
Represent a G_ICMP.
An integer-like constant.
Definition Utils.h:652
Abstract class that contains various methods for clients to notify about changes.
Represents any type of generic load or store.
Represents a logical binary operation.
Represents a G_PTR_ADD.
Represents a G_SELECT.
Represents a G_ZEXTLOAD.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Helper class to build MachineInstr.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Holds all the information related to register banks.
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
Definition Register.h:19
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
std::function< void(MachineIRBuilder &)> BuildFnTy
SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > OperandBuildSteps
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
@ Other
Any other memory.
Definition ModRef.h:68
LLVM_ABI bool isZeroOrZeroSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
InstructionBuildSteps(unsigned Opcode, const OperandBuildSteps &OperandFns)
InstructionBuildSteps()=default
Operands to be added to the instruction.
OperandBuildSteps OperandFns
The opcode for the produced instruction.
InstructionStepsMatchInfo(std::initializer_list< InstructionBuildSteps > InstrsToBuild)
SmallVector< InstructionBuildSteps, 2 > InstrsToBuild
Describes instructions to be built during a combine.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
const RegisterBank * Bank