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