blob: 136356cc109792a7c15034d35fabea31d72e6f58 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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 Scull5e1ddfa2018-08-14 10:06:54 +01006//
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;
Andrew Walbran16937d02019-10-22 13:54:20 +010034class GISelChangeObserver;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035
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
Andrew Walbran16937d02019-10-22 13:54:20 +010051 LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer,
52 MachineIRBuilder &B);
53 LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
54 GISelChangeObserver &Observer, MachineIRBuilder &B);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010055
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 Walbran16937d02019-10-22 13:54:20 +010089 LLT MoreTy);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010090
91 /// Expose MIRBuilder so clients can set their own RecordInsertInstruction
92 /// functions
Andrew Walbran16937d02019-10-22 13:54:20 +010093 MachineIRBuilder &MIRBuilder;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010094
95 /// Expose LegalizerInfo so the clients can re-use.
96 const LegalizerInfo &getLegalizerInfo() const { return LI; }
97
98private:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010099 /// 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 Walbran16937d02019-10-22 13:54:20 +0100107 /// 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 Scullcdfcccc2018-10-05 20:58:37 +0100112 /// 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 Scull5e1ddfa2018-08-14 10:06:54 +0100116
Andrew Walbran16937d02019-10-22 13:54:20 +0100117 // 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 Scull5e1ddfa2018-08-14 10:06:54 +0100136 /// 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 Scullcdfcccc2018-10-05 20:58:37 +0100140 SmallVectorImpl<unsigned> &VRegs);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100141
Andrew Walbran16937d02019-10-22 13:54:20 +0100142 /// 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 Scull0372a572018-11-16 15:47:06 +0000197 LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
198
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100199 MachineRegisterInfo &MRI;
200 const LegalizerInfo &LI;
Andrew Walbran16937d02019-10-22 13:54:20 +0100201 /// To keep track of changes made by the LegalizerHelper.
202 GISelChangeObserver &Observer;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100203};
204
205/// Helper function that creates the given libcall.
206LegalizerHelper::LegalizeResult
207createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
208 const CallLowering::ArgInfo &Result,
209 ArrayRef<CallLowering::ArgInfo> Args);
210
211} // End namespace llvm.
212
213#endif