1 //== llvm/CodeGen/GlobalISel/LegalizerHelper.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 // 9 /// \file A pass to convert the target-illegal operations created by IR -> MIR 10 /// translation into ones the target expects to be able to select. This may 11 /// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> -> 12 /// G_ADD <4 x i16>. 13 /// 14 /// The LegalizerHelper class is where most of the work happens, and is 15 /// designed to be callable from other passes that find themselves with an 16 /// illegal instruction. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H 21 #define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H 22 23 #include "llvm/CodeGen/GlobalISel/CallLowering.h" 24 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 25 #include "llvm/CodeGen/LowLevelType.h" 26 #include "llvm/CodeGen/MachineFunctionPass.h" 27 #include "llvm/CodeGen/RuntimeLibcalls.h" 28 29 namespace llvm { 30 // Forward declarations. 31 class LegalizerInfo; 32 class Legalizer; 33 class MachineRegisterInfo; 34 class GISelChangeObserver; 35 36 class LegalizerHelper { 37 public: 38 enum LegalizeResult { 39 /// Instruction was already legal and no change was made to the 40 /// MachineFunction. 41 AlreadyLegal, 42 43 /// Instruction has been legalized and the MachineFunction changed. 44 Legalized, 45 46 /// Some kind of error has occurred and we could not legalize this 47 /// instruction. 48 UnableToLegalize, 49 }; 50 51 LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, 52 MachineIRBuilder &B); 53 LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, 54 GISelChangeObserver &Observer, MachineIRBuilder &B); 55 56 /// Replace \p MI by a sequence of legal instructions that can implement the 57 /// same operation. Note that this means \p MI may be deleted, so any iterator 58 /// steps should be performed before calling this function. \p Helper should 59 /// be initialized to the MachineFunction containing \p MI. 60 /// 61 /// Considered as an opaque blob, the legal code will use and define the same 62 /// registers as \p MI. 63 LegalizeResult legalizeInstrStep(MachineInstr &MI); 64 65 /// Legalize an instruction by emiting a runtime library call instead. 66 LegalizeResult libcall(MachineInstr &MI); 67 68 /// Legalize an instruction by reducing the width of the underlying scalar 69 /// type. 70 LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); 71 72 /// Legalize an instruction by performing the operation on a wider scalar type 73 /// (for example a 16-bit addition can be safely performed at 32-bits 74 /// precision, ignoring the unused bits). 75 LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); 76 77 /// Legalize an instruction by splitting it into simpler parts, hopefully 78 /// understood by the target. 79 LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 80 81 /// Legalize a vector instruction by splitting into multiple components, each 82 /// acting on the same scalar type as the original but with fewer elements. 83 LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 84 LLT NarrowTy); 85 86 /// Legalize a vector instruction by increasing the number of vector elements 87 /// involved and ignoring the added elements later. 88 LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, 89 LLT MoreTy); 90 91 /// Expose MIRBuilder so clients can set their own RecordInsertInstruction 92 /// functions 93 MachineIRBuilder &MIRBuilder; 94 95 /// Expose LegalizerInfo so the clients can re-use. getLegalizerInfo()96 const LegalizerInfo &getLegalizerInfo() const { return LI; } 97 98 private: 99 /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a 100 /// Use by extending the operand's type to \p WideTy using the specified \p 101 /// ExtOpcode for the extension instruction, and replacing the vreg of the 102 /// operand in place. 103 void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, 104 unsigned ExtOpcode); 105 106 /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a 107 /// Use by truncating the operand's type to \p NarrowTy using G_TRUNC, and 108 /// replacing the vreg of the operand in place. 109 void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx); 110 111 /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a 112 /// Def by extending the operand's type to \p WideTy and truncating it back 113 /// with the \p TruncOpcode, and replacing the vreg of the operand in place. 114 void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0, 115 unsigned TruncOpcode = TargetOpcode::G_TRUNC); 116 117 // Legalize a single operand \p OpIdx of the machine instruction \p MI as a 118 // Def by truncating the operand's type to \p NarrowTy, replacing in place and 119 // extending back with \p ExtOpcode. 120 void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, 121 unsigned ExtOpcode); 122 /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a 123 /// Def by performing it with additional vector elements and extracting the 124 /// result elements, and replacing the vreg of the operand in place. 125 void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); 126 127 /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a 128 /// Use by producing a vector with undefined high elements, extracting the 129 /// original vector type, and replacing the vreg of the operand in place. 130 void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); 131 132 LegalizeResult 133 widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); 134 LegalizeResult 135 widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); 136 LegalizeResult 137 widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); 138 LegalizeResult 139 widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); 140 141 /// Helper function to split a wide generic register into bitwise blocks with 142 /// the given Type (which implies the number of blocks needed). The generic 143 /// registers created are appended to Ops, starting at bit 0 of Reg. 144 void extractParts(Register Reg, LLT Ty, int NumParts, 145 SmallVectorImpl<Register> &VRegs); 146 147 /// Version which handles irregular splits. 148 bool extractParts(Register Reg, LLT RegTy, LLT MainTy, 149 LLT &LeftoverTy, 150 SmallVectorImpl<Register> &VRegs, 151 SmallVectorImpl<Register> &LeftoverVRegs); 152 153 /// Helper function to build a wide generic register \p DstReg of type \p 154 /// RegTy from smaller parts. This will produce a G_MERGE_VALUES, 155 /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate 156 /// for the types. 157 /// 158 /// \p PartRegs must be registers of type \p PartTy. 159 /// 160 /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the 161 /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy. 162 void insertParts(Register DstReg, LLT ResultTy, 163 LLT PartTy, ArrayRef<Register> PartRegs, 164 LLT LeftoverTy = LLT(), ArrayRef<Register> LeftoverRegs = {}); 165 166 /// Perform generic multiplication of values held in multiple registers. 167 /// Generated instructions use only types NarrowTy and i1. 168 /// Destination can be same or two times size of the source. 169 void multiplyRegisters(SmallVectorImpl<Register> &DstRegs, 170 ArrayRef<Register> Src1Regs, 171 ArrayRef<Register> Src2Regs, LLT NarrowTy); 172 173 public: 174 LegalizeResult fewerElementsVectorImplicitDef(MachineInstr &MI, 175 unsigned TypeIdx, LLT NarrowTy); 176 177 /// Legalize a simple vector instruction where all operands are the same type 178 /// by splitting into multiple components. 179 LegalizeResult fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx, 180 LLT NarrowTy); 181 182 /// Legalize a instruction with a vector type where each operand may have a 183 /// different element type. All type indexes must have the same number of 184 /// elements. 185 LegalizeResult fewerElementsVectorMultiEltType(MachineInstr &MI, 186 unsigned TypeIdx, LLT NarrowTy); 187 188 LegalizeResult fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx, 189 LLT NarrowTy); 190 191 LegalizeResult 192 fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); 193 194 LegalizeResult 195 fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); 196 197 LegalizeResult fewerElementsVectorPhi(MachineInstr &MI, 198 unsigned TypeIdx, LLT NarrowTy); 199 200 LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, 201 LLT MoreTy); 202 203 LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, 204 unsigned TypeIdx, 205 LLT NarrowTy); 206 LegalizeResult fewerElementsVectorBuildVector(MachineInstr &MI, 207 unsigned TypeIdx, 208 LLT NarrowTy); 209 210 LegalizeResult 211 reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); 212 213 LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, 214 LLT HalfTy, LLT ShiftAmtTy); 215 216 LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 217 LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); 218 LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 219 LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 220 221 LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 222 LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 223 224 LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 225 226 LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); 227 LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 228 LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 229 LegalizeResult lowerFPTOUI(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 230 LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 231 LegalizeResult lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty); 232 LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); 233 LegalizeResult lowerFMad(MachineInstr &MI); 234 LegalizeResult lowerIntrinsicRound(MachineInstr &MI); 235 LegalizeResult lowerUnmergeValues(MachineInstr &MI); 236 LegalizeResult lowerShuffleVector(MachineInstr &MI); 237 LegalizeResult lowerDynStackAlloc(MachineInstr &MI); 238 LegalizeResult lowerExtract(MachineInstr &MI); 239 LegalizeResult lowerInsert(MachineInstr &MI); 240 LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI); 241 LegalizeResult lowerBswap(MachineInstr &MI); 242 LegalizeResult lowerBitreverse(MachineInstr &MI); 243 LegalizeResult lowerReadRegister(MachineInstr &MI); 244 245 private: 246 MachineRegisterInfo &MRI; 247 const LegalizerInfo &LI; 248 /// To keep track of changes made by the LegalizerHelper. 249 GISelChangeObserver &Observer; 250 }; 251 252 /// Helper function that creates the given libcall. 253 LegalizerHelper::LegalizeResult 254 createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, 255 const CallLowering::ArgInfo &Result, 256 ArrayRef<CallLowering::ArgInfo> Args); 257 258 /// Create a libcall to memcpy et al. 259 LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, 260 MachineRegisterInfo &MRI, 261 MachineInstr &MI); 262 263 } // End namespace llvm. 264 265 #endif 266