]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Merge ^/head r316992 through r317215.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / CodeGen / GlobalISel / LegalizerHelper.cpp
1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file This file implements the LegalizerHelper class to legalize
11 /// individual instructions and the LegalizeMachineIR wrapper pass for the
12 /// primary legalization.
13 //
14 //===----------------------------------------------------------------------===//
15
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"
24
25 #include <sstream>
26
27 #define DEBUG_TYPE "legalize-mir"
28
29 using namespace llvm;
30
31 LegalizerHelper::LegalizerHelper(MachineFunction &MF)
32     : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
33   MIRBuilder.setMF(MF);
34 }
35
36 LegalizerHelper::LegalizeResult
37 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
38   auto Action = LI.getAction(MI, MRI);
39   switch (std::get<0>(Action)) {
40   case LegalizerInfo::Legal:
41     return AlreadyLegal;
42   case LegalizerInfo::Libcall:
43     return libcall(MI);
44   case LegalizerInfo::NarrowScalar:
45     return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
46   case LegalizerInfo::WidenScalar:
47     return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
48   case LegalizerInfo::Lower:
49     return lower(MI, std::get<1>(Action), std::get<2>(Action));
50   case LegalizerInfo::FewerElements:
51     return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
52   case LegalizerInfo::Custom:
53     return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
54                                                   : UnableToLegalize;
55   default:
56     return UnableToLegalize;
57   }
58 }
59
60 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
61                                    SmallVectorImpl<unsigned> &VRegs) {
62   for (int i = 0; i < NumParts; ++i)
63     VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
64   MIRBuilder.buildUnmerge(VRegs, Reg);
65 }
66
67 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
68   switch (Opcode) {
69   case TargetOpcode::G_FADD:
70     assert((Size == 32 || Size == 64) && "Unsupported size");
71     return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
72   case TargetOpcode::G_FREM:
73     return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
74   case TargetOpcode::G_FPOW:
75     return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
76   }
77   llvm_unreachable("Unknown libcall function");
78 }
79
80 LegalizerHelper::LegalizeResult
81 LegalizerHelper::libcall(MachineInstr &MI) {
82   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
83   unsigned Size = Ty.getSizeInBits();
84   MIRBuilder.setInstr(MI);
85
86   switch (MI.getOpcode()) {
87   default:
88     return UnableToLegalize;
89   case TargetOpcode::G_FADD:
90   case TargetOpcode::G_FPOW:
91   case TargetOpcode::G_FREM: {
92     auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
93     Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
94     auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
95     auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
96     auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
97     const char *Name = TLI.getLibcallName(Libcall);
98     MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
99     CLI.lowerCall(
100         MIRBuilder, TLI.getLibcallCallingConv(Libcall),
101         MachineOperand::CreateES(Name), {MI.getOperand(0).getReg(), Ty},
102         {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
103     MI.eraseFromParent();
104     return Legalized;
105   }
106   }
107 }
108
109 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
110                                                               unsigned TypeIdx,
111                                                               LLT NarrowTy) {
112   // FIXME: Don't know how to handle secondary types yet.
113   if (TypeIdx != 0)
114     return UnableToLegalize;
115
116   MIRBuilder.setInstr(MI);
117
118   switch (MI.getOpcode()) {
119   default:
120     return UnableToLegalize;
121   case TargetOpcode::G_ADD: {
122     // Expand in terms of carry-setting/consuming G_ADDE instructions.
123     int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
124                    NarrowTy.getSizeInBits();
125
126     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
127     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
128     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
129
130     unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
131     MIRBuilder.buildConstant(CarryIn, 0);
132
133     for (int i = 0; i < NumParts; ++i) {
134       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
135       unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
136
137       MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
138                             Src2Regs[i], CarryIn);
139
140       DstRegs.push_back(DstReg);
141       CarryIn = CarryOut;
142     }
143     unsigned DstReg = MI.getOperand(0).getReg();
144     MIRBuilder.buildMerge(DstReg, DstRegs);
145     MI.eraseFromParent();
146     return Legalized;
147   }
148   case TargetOpcode::G_INSERT: {
149     if (TypeIdx != 0)
150       return UnableToLegalize;
151
152     int64_t NarrowSize = NarrowTy.getSizeInBits();
153     int NumParts =
154         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
155
156     SmallVector<unsigned, 2> SrcRegs, DstRegs;
157     SmallVector<uint64_t, 2> Indexes;
158     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
159
160     unsigned OpReg = MI.getOperand(2).getReg();
161     int64_t OpStart = MI.getOperand(3).getImm();
162     int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
163     for (int i = 0; i < NumParts; ++i) {
164       unsigned DstStart = i * NarrowSize;
165
166       if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
167         // No part of the insert affects this subregister, forward the original.
168         DstRegs.push_back(SrcRegs[i]);
169         continue;
170       } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
171         // The entire subregister is defined by this insert, forward the new
172         // value.
173         DstRegs.push_back(OpReg);
174         continue;
175       }
176
177       // OpSegStart is where this destination segment would start in OpReg if it
178       // extended infinitely in both directions.
179       int64_t ExtractOffset, InsertOffset, SegSize;
180       if (OpStart < DstStart) {
181         InsertOffset = 0;
182         ExtractOffset = DstStart - OpStart;
183         SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
184       } else {
185         InsertOffset = OpStart - DstStart;
186         ExtractOffset = 0;
187         SegSize =
188             std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
189       }
190
191       unsigned SegReg = OpReg;
192       if (ExtractOffset != 0 || SegSize != OpSize) {
193         // A genuine extract is needed.
194         SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
195         MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
196       }
197
198       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
199       MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
200       DstRegs.push_back(DstReg);
201     }
202
203     assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
204     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
205     MI.eraseFromParent();
206     return Legalized;
207   }
208   case TargetOpcode::G_LOAD: {
209     unsigned NarrowSize = NarrowTy.getSizeInBits();
210     int NumParts =
211         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
212     LLT NarrowPtrTy = LLT::pointer(
213         MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
214
215     SmallVector<unsigned, 2> DstRegs;
216     for (int i = 0; i < NumParts; ++i) {
217       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
218       unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
219       unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
220
221       MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
222       MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
223       // TODO: This is conservatively correct, but we probably want to split the
224       // memory operands in the future.
225       MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
226
227       DstRegs.push_back(DstReg);
228     }
229     unsigned DstReg = MI.getOperand(0).getReg();
230     MIRBuilder.buildMerge(DstReg, DstRegs);
231     MI.eraseFromParent();
232     return Legalized;
233   }
234   case TargetOpcode::G_STORE: {
235     unsigned NarrowSize = NarrowTy.getSizeInBits();
236     int NumParts =
237         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
238     LLT NarrowPtrTy = LLT::pointer(
239         MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
240
241     SmallVector<unsigned, 2> SrcRegs;
242     extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
243
244     for (int i = 0; i < NumParts; ++i) {
245       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
246       unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
247       MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
248       MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
249       // TODO: This is conservatively correct, but we probably want to split the
250       // memory operands in the future.
251       MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
252     }
253     MI.eraseFromParent();
254     return Legalized;
255   }
256   case TargetOpcode::G_CONSTANT: {
257     unsigned NarrowSize = NarrowTy.getSizeInBits();
258     int NumParts =
259         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
260     const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
261     LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
262
263     SmallVector<unsigned, 2> DstRegs;
264     for (int i = 0; i < NumParts; ++i) {
265       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
266       ConstantInt *CI =
267           ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
268       MIRBuilder.buildConstant(DstReg, *CI);
269       DstRegs.push_back(DstReg);
270     }
271     unsigned DstReg = MI.getOperand(0).getReg();
272     MIRBuilder.buildMerge(DstReg, DstRegs);
273     MI.eraseFromParent();
274     return Legalized;
275   }
276   }
277 }
278
279 LegalizerHelper::LegalizeResult
280 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
281   MIRBuilder.setInstr(MI);
282
283   switch (MI.getOpcode()) {
284   default:
285     return UnableToLegalize;
286   case TargetOpcode::G_ADD:
287   case TargetOpcode::G_AND:
288   case TargetOpcode::G_MUL:
289   case TargetOpcode::G_OR:
290   case TargetOpcode::G_XOR:
291   case TargetOpcode::G_SUB:
292   case TargetOpcode::G_SHL: {
293     // Perform operation at larger width (any extension is fine here, high bits
294     // don't affect the result) and then truncate the result back to the
295     // original type.
296     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
297     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
298     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
299     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
300
301     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
302     MIRBuilder.buildInstr(MI.getOpcode())
303         .addDef(DstExt)
304         .addUse(Src1Ext)
305         .addUse(Src2Ext);
306
307     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
308     MI.eraseFromParent();
309     return Legalized;
310   }
311   case TargetOpcode::G_SDIV:
312   case TargetOpcode::G_UDIV:
313   case TargetOpcode::G_ASHR:
314   case TargetOpcode::G_LSHR: {
315     unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
316                              MI.getOpcode() == TargetOpcode::G_ASHR
317                          ? TargetOpcode::G_SEXT
318                          : TargetOpcode::G_ZEXT;
319
320     unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
321     MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
322         MI.getOperand(1).getReg());
323
324     unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
325     MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
326         MI.getOperand(2).getReg());
327
328     unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
329     MIRBuilder.buildInstr(MI.getOpcode())
330         .addDef(ResExt)
331         .addUse(LHSExt)
332         .addUse(RHSExt);
333
334     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
335     MI.eraseFromParent();
336     return Legalized;
337   }
338   case TargetOpcode::G_SELECT: {
339     if (TypeIdx != 0)
340       return UnableToLegalize;
341
342     // Perform operation at larger width (any extension is fine here, high bits
343     // don't affect the result) and then truncate the result back to the
344     // original type.
345     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
346     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
347     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
348     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
349
350     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
351     MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
352         .addDef(DstExt)
353         .addReg(MI.getOperand(1).getReg())
354         .addUse(Src1Ext)
355         .addUse(Src2Ext);
356
357     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
358     MI.eraseFromParent();
359     return Legalized;
360   }
361   case TargetOpcode::G_FPTOSI:
362   case TargetOpcode::G_FPTOUI: {
363     if (TypeIdx != 0)
364       return UnableToLegalize;
365
366     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
367     MIRBuilder.buildInstr(MI.getOpcode())
368         .addDef(DstExt)
369         .addUse(MI.getOperand(1).getReg());
370
371     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
372     MI.eraseFromParent();
373     return Legalized;
374   }
375   case TargetOpcode::G_SITOFP:
376   case TargetOpcode::G_UITOFP: {
377     if (TypeIdx != 1)
378       return UnableToLegalize;
379
380     unsigned Src = MI.getOperand(1).getReg();
381     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
382
383     if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
384       MIRBuilder.buildSExt(SrcExt, Src);
385     } else {
386       assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
387       MIRBuilder.buildZExt(SrcExt, Src);
388     }
389
390     MIRBuilder.buildInstr(MI.getOpcode())
391         .addDef(MI.getOperand(0).getReg())
392         .addUse(SrcExt);
393
394     MI.eraseFromParent();
395     return Legalized;
396   }
397   case TargetOpcode::G_INSERT: {
398     if (TypeIdx != 0)
399       return UnableToLegalize;
400
401     unsigned Src = MI.getOperand(1).getReg();
402     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
403     MIRBuilder.buildAnyExt(SrcExt, Src);
404
405     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
406     auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
407                                       MI.getOperand(3).getImm());
408     for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
409       MIB.addReg(MI.getOperand(OpNum).getReg());
410       MIB.addImm(MI.getOperand(OpNum + 1).getImm());
411     }
412
413     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
414     MI.eraseFromParent();
415     return Legalized;
416   }
417   case TargetOpcode::G_LOAD: {
418     assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
419                WideTy.getSizeInBits() &&
420            "illegal to increase number of bytes loaded");
421
422     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
423     MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
424                          **MI.memoperands_begin());
425     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
426     MI.eraseFromParent();
427     return Legalized;
428   }
429   case TargetOpcode::G_STORE: {
430     if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
431         WideTy != LLT::scalar(8))
432       return UnableToLegalize;
433
434     auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
435     auto Content = TLI.getBooleanContents(false, false);
436
437     unsigned ExtOp = TargetOpcode::G_ANYEXT;
438     if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
439       ExtOp = TargetOpcode::G_ZEXT;
440     else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
441       ExtOp = TargetOpcode::G_SEXT;
442     else
443       ExtOp = TargetOpcode::G_ANYEXT;
444
445     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
446     MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
447         MI.getOperand(0).getReg());
448     MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
449                           **MI.memoperands_begin());
450     MI.eraseFromParent();
451     return Legalized;
452   }
453   case TargetOpcode::G_CONSTANT: {
454     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
455     MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
456     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
457     MI.eraseFromParent();
458     return Legalized;
459   }
460   case TargetOpcode::G_FCONSTANT: {
461     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
462     MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
463     MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
464     MI.eraseFromParent();
465     return Legalized;
466   }
467   case TargetOpcode::G_BRCOND: {
468     unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
469     MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
470     MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
471     MI.eraseFromParent();
472     return Legalized;
473   }
474   case TargetOpcode::G_ICMP: {
475     assert(TypeIdx == 1 && "unable to legalize predicate");
476     bool IsSigned = CmpInst::isSigned(
477         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
478     unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
479     unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
480     if (IsSigned) {
481       MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
482       MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
483     } else {
484       MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
485       MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
486     }
487     MIRBuilder.buildICmp(
488         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
489         MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
490     MI.eraseFromParent();
491     return Legalized;
492   }
493   case TargetOpcode::G_GEP: {
494     assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
495     unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
496     MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
497     MI.getOperand(2).setReg(OffsetExt);
498     return Legalized;
499   }
500   }
501 }
502
503 LegalizerHelper::LegalizeResult
504 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
505   using namespace TargetOpcode;
506   MIRBuilder.setInstr(MI);
507
508   switch(MI.getOpcode()) {
509   default:
510     return UnableToLegalize;
511   case TargetOpcode::G_SREM:
512   case TargetOpcode::G_UREM: {
513     unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
514     MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
515         .addDef(QuotReg)
516         .addUse(MI.getOperand(1).getReg())
517         .addUse(MI.getOperand(2).getReg());
518
519     unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
520     MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
521     MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
522                         ProdReg);
523     MI.eraseFromParent();
524     return Legalized;
525   }
526   case TargetOpcode::G_SMULO:
527   case TargetOpcode::G_UMULO: {
528     // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
529     // result.
530     unsigned Res = MI.getOperand(0).getReg();
531     unsigned Overflow = MI.getOperand(1).getReg();
532     unsigned LHS = MI.getOperand(2).getReg();
533     unsigned RHS = MI.getOperand(3).getReg();
534
535     MIRBuilder.buildMul(Res, LHS, RHS);
536
537     unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
538                           ? TargetOpcode::G_SMULH
539                           : TargetOpcode::G_UMULH;
540
541     unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
542     MIRBuilder.buildInstr(Opcode)
543       .addDef(HiPart)
544       .addUse(LHS)
545       .addUse(RHS);
546
547     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
548     MIRBuilder.buildConstant(Zero, 0);
549     MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
550     MI.eraseFromParent();
551     return Legalized;
552   }
553   case TargetOpcode::G_FNEG: {
554     // TODO: Handle vector types once we are able to
555     // represent them.
556     if (Ty.isVector())
557       return UnableToLegalize;
558     unsigned Res = MI.getOperand(0).getReg();
559     Type *ZeroTy;
560     LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
561     switch (Ty.getSizeInBits()) {
562     case 16:
563       ZeroTy = Type::getHalfTy(Ctx);
564       break;
565     case 32:
566       ZeroTy = Type::getFloatTy(Ctx);
567       break;
568     case 64:
569       ZeroTy = Type::getDoubleTy(Ctx);
570       break;
571     default:
572       llvm_unreachable("unexpected floating-point type");
573     }
574     ConstantFP &ZeroForNegation =
575         *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
576     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
577     MIRBuilder.buildFConstant(Zero, ZeroForNegation);
578     MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
579         .addDef(Res)
580         .addUse(Zero)
581         .addUse(MI.getOperand(1).getReg());
582     MI.eraseFromParent();
583     return Legalized;
584   }
585   case TargetOpcode::G_FSUB: {
586     // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
587     // First, check if G_FNEG is marked as Lower. If so, we may
588     // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
589     if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
590       return UnableToLegalize;
591     unsigned Res = MI.getOperand(0).getReg();
592     unsigned LHS = MI.getOperand(1).getReg();
593     unsigned RHS = MI.getOperand(2).getReg();
594     unsigned Neg = MRI.createGenericVirtualRegister(Ty);
595     MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
596     MIRBuilder.buildInstr(TargetOpcode::G_FADD)
597         .addDef(Res)
598         .addUse(LHS)
599         .addUse(Neg);
600     MI.eraseFromParent();
601     return Legalized;
602   }
603   }
604 }
605
606 LegalizerHelper::LegalizeResult
607 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
608                                      LLT NarrowTy) {
609   // FIXME: Don't know how to handle secondary types yet.
610   if (TypeIdx != 0)
611     return UnableToLegalize;
612   switch (MI.getOpcode()) {
613   default:
614     return UnableToLegalize;
615   case TargetOpcode::G_ADD: {
616     unsigned NarrowSize = NarrowTy.getSizeInBits();
617     unsigned DstReg = MI.getOperand(0).getReg();
618     int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
619
620     MIRBuilder.setInstr(MI);
621
622     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
623     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
624     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
625
626     for (int i = 0; i < NumParts; ++i) {
627       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
628       MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
629       DstRegs.push_back(DstReg);
630     }
631
632     MIRBuilder.buildMerge(DstReg, DstRegs);
633     MI.eraseFromParent();
634     return Legalized;
635   }
636   }
637 }