xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file A pass to convert the target-illegal operations created by IR -> MIR
100b57cec5SDimitry Andric /// translation into ones the target expects to be able to select. This may
110b57cec5SDimitry Andric /// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> ->
120b57cec5SDimitry Andric /// G_ADD <4 x i16>.
130b57cec5SDimitry Andric ///
140b57cec5SDimitry Andric /// The LegalizerHelper class is where most of the work happens, and is
150b57cec5SDimitry Andric /// designed to be callable from other passes that find themselves with an
160b57cec5SDimitry Andric /// illegal instruction.
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
190b57cec5SDimitry Andric 
20fe6060f1SDimitry Andric #ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H
21fe6060f1SDimitry Andric #define LLVM_CODEGEN_GLOBALISEL_LEGALIZERHELPER_H
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h"
2406c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
25*0fca6ea1SDimitry Andric #include "llvm/CodeGen/RuntimeLibcallUtil.h"
2681ad6265SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace llvm {
290b57cec5SDimitry Andric // Forward declarations.
3081ad6265SDimitry Andric class APInt;
3181ad6265SDimitry Andric class GAnyLoad;
3281ad6265SDimitry Andric class GLoadStore;
3381ad6265SDimitry Andric class GStore;
3481ad6265SDimitry Andric class GenericMachineInstr;
3581ad6265SDimitry Andric class MachineFunction;
3681ad6265SDimitry Andric class MachineIRBuilder;
3781ad6265SDimitry Andric class MachineInstr;
3881ad6265SDimitry Andric class MachineInstrBuilder;
3981ad6265SDimitry Andric struct MachinePointerInfo;
4081ad6265SDimitry Andric template <typename T> class SmallVectorImpl;
410b57cec5SDimitry Andric class LegalizerInfo;
420b57cec5SDimitry Andric class MachineRegisterInfo;
430b57cec5SDimitry Andric class GISelChangeObserver;
44fe6060f1SDimitry Andric class LostDebugLocObserver;
45e8d8bef9SDimitry Andric class TargetLowering;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric class LegalizerHelper {
480b57cec5SDimitry Andric public:
495ffd83dbSDimitry Andric   /// Expose MIRBuilder so clients can set their own RecordInsertInstruction
505ffd83dbSDimitry Andric   /// functions
515ffd83dbSDimitry Andric   MachineIRBuilder &MIRBuilder;
525ffd83dbSDimitry Andric 
535ffd83dbSDimitry Andric   /// To keep track of changes made by the LegalizerHelper.
545ffd83dbSDimitry Andric   GISelChangeObserver &Observer;
555ffd83dbSDimitry Andric 
565ffd83dbSDimitry Andric private:
575ffd83dbSDimitry Andric   MachineRegisterInfo &MRI;
585ffd83dbSDimitry Andric   const LegalizerInfo &LI;
59e8d8bef9SDimitry Andric   const TargetLowering &TLI;
6006c3fb27SDimitry Andric   GISelKnownBits *KB;
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric public:
630b57cec5SDimitry Andric   enum LegalizeResult {
640b57cec5SDimitry Andric     /// Instruction was already legal and no change was made to the
650b57cec5SDimitry Andric     /// MachineFunction.
660b57cec5SDimitry Andric     AlreadyLegal,
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric     /// Instruction has been legalized and the MachineFunction changed.
690b57cec5SDimitry Andric     Legalized,
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric     /// Some kind of error has occurred and we could not legalize this
720b57cec5SDimitry Andric     /// instruction.
730b57cec5SDimitry Andric     UnableToLegalize,
740b57cec5SDimitry Andric   };
750b57cec5SDimitry Andric 
765ffd83dbSDimitry Andric   /// Expose LegalizerInfo so the clients can re-use.
getLegalizerInfo()775ffd83dbSDimitry Andric   const LegalizerInfo &getLegalizerInfo() const { return LI; }
getTargetLowering()78e8d8bef9SDimitry Andric   const TargetLowering &getTargetLowering() const { return TLI; }
getKnownBits()7906c3fb27SDimitry Andric   GISelKnownBits *getKnownBits() const { return KB; }
805ffd83dbSDimitry Andric 
810b57cec5SDimitry Andric   LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer,
820b57cec5SDimitry Andric                   MachineIRBuilder &B);
830b57cec5SDimitry Andric   LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
8406c3fb27SDimitry Andric                   GISelChangeObserver &Observer, MachineIRBuilder &B,
8506c3fb27SDimitry Andric                   GISelKnownBits *KB = nullptr);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// Replace \p MI by a sequence of legal instructions that can implement the
880b57cec5SDimitry Andric   /// same operation. Note that this means \p MI may be deleted, so any iterator
890b57cec5SDimitry Andric   /// steps should be performed before calling this function. \p Helper should
900b57cec5SDimitry Andric   /// be initialized to the MachineFunction containing \p MI.
910b57cec5SDimitry Andric   ///
920b57cec5SDimitry Andric   /// Considered as an opaque blob, the legal code will use and define the same
930b57cec5SDimitry Andric   /// registers as \p MI.
94fe6060f1SDimitry Andric   LegalizeResult legalizeInstrStep(MachineInstr &MI,
95fe6060f1SDimitry Andric                                    LostDebugLocObserver &LocObserver);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   /// Legalize an instruction by emiting a runtime library call instead.
98fe6060f1SDimitry Andric   LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   /// Legalize an instruction by reducing the width of the underlying scalar
1010b57cec5SDimitry Andric   /// type.
1020b57cec5SDimitry Andric   LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   /// Legalize an instruction by performing the operation on a wider scalar type
1050b57cec5SDimitry Andric   /// (for example a 16-bit addition can be safely performed at 32-bits
1060b57cec5SDimitry Andric   /// precision, ignoring the unused bits).
1070b57cec5SDimitry Andric   LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
1080b57cec5SDimitry Andric 
1095ffd83dbSDimitry Andric   /// Legalize an instruction by replacing the value type
1105ffd83dbSDimitry Andric   LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
1115ffd83dbSDimitry Andric 
1120b57cec5SDimitry Andric   /// Legalize an instruction by splitting it into simpler parts, hopefully
1130b57cec5SDimitry Andric   /// understood by the target.
1140b57cec5SDimitry Andric   LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   /// Legalize a vector instruction by splitting into multiple components, each
1170b57cec5SDimitry Andric   /// acting on the same scalar type as the original but with fewer elements.
1180b57cec5SDimitry Andric   LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1190b57cec5SDimitry Andric                                      LLT NarrowTy);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   /// Legalize a vector instruction by increasing the number of vector elements
1220b57cec5SDimitry Andric   /// involved and ignoring the added elements later.
1230b57cec5SDimitry Andric   LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
1240b57cec5SDimitry Andric                                     LLT MoreTy);
1250b57cec5SDimitry Andric 
1265ffd83dbSDimitry Andric   /// Cast the given value to an LLT::scalar with an equivalent size. Returns
1275ffd83dbSDimitry Andric   /// the register to use if an instruction was inserted. Returns the original
1285ffd83dbSDimitry Andric   /// register if no coercion was necessary.
1295ffd83dbSDimitry Andric   //
1305ffd83dbSDimitry Andric   // This may also fail and return Register() if there is no legal way to cast.
1315ffd83dbSDimitry Andric   Register coerceToScalar(Register Val);
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1340b57cec5SDimitry Andric   /// Use by extending the operand's type to \p WideTy using the specified \p
1350b57cec5SDimitry Andric   /// ExtOpcode for the extension instruction, and replacing the vreg of the
1360b57cec5SDimitry Andric   /// operand in place.
1370b57cec5SDimitry Andric   void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx,
1380b57cec5SDimitry Andric                       unsigned ExtOpcode);
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1410b57cec5SDimitry Andric   /// Use by truncating the operand's type to \p NarrowTy using G_TRUNC, and
1420b57cec5SDimitry Andric   /// replacing the vreg of the operand in place.
1430b57cec5SDimitry Andric   void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1460b57cec5SDimitry Andric   /// Def by extending the operand's type to \p WideTy and truncating it back
1470b57cec5SDimitry Andric   /// with the \p TruncOpcode, and replacing the vreg of the operand in place.
1480b57cec5SDimitry Andric   void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0,
1490b57cec5SDimitry Andric                       unsigned TruncOpcode = TargetOpcode::G_TRUNC);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1520b57cec5SDimitry Andric   // Def by truncating the operand's type to \p NarrowTy, replacing in place and
1530b57cec5SDimitry Andric   // extending back with \p ExtOpcode.
1540b57cec5SDimitry Andric   void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx,
1550b57cec5SDimitry Andric                        unsigned ExtOpcode);
1560b57cec5SDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1570b57cec5SDimitry Andric   /// Def by performing it with additional vector elements and extracting the
1580b57cec5SDimitry Andric   /// result elements, and replacing the vreg of the operand in place.
1590b57cec5SDimitry Andric   void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx);
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1620b57cec5SDimitry Andric   /// Use by producing a vector with undefined high elements, extracting the
1630b57cec5SDimitry Andric   /// original vector type, and replacing the vreg of the operand in place.
1640b57cec5SDimitry Andric   void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx);
1650b57cec5SDimitry Andric 
1665ffd83dbSDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1675ffd83dbSDimitry Andric   /// use by inserting a G_BITCAST to \p CastTy
1685ffd83dbSDimitry Andric   void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx);
1695ffd83dbSDimitry Andric 
1705ffd83dbSDimitry Andric   /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a
1715ffd83dbSDimitry Andric   /// def by inserting a G_BITCAST from \p CastTy
1725ffd83dbSDimitry Andric   void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx);
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric private:
1750b57cec5SDimitry Andric   LegalizeResult
1760b57cec5SDimitry Andric   widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
1770b57cec5SDimitry Andric   LegalizeResult
1780b57cec5SDimitry Andric   widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
1790b57cec5SDimitry Andric   LegalizeResult
1800b57cec5SDimitry Andric   widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
1810b57cec5SDimitry Andric   LegalizeResult
1820b57cec5SDimitry Andric   widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
183fe6060f1SDimitry Andric   LegalizeResult widenScalarAddSubOverflow(MachineInstr &MI, unsigned TypeIdx,
184e8d8bef9SDimitry Andric                                            LLT WideTy);
185e8d8bef9SDimitry Andric   LegalizeResult widenScalarAddSubShlSat(MachineInstr &MI, unsigned TypeIdx,
1865ffd83dbSDimitry Andric                                          LLT WideTy);
187fe6060f1SDimitry Andric   LegalizeResult widenScalarMulo(MachineInstr &MI, unsigned TypeIdx,
188fe6060f1SDimitry Andric                                  LLT WideTy);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// Helper function to build a wide generic register \p DstReg of type \p
1910b57cec5SDimitry Andric   /// RegTy from smaller parts. This will produce a G_MERGE_VALUES,
1920b57cec5SDimitry Andric   /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate
1930b57cec5SDimitry Andric   /// for the types.
1940b57cec5SDimitry Andric   ///
1950b57cec5SDimitry Andric   /// \p PartRegs must be registers of type \p PartTy.
1960b57cec5SDimitry Andric   ///
1970b57cec5SDimitry Andric   /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the
1980b57cec5SDimitry Andric   /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy.
1990b57cec5SDimitry Andric   void insertParts(Register DstReg, LLT ResultTy,
2000b57cec5SDimitry Andric                    LLT PartTy, ArrayRef<Register> PartRegs,
2010b57cec5SDimitry Andric                    LLT LeftoverTy = LLT(), ArrayRef<Register> LeftoverRegs = {});
2020b57cec5SDimitry Andric 
2030eae32dcSDimitry Andric   /// Merge \p PartRegs with different types into \p DstReg.
2040eae32dcSDimitry Andric   void mergeMixedSubvectors(Register DstReg, ArrayRef<Register> PartRegs);
2050eae32dcSDimitry Andric 
2060eae32dcSDimitry Andric   void appendVectorElts(SmallVectorImpl<Register> &Elts, Register Reg);
2070eae32dcSDimitry Andric 
208e8d8bef9SDimitry Andric   /// Unmerge \p SrcReg into smaller sized values, and append them to \p
209e8d8bef9SDimitry Andric   /// Parts. The elements of \p Parts will be the greatest common divisor type
210e8d8bef9SDimitry Andric   /// of \p DstTy, \p NarrowTy and the type of \p SrcReg. This will compute and
211e8d8bef9SDimitry Andric   /// return the GCD type.
2125ffd83dbSDimitry Andric   LLT extractGCDType(SmallVectorImpl<Register> &Parts, LLT DstTy,
2135ffd83dbSDimitry Andric                      LLT NarrowTy, Register SrcReg);
2145ffd83dbSDimitry Andric 
215e8d8bef9SDimitry Andric   /// Unmerge \p SrcReg into \p GCDTy typed registers. This will append all of
216e8d8bef9SDimitry Andric   /// the unpacked registers to \p Parts. This version is if the common unmerge
217e8d8bef9SDimitry Andric   /// type is already known.
218e8d8bef9SDimitry Andric   void extractGCDType(SmallVectorImpl<Register> &Parts, LLT GCDTy,
219e8d8bef9SDimitry Andric                       Register SrcReg);
220e8d8bef9SDimitry Andric 
2215ffd83dbSDimitry Andric   /// Produce a merge of values in \p VRegs to define \p DstReg. Perform a merge
2225ffd83dbSDimitry Andric   /// from the least common multiple type, and convert as appropriate to \p
2235ffd83dbSDimitry Andric   /// DstReg.
2245ffd83dbSDimitry Andric   ///
2255ffd83dbSDimitry Andric   /// \p VRegs should each have type \p GCDTy. This type should be greatest
2265ffd83dbSDimitry Andric   /// common divisor type of \p DstReg, \p NarrowTy, and an undetermined source
2275ffd83dbSDimitry Andric   /// type.
2285ffd83dbSDimitry Andric   ///
2295ffd83dbSDimitry Andric   /// \p NarrowTy is the desired result merge source type. If the source value
2305ffd83dbSDimitry Andric   /// needs to be widened to evenly cover \p DstReg, inserts high bits
2315ffd83dbSDimitry Andric   /// corresponding to the extension opcode \p PadStrategy.
2325ffd83dbSDimitry Andric   ///
2335f757f3fSDimitry Andric   /// \p VRegs will be cleared, and the result \p NarrowTy register pieces
2345ffd83dbSDimitry Andric   /// will replace it. Returns The complete LCMTy that \p VRegs will cover when
2355ffd83dbSDimitry Andric   /// merged.
2365ffd83dbSDimitry Andric   LLT buildLCMMergePieces(LLT DstTy, LLT NarrowTy, LLT GCDTy,
2375ffd83dbSDimitry Andric                           SmallVectorImpl<Register> &VRegs,
2385ffd83dbSDimitry Andric                           unsigned PadStrategy = TargetOpcode::G_ANYEXT);
2395ffd83dbSDimitry Andric 
2405ffd83dbSDimitry Andric   /// Merge the values in \p RemergeRegs to an \p LCMTy typed value. Extract the
2415ffd83dbSDimitry Andric   /// low bits into \p DstReg. This is intended to use the outputs from
2425ffd83dbSDimitry Andric   /// buildLCMMergePieces after processing.
2435ffd83dbSDimitry Andric   void buildWidenedRemergeToDst(Register DstReg, LLT LCMTy,
2445ffd83dbSDimitry Andric                                 ArrayRef<Register> RemergeRegs);
2455ffd83dbSDimitry Andric 
2460b57cec5SDimitry Andric   /// Perform generic multiplication of values held in multiple registers.
2470b57cec5SDimitry Andric   /// Generated instructions use only types NarrowTy and i1.
2480b57cec5SDimitry Andric   /// Destination can be same or two times size of the source.
2490b57cec5SDimitry Andric   void multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
2500b57cec5SDimitry Andric                          ArrayRef<Register> Src1Regs,
2510b57cec5SDimitry Andric                          ArrayRef<Register> Src2Regs, LLT NarrowTy);
2520b57cec5SDimitry Andric 
253e8d8bef9SDimitry Andric   void changeOpcode(MachineInstr &MI, unsigned NewOpcode);
254e8d8bef9SDimitry Andric 
255fe6060f1SDimitry Andric   LegalizeResult tryNarrowPow2Reduction(MachineInstr &MI, Register SrcReg,
256fe6060f1SDimitry Andric                                         LLT SrcTy, LLT NarrowTy,
257fe6060f1SDimitry Andric                                         unsigned ScalarOpc);
258fe6060f1SDimitry Andric 
259349cc55cSDimitry Andric   // Memcpy family legalization helpers.
260349cc55cSDimitry Andric   LegalizeResult lowerMemset(MachineInstr &MI, Register Dst, Register Val,
261349cc55cSDimitry Andric                              uint64_t KnownLen, Align Alignment,
262349cc55cSDimitry Andric                              bool IsVolatile);
263349cc55cSDimitry Andric   LegalizeResult lowerMemcpyInline(MachineInstr &MI, Register Dst, Register Src,
264349cc55cSDimitry Andric                                    uint64_t KnownLen, Align DstAlign,
265349cc55cSDimitry Andric                                    Align SrcAlign, bool IsVolatile);
266349cc55cSDimitry Andric   LegalizeResult lowerMemcpy(MachineInstr &MI, Register Dst, Register Src,
267349cc55cSDimitry Andric                              uint64_t KnownLen, uint64_t Limit, Align DstAlign,
268349cc55cSDimitry Andric                              Align SrcAlign, bool IsVolatile);
269349cc55cSDimitry Andric   LegalizeResult lowerMemmove(MachineInstr &MI, Register Dst, Register Src,
270349cc55cSDimitry Andric                               uint64_t KnownLen, Align DstAlign, Align SrcAlign,
271349cc55cSDimitry Andric                               bool IsVolatile);
272349cc55cSDimitry Andric 
2735f757f3fSDimitry Andric   // Implements floating-point environment read/write via library function call.
2745f757f3fSDimitry Andric   LegalizeResult createGetStateLibcall(MachineIRBuilder &MIRBuilder,
2751db9f3b2SDimitry Andric                                        MachineInstr &MI,
2761db9f3b2SDimitry Andric                                        LostDebugLocObserver &LocObserver);
2775f757f3fSDimitry Andric   LegalizeResult createSetStateLibcall(MachineIRBuilder &MIRBuilder,
2781db9f3b2SDimitry Andric                                        MachineInstr &MI,
2791db9f3b2SDimitry Andric                                        LostDebugLocObserver &LocObserver);
2805f757f3fSDimitry Andric   LegalizeResult createResetStateLibcall(MachineIRBuilder &MIRBuilder,
2811db9f3b2SDimitry Andric                                          MachineInstr &MI,
2821db9f3b2SDimitry Andric                                          LostDebugLocObserver &LocObserver);
2835f757f3fSDimitry Andric 
284*0fca6ea1SDimitry Andric   MachineInstrBuilder
285*0fca6ea1SDimitry Andric   getNeutralElementForVecReduce(unsigned Opcode, MachineIRBuilder &MIRBuilder,
286*0fca6ea1SDimitry Andric                                 LLT Ty);
287*0fca6ea1SDimitry Andric 
2880b57cec5SDimitry Andric public:
289e8d8bef9SDimitry Andric   /// Return the alignment to use for a stack temporary object with the given
290e8d8bef9SDimitry Andric   /// type.
291e8d8bef9SDimitry Andric   Align getStackTemporaryAlignment(LLT Type, Align MinAlign = Align()) const;
292e8d8bef9SDimitry Andric 
293e8d8bef9SDimitry Andric   /// Create a stack temporary based on the size in bytes and the alignment
294e8d8bef9SDimitry Andric   MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment,
295e8d8bef9SDimitry Andric                                            MachinePointerInfo &PtrInfo);
296e8d8bef9SDimitry Andric 
297e8d8bef9SDimitry Andric   /// Get a pointer to vector element \p Index located in memory for a vector of
298e8d8bef9SDimitry Andric   /// type \p VecTy starting at a base address of \p VecPtr. If \p Index is out
299e8d8bef9SDimitry Andric   /// of bounds the returned pointer is unspecified, but will be within the
300e8d8bef9SDimitry Andric   /// vector bounds.
301e8d8bef9SDimitry Andric   Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index);
302e8d8bef9SDimitry Andric 
3030eae32dcSDimitry Andric   /// Handles most opcodes. Split \p MI into same instruction on sub-vectors or
3040eae32dcSDimitry Andric   /// scalars with \p NumElts elements (1 for scalar). Supports uneven splits:
3050eae32dcSDimitry Andric   /// there can be leftover sub-vector with fewer then \p NumElts or a leftover
3060eae32dcSDimitry Andric   /// scalar. To avoid this use moreElements first and set MI number of elements
3070eae32dcSDimitry Andric   /// to multiple of \p NumElts. Non-vector operands that should be used on all
3080eae32dcSDimitry Andric   /// sub-instructions without split are listed in \p NonVecOpIndices.
3090eae32dcSDimitry Andric   LegalizeResult fewerElementsVectorMultiEltType(
3100eae32dcSDimitry Andric       GenericMachineInstr &MI, unsigned NumElts,
3110eae32dcSDimitry Andric       std::initializer_list<unsigned> NonVecOpIndices = {});
3120b57cec5SDimitry Andric 
3130eae32dcSDimitry Andric   LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI,
3140eae32dcSDimitry Andric                                         unsigned NumElts);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
3170b57cec5SDimitry Andric                                        LLT MoreTy);
318fe6060f1SDimitry Andric   LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx,
319fe6060f1SDimitry Andric                                            LLT MoreTy);
3200b57cec5SDimitry Andric 
3218bcb0991SDimitry Andric   LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI,
3228bcb0991SDimitry Andric                                                   unsigned TypeIdx,
3238bcb0991SDimitry Andric                                                   LLT NarrowTy);
324e8d8bef9SDimitry Andric   LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx,
325e8d8bef9SDimitry Andric                                           LLT NarrowTy);
326e8d8bef9SDimitry Andric   LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI,
3278bcb0991SDimitry Andric                                                            unsigned TypeIdx,
3288bcb0991SDimitry Andric                                                            LLT NarrowTy);
3298bcb0991SDimitry Andric 
33006c3fb27SDimitry Andric   /// Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
33106c3fb27SDimitry Andric   LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI);
33206c3fb27SDimitry Andric 
333fe6060f1SDimitry Andric   LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx,
334fe6060f1SDimitry Andric                                       LLT NarrowTy);
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
3370b57cec5SDimitry Andric                                              LLT HalfTy, LLT ShiftAmtTy);
3380b57cec5SDimitry Andric 
339fe6060f1SDimitry Andric   LegalizeResult fewerElementsVectorReductions(MachineInstr &MI,
340fe6060f1SDimitry Andric                                                unsigned TypeIdx, LLT NarrowTy);
3411db9f3b2SDimitry Andric   LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI,
3421db9f3b2SDimitry Andric                                                   unsigned TypeIdx,
3431db9f3b2SDimitry Andric                                                   LLT NarrowTy);
344fe6060f1SDimitry Andric 
345*0fca6ea1SDimitry Andric   // Fewer Elements for bitcast, ensuring that the size of the Src and Dst
346*0fca6ea1SDimitry Andric   // registers will be the same
347*0fca6ea1SDimitry Andric   LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx,
348*0fca6ea1SDimitry Andric                                       LLT NarrowTy);
349*0fca6ea1SDimitry Andric 
350fe6060f1SDimitry Andric   LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx,
351fe6060f1SDimitry Andric                                             LLT NarrowTy);
352fe6060f1SDimitry Andric 
3530b57cec5SDimitry Andric   LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
354fe6060f1SDimitry Andric   LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx,
355fe6060f1SDimitry Andric                                     LLT NarrowTy);
3560b57cec5SDimitry Andric   LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty);
35723408297SDimitry Andric   LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3580b57cec5SDimitry Andric   LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3590b57cec5SDimitry Andric   LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3625ffd83dbSDimitry Andric   LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3630b57cec5SDimitry Andric   LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3645ffd83dbSDimitry Andric   LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3655ffd83dbSDimitry Andric   LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3665ffd83dbSDimitry Andric   LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
36706c3fb27SDimitry Andric   LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
3680b57cec5SDimitry Andric 
369e8d8bef9SDimitry Andric   /// Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
370e8d8bef9SDimitry Andric   LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx,
371e8d8bef9SDimitry Andric                                          LLT CastTy);
372e8d8bef9SDimitry Andric 
373e8d8bef9SDimitry Andric   /// Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
374e8d8bef9SDimitry Andric   LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx,
375e8d8bef9SDimitry Andric                                         LLT CastTy);
376*0fca6ea1SDimitry Andric   LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx,
377*0fca6ea1SDimitry Andric                                      LLT CastTy);
378e8d8bef9SDimitry Andric 
379*0fca6ea1SDimitry Andric   LegalizeResult lowerConstant(MachineInstr &MI);
38006c3fb27SDimitry Andric   LegalizeResult lowerFConstant(MachineInstr &MI);
3815ffd83dbSDimitry Andric   LegalizeResult lowerBitcast(MachineInstr &MI);
382fe6060f1SDimitry Andric   LegalizeResult lowerLoad(GAnyLoad &MI);
383fe6060f1SDimitry Andric   LegalizeResult lowerStore(GStore &MI);
384e8d8bef9SDimitry Andric   LegalizeResult lowerBitCount(MachineInstr &MI);
385fe6060f1SDimitry Andric   LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI);
386fe6060f1SDimitry Andric   LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI);
387fe6060f1SDimitry Andric   LegalizeResult lowerFunnelShift(MachineInstr &MI);
3885f757f3fSDimitry Andric   LegalizeResult lowerEXT(MachineInstr &MI);
3895f757f3fSDimitry Andric   LegalizeResult lowerTRUNC(MachineInstr &MI);
390fe6060f1SDimitry Andric   LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI);
391fe6060f1SDimitry Andric   LegalizeResult lowerRotate(MachineInstr &MI);
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI);
394e8d8bef9SDimitry Andric   LegalizeResult lowerUITOFP(MachineInstr &MI);
395e8d8bef9SDimitry Andric   LegalizeResult lowerSITOFP(MachineInstr &MI);
396e8d8bef9SDimitry Andric   LegalizeResult lowerFPTOUI(MachineInstr &MI);
3975ffd83dbSDimitry Andric   LegalizeResult lowerFPTOSI(MachineInstr &MI);
3985ffd83dbSDimitry Andric 
3995ffd83dbSDimitry Andric   LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI);
400e8d8bef9SDimitry Andric   LegalizeResult lowerFPTRUNC(MachineInstr &MI);
401e8d8bef9SDimitry Andric   LegalizeResult lowerFPOWI(MachineInstr &MI);
4025ffd83dbSDimitry Andric 
403bdd1243dSDimitry Andric   LegalizeResult lowerISFPCLASS(MachineInstr &MI);
404bdd1243dSDimitry Andric 
405*0fca6ea1SDimitry Andric   LegalizeResult lowerThreewayCompare(MachineInstr &MI);
406e8d8bef9SDimitry Andric   LegalizeResult lowerMinMax(MachineInstr &MI);
407e8d8bef9SDimitry Andric   LegalizeResult lowerFCopySign(MachineInstr &MI);
4080b57cec5SDimitry Andric   LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI);
4098bcb0991SDimitry Andric   LegalizeResult lowerFMad(MachineInstr &MI);
410480093f4SDimitry Andric   LegalizeResult lowerIntrinsicRound(MachineInstr &MI);
4115ffd83dbSDimitry Andric   LegalizeResult lowerFFloor(MachineInstr &MI);
4125ffd83dbSDimitry Andric   LegalizeResult lowerMergeValues(MachineInstr &MI);
4138bcb0991SDimitry Andric   LegalizeResult lowerUnmergeValues(MachineInstr &MI);
414e8d8bef9SDimitry Andric   LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI);
4158bcb0991SDimitry Andric   LegalizeResult lowerShuffleVector(MachineInstr &MI);
416*0fca6ea1SDimitry Andric   LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI);
4175f757f3fSDimitry Andric   Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize,
4185f757f3fSDimitry Andric                                      Align Alignment, LLT PtrTy);
4198bcb0991SDimitry Andric   LegalizeResult lowerDynStackAlloc(MachineInstr &MI);
4205f757f3fSDimitry Andric   LegalizeResult lowerStackSave(MachineInstr &MI);
4215f757f3fSDimitry Andric   LegalizeResult lowerStackRestore(MachineInstr &MI);
4228bcb0991SDimitry Andric   LegalizeResult lowerExtract(MachineInstr &MI);
4238bcb0991SDimitry Andric   LegalizeResult lowerInsert(MachineInstr &MI);
4248bcb0991SDimitry Andric   LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI);
425e8d8bef9SDimitry Andric   LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI);
426e8d8bef9SDimitry Andric   LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI);
427e8d8bef9SDimitry Andric   LegalizeResult lowerShlSat(MachineInstr &MI);
428480093f4SDimitry Andric   LegalizeResult lowerBswap(MachineInstr &MI);
429480093f4SDimitry Andric   LegalizeResult lowerBitreverse(MachineInstr &MI);
4305ffd83dbSDimitry Andric   LegalizeResult lowerReadWriteRegister(MachineInstr &MI);
431e8d8bef9SDimitry Andric   LegalizeResult lowerSMULH_UMULH(MachineInstr &MI);
432e8d8bef9SDimitry Andric   LegalizeResult lowerSelect(MachineInstr &MI);
433fe6060f1SDimitry Andric   LegalizeResult lowerDIVREM(MachineInstr &MI);
434fe6060f1SDimitry Andric   LegalizeResult lowerAbsToAddXor(MachineInstr &MI);
435fe6060f1SDimitry Andric   LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI);
436*0fca6ea1SDimitry Andric   LegalizeResult lowerAbsToCNeg(MachineInstr &MI);
437349cc55cSDimitry Andric   LegalizeResult lowerVectorReduction(MachineInstr &MI);
438349cc55cSDimitry Andric   LegalizeResult lowerMemcpyInline(MachineInstr &MI);
439349cc55cSDimitry Andric   LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0);
4405f757f3fSDimitry Andric   LegalizeResult lowerVAArg(MachineInstr &MI);
4410b57cec5SDimitry Andric };
4420b57cec5SDimitry Andric 
4435ffd83dbSDimitry Andric /// Helper function that creates a libcall to the given \p Name using the given
4445ffd83dbSDimitry Andric /// calling convention \p CC.
4455ffd83dbSDimitry Andric LegalizerHelper::LegalizeResult
4465ffd83dbSDimitry Andric createLibcall(MachineIRBuilder &MIRBuilder, const char *Name,
4475ffd83dbSDimitry Andric               const CallLowering::ArgInfo &Result,
4481db9f3b2SDimitry Andric               ArrayRef<CallLowering::ArgInfo> Args, CallingConv::ID CC,
4491db9f3b2SDimitry Andric               LostDebugLocObserver &LocObserver, MachineInstr *MI = nullptr);
4505ffd83dbSDimitry Andric 
4510b57cec5SDimitry Andric /// Helper function that creates the given libcall.
4520b57cec5SDimitry Andric LegalizerHelper::LegalizeResult
4530b57cec5SDimitry Andric createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
4540b57cec5SDimitry Andric               const CallLowering::ArgInfo &Result,
4551db9f3b2SDimitry Andric               ArrayRef<CallLowering::ArgInfo> Args,
4561db9f3b2SDimitry Andric               LostDebugLocObserver &LocObserver, MachineInstr *MI = nullptr);
4570b57cec5SDimitry Andric 
4588bcb0991SDimitry Andric /// Create a libcall to memcpy et al.
459fe6060f1SDimitry Andric LegalizerHelper::LegalizeResult
460fe6060f1SDimitry Andric createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
461fe6060f1SDimitry Andric                  MachineInstr &MI, LostDebugLocObserver &LocObserver);
4628bcb0991SDimitry Andric 
4635f757f3fSDimitry Andric 
4640b57cec5SDimitry Andric } // End namespace llvm.
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric #endif
467