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