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   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