/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
Line | Count | Source |
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. |
96 | 239k | 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 |
204 | | reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); |
205 | | |
206 | | LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, |
207 | | LLT HalfTy, LLT ShiftAmtTy); |
208 | | |
209 | | LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
210 | | LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); |
211 | | LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
212 | | LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
213 | | |
214 | | LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
215 | | LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
216 | | |
217 | | LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
218 | | |
219 | | LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); |
220 | | LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
221 | | LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
222 | | LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
223 | | LegalizeResult lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty); |
224 | | LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); |
225 | | |
226 | | private: |
227 | | MachineRegisterInfo &MRI; |
228 | | const LegalizerInfo &LI; |
229 | | /// To keep track of changes made by the LegalizerHelper. |
230 | | GISelChangeObserver &Observer; |
231 | | }; |
232 | | |
233 | | /// Helper function that creates the given libcall. |
234 | | LegalizerHelper::LegalizeResult |
235 | | createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, |
236 | | const CallLowering::ArgInfo &Result, |
237 | | ArrayRef<CallLowering::ArgInfo> Args); |
238 | | |
239 | | /// Create a libcall to memcpy et al. |
240 | | LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder, |
241 | | MachineRegisterInfo &MRI, |
242 | | MachineInstr &MI); |
243 | | |
244 | | } // End namespace llvm. |
245 | | |
246 | | #endif |