Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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; |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 34 | class GISelChangeObserver; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 51 | LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, |
| 52 | MachineIRBuilder &B); |
| 53 | LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, |
| 54 | GISelChangeObserver &Observer, MachineIRBuilder &B); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 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, |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 89 | LLT MoreTy); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 90 | |
| 91 | /// Expose MIRBuilder so clients can set their own RecordInsertInstruction |
| 92 | /// functions |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 93 | MachineIRBuilder &MIRBuilder; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 94 | |
| 95 | /// Expose LegalizerInfo so the clients can re-use. |
| 96 | const LegalizerInfo &getLegalizerInfo() const { return LI; } |
| 97 | |
| 98 | private: |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 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 |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 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); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 116 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 | LegalizeResult |
| 128 | widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); |
| 129 | LegalizeResult |
| 130 | widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); |
| 131 | LegalizeResult |
| 132 | widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); |
| 133 | LegalizeResult |
| 134 | widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); |
| 135 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 136 | /// Helper function to split a wide generic register into bitwise blocks with |
| 137 | /// the given Type (which implies the number of blocks needed). The generic |
| 138 | /// registers created are appended to Ops, starting at bit 0 of Reg. |
| 139 | void extractParts(unsigned Reg, LLT Ty, int NumParts, |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 140 | SmallVectorImpl<unsigned> &VRegs); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 141 | |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 142 | /// Version which handles irregular splits. |
| 143 | bool extractParts(unsigned Reg, LLT RegTy, LLT MainTy, |
| 144 | LLT &LeftoverTy, |
| 145 | SmallVectorImpl<unsigned> &VRegs, |
| 146 | SmallVectorImpl<unsigned> &LeftoverVRegs); |
| 147 | |
| 148 | /// Helper function to build a wide generic register \p DstReg of type \p |
| 149 | /// RegTy from smaller parts. This will produce a G_MERGE_VALUES, |
| 150 | /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate |
| 151 | /// for the types. |
| 152 | /// |
| 153 | /// \p PartRegs must be registers of type \p PartTy. |
| 154 | /// |
| 155 | /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the |
| 156 | /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy. |
| 157 | void insertParts(unsigned DstReg, LLT ResultTy, |
| 158 | LLT PartTy, ArrayRef<unsigned> PartRegs, |
| 159 | LLT LeftoverTy = LLT(), ArrayRef<unsigned> LeftoverRegs = {}); |
| 160 | |
| 161 | LegalizeResult fewerElementsVectorImplicitDef(MachineInstr &MI, |
| 162 | unsigned TypeIdx, LLT NarrowTy); |
| 163 | |
| 164 | /// Legalize a simple vector instruction where all operands are the same type |
| 165 | /// by splitting into multiple components. |
| 166 | LegalizeResult fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx, |
| 167 | LLT NarrowTy); |
| 168 | |
| 169 | /// Legalize a instruction with a vector type where each operand may have a |
| 170 | /// different element type. All type indexes must have the same number of |
| 171 | /// elements. |
| 172 | LegalizeResult fewerElementsVectorMultiEltType(MachineInstr &MI, |
| 173 | unsigned TypeIdx, LLT NarrowTy); |
| 174 | |
| 175 | LegalizeResult fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx, |
| 176 | LLT NarrowTy); |
| 177 | |
| 178 | LegalizeResult |
| 179 | fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); |
| 180 | |
| 181 | LegalizeResult |
| 182 | fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); |
| 183 | |
| 184 | LegalizeResult |
| 185 | reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); |
| 186 | |
| 187 | LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, |
| 188 | LLT HalfTy, LLT ShiftAmtTy); |
| 189 | |
| 190 | LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
| 191 | LegalizeResult narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
| 192 | LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
| 193 | LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
| 194 | |
| 195 | LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
| 196 | |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 197 | LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
| 198 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 199 | MachineRegisterInfo &MRI; |
| 200 | const LegalizerInfo &LI; |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 201 | /// To keep track of changes made by the LegalizerHelper. |
| 202 | GISelChangeObserver &Observer; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 203 | }; |
| 204 | |
| 205 | /// Helper function that creates the given libcall. |
| 206 | LegalizerHelper::LegalizeResult |
| 207 | createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, |
| 208 | const CallLowering::ArgInfo &Result, |
| 209 | ArrayRef<CallLowering::ArgInfo> Args); |
| 210 | |
| 211 | } // End namespace llvm. |
| 212 | |
| 213 | #endif |