1 //== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
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> ->
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.
18 //===----------------------------------------------------------------------===//
20 #ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
21 #define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
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"
30 // Forward declarations.
33 class MachineRegisterInfo
;
34 class GISelChangeObserver
;
36 class LegalizerHelper
{
39 /// Instruction was already legal and no change was made to the
43 /// Instruction has been legalized and the MachineFunction changed.
46 /// Some kind of error has occurred and we could not legalize this
51 LegalizerHelper(MachineFunction
&MF
, GISelChangeObserver
&Observer
,
53 LegalizerHelper(MachineFunction
&MF
, const LegalizerInfo
&LI
,
54 GISelChangeObserver
&Observer
, MachineIRBuilder
&B
);
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.
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
);
65 /// Legalize an instruction by emiting a runtime library call instead.
66 LegalizeResult
libcall(MachineInstr
&MI
);
68 /// Legalize an instruction by reducing the width of the underlying scalar
70 LegalizeResult
narrowScalar(MachineInstr
&MI
, unsigned TypeIdx
, LLT NarrowTy
);
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
);
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
);
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
,
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
,
91 /// Expose MIRBuilder so clients can set their own RecordInsertInstruction
93 MachineIRBuilder
&MIRBuilder
;
95 /// Expose LegalizerInfo so the clients can re-use.
96 const LegalizerInfo
&getLegalizerInfo() const { return LI
; }
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
,
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
);
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
);
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
,
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
);
128 widenScalarMergeValues(MachineInstr
&MI
, unsigned TypeIdx
, LLT WideTy
);
130 widenScalarUnmergeValues(MachineInstr
&MI
, unsigned TypeIdx
, LLT WideTy
);
132 widenScalarExtract(MachineInstr
&MI
, unsigned TypeIdx
, LLT WideTy
);
134 widenScalarInsert(MachineInstr
&MI
, unsigned TypeIdx
, LLT WideTy
);
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
,
140 SmallVectorImpl
<unsigned> &VRegs
);
142 /// Version which handles irregular splits.
143 bool extractParts(unsigned Reg
, LLT RegTy
, LLT MainTy
,
145 SmallVectorImpl
<unsigned> &VRegs
,
146 SmallVectorImpl
<unsigned> &LeftoverVRegs
);
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
153 /// \p PartRegs must be registers of type \p PartTy.
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
= {});
161 LegalizeResult
fewerElementsVectorImplicitDef(MachineInstr
&MI
,
162 unsigned TypeIdx
, LLT NarrowTy
);
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
,
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
172 LegalizeResult
fewerElementsVectorMultiEltType(MachineInstr
&MI
,
173 unsigned TypeIdx
, LLT NarrowTy
);
175 LegalizeResult
fewerElementsVectorCasts(MachineInstr
&MI
, unsigned TypeIdx
,
179 fewerElementsVectorCmp(MachineInstr
&MI
, unsigned TypeIdx
, LLT NarrowTy
);
182 fewerElementsVectorSelect(MachineInstr
&MI
, unsigned TypeIdx
, LLT NarrowTy
);
185 reduceLoadStoreWidth(MachineInstr
&MI
, unsigned TypeIdx
, LLT NarrowTy
);
187 LegalizeResult
narrowScalarShiftByConstant(MachineInstr
&MI
, const APInt
&Amt
,
188 LLT HalfTy
, LLT ShiftAmtTy
);
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
);
195 LegalizeResult
narrowScalarSelect(MachineInstr
&MI
, unsigned TypeIdx
, LLT Ty
);
197 LegalizeResult
lowerBitCount(MachineInstr
&MI
, unsigned TypeIdx
, LLT Ty
);
199 MachineRegisterInfo
&MRI
;
200 const LegalizerInfo
&LI
;
201 /// To keep track of changes made by the LegalizerHelper.
202 GISelChangeObserver
&Observer
;
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
);
211 } // End namespace llvm.