1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \file This file implements the LegalizerHelper class to legalize
11 /// individual instructions and the LegalizeMachineIR wrapper pass for the
12 /// primary legalization.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
18 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Target/TargetLowering.h"
23 #include "llvm/Target/TargetSubtargetInfo.h"
27 #define DEBUG_TYPE "legalize-mir"
31 LegalizerHelper::LegalizerHelper(MachineFunction &MF)
32 : MRI(MF.getRegInfo()) {
36 LegalizerHelper::LegalizeResult
37 LegalizerHelper::legalizeInstrStep(MachineInstr &MI,
38 const LegalizerInfo &LegalizerInfo) {
39 auto Action = LegalizerInfo.getAction(MI, MRI);
40 switch (std::get<0>(Action)) {
41 case LegalizerInfo::Legal:
43 case LegalizerInfo::Libcall:
45 case LegalizerInfo::NarrowScalar:
46 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
47 case LegalizerInfo::WidenScalar:
48 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
49 case LegalizerInfo::Lower:
50 return lower(MI, std::get<1>(Action), std::get<2>(Action));
51 case LegalizerInfo::FewerElements:
52 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
54 return UnableToLegalize;
58 LegalizerHelper::LegalizeResult
59 LegalizerHelper::legalizeInstr(MachineInstr &MI,
60 const LegalizerInfo &LegalizerInfo) {
61 SmallVector<MachineInstr *, 4> WorkList;
62 MIRBuilder.recordInsertions(
63 [&](MachineInstr *MI) { WorkList.push_back(MI); });
64 WorkList.push_back(&MI);
70 Res = legalizeInstrStep(*WorkList[Idx], LegalizerInfo);
71 if (Res == UnableToLegalize) {
72 MIRBuilder.stopRecordingInsertions();
73 return UnableToLegalize;
75 Changed |= Res == Legalized;
77 } while (Idx < WorkList.size());
79 MIRBuilder.stopRecordingInsertions();
81 return Changed ? Legalized : AlreadyLegal;
84 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
85 SmallVectorImpl<unsigned> &VRegs) {
86 unsigned Size = Ty.getSizeInBits();
87 SmallVector<uint64_t, 4> Indexes;
88 for (int i = 0; i < NumParts; ++i) {
89 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
90 Indexes.push_back(i * Size);
92 MIRBuilder.buildExtract(VRegs, Indexes, Reg);
95 LegalizerHelper::LegalizeResult
96 LegalizerHelper::libcall(MachineInstr &MI) {
97 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
98 unsigned Size = Ty.getSizeInBits();
99 MIRBuilder.setInstr(MI);
101 switch (MI.getOpcode()) {
103 return UnableToLegalize;
104 case TargetOpcode::G_FREM: {
105 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
106 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
107 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
108 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
110 TLI.getLibcallName(Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32);
113 MIRBuilder, MachineOperand::CreateES(Name),
114 {MI.getOperand(0).getReg(), Ty},
115 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
116 MI.eraseFromParent();
122 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
125 // FIXME: Don't know how to handle secondary types yet.
127 return UnableToLegalize;
128 switch (MI.getOpcode()) {
130 return UnableToLegalize;
131 case TargetOpcode::G_ADD: {
132 // Expand in terms of carry-setting/consuming G_ADDE instructions.
133 unsigned NarrowSize = NarrowTy.getSizeInBits();
134 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
135 NarrowTy.getSizeInBits();
137 MIRBuilder.setInstr(MI);
139 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
140 SmallVector<uint64_t, 2> Indexes;
141 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
142 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
144 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
145 MIRBuilder.buildConstant(CarryIn, 0);
147 for (int i = 0; i < NumParts; ++i) {
148 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
149 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
151 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
152 Src2Regs[i], CarryIn);
154 DstRegs.push_back(DstReg);
155 Indexes.push_back(i * NarrowSize);
158 unsigned DstReg = MI.getOperand(0).getReg();
159 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
160 MI.eraseFromParent();
166 LegalizerHelper::LegalizeResult
167 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
168 MIRBuilder.setInstr(MI);
170 switch (MI.getOpcode()) {
172 return UnableToLegalize;
173 case TargetOpcode::G_ADD:
174 case TargetOpcode::G_AND:
175 case TargetOpcode::G_MUL:
176 case TargetOpcode::G_OR:
177 case TargetOpcode::G_XOR:
178 case TargetOpcode::G_SUB: {
179 // Perform operation at larger width (any extension is fine here, high bits
180 // don't affect the result) and then truncate the result back to the
182 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
183 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
184 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
185 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
187 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
188 MIRBuilder.buildInstr(MI.getOpcode())
193 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
194 MI.eraseFromParent();
197 case TargetOpcode::G_SDIV:
198 case TargetOpcode::G_UDIV: {
199 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV
200 ? TargetOpcode::G_SEXT
201 : TargetOpcode::G_ZEXT;
203 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
204 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
205 MI.getOperand(1).getReg());
207 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
208 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
209 MI.getOperand(2).getReg());
211 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
212 MIRBuilder.buildInstr(MI.getOpcode())
217 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
218 MI.eraseFromParent();
221 case TargetOpcode::G_LOAD: {
222 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
223 WideTy.getSizeInBits() &&
224 "illegal to increase number of bytes loaded");
226 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
227 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
228 **MI.memoperands_begin());
229 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
230 MI.eraseFromParent();
233 case TargetOpcode::G_STORE: {
234 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
235 WideTy.getSizeInBits() &&
236 "illegal to increase number of bytes modified by a store");
238 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
239 MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
240 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
241 **MI.memoperands_begin());
242 MI.eraseFromParent();
245 case TargetOpcode::G_CONSTANT: {
246 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
247 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
248 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
249 MI.eraseFromParent();
252 case TargetOpcode::G_FCONSTANT: {
253 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
254 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
255 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
256 MI.eraseFromParent();
259 case TargetOpcode::G_BRCOND: {
260 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
261 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
262 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
263 MI.eraseFromParent();
266 case TargetOpcode::G_ICMP: {
267 assert(TypeIdx == 1 && "unable to legalize predicate");
268 bool IsSigned = CmpInst::isSigned(
269 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
270 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
271 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
273 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
274 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
276 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
277 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
279 MIRBuilder.buildICmp(
280 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
281 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
282 MI.eraseFromParent();
285 case TargetOpcode::G_GEP: {
286 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
287 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
288 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
289 MI.getOperand(2).setReg(OffsetExt);
295 LegalizerHelper::LegalizeResult
296 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
297 using namespace TargetOpcode;
298 MIRBuilder.setInstr(MI);
300 switch(MI.getOpcode()) {
302 return UnableToLegalize;
303 case TargetOpcode::G_SREM:
304 case TargetOpcode::G_UREM: {
305 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
306 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
308 .addUse(MI.getOperand(1).getReg())
309 .addUse(MI.getOperand(2).getReg());
311 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
312 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
313 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
315 MI.eraseFromParent();
321 LegalizerHelper::LegalizeResult
322 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
324 // FIXME: Don't know how to handle secondary types yet.
326 return UnableToLegalize;
327 switch (MI.getOpcode()) {
329 return UnableToLegalize;
330 case TargetOpcode::G_ADD: {
331 unsigned NarrowSize = NarrowTy.getSizeInBits();
332 unsigned DstReg = MI.getOperand(0).getReg();
333 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
335 MIRBuilder.setInstr(MI);
337 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
338 SmallVector<uint64_t, 2> Indexes;
339 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
340 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
342 for (int i = 0; i < NumParts; ++i) {
343 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
344 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
345 DstRegs.push_back(DstReg);
346 Indexes.push_back(i * NarrowSize);
349 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes);
350 MI.eraseFromParent();