LegalizerHelper.h revision 360784
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
29namespace llvm {
30// Forward declarations.
31class LegalizerInfo;
32class Legalizer;
33class MachineRegisterInfo;
34class GISelChangeObserver;
35
36class LegalizerHelper {
37public:
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
98private:
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
173public:
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
245private:
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.
253LegalizerHelper::LegalizeResult
254createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
255              const CallLowering::ArgInfo &Result,
256              ArrayRef<CallLowering::ArgInfo> Args);
257
258/// Create a libcall to memcpy et al.
259LegalizerHelper::LegalizeResult createMemLibcall(MachineIRBuilder &MIRBuilder,
260                                                 MachineRegisterInfo &MRI,
261                                                 MachineInstr &MI);
262
263} // End namespace llvm.
264
265#endif
266