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