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     assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
432                WideTy.getSizeInBits() &&
433            "illegal to increase number of bytes modified by a store");
434 
435     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
436     MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
437     MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
438                           **MI.memoperands_begin());
439     MI.eraseFromParent();
440     return Legalized;
441   }
442   case TargetOpcode::G_CONSTANT: {
443     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
444     MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
445     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
446     MI.eraseFromParent();
447     return Legalized;
448   }
449   case TargetOpcode::G_FCONSTANT: {
450     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
451     MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
452     MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
453     MI.eraseFromParent();
454     return Legalized;
455   }
456   case TargetOpcode::G_BRCOND: {
457     unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
458     MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
459     MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
460     MI.eraseFromParent();
461     return Legalized;
462   }
463   case TargetOpcode::G_ICMP: {
464     assert(TypeIdx == 1 && "unable to legalize predicate");
465     bool IsSigned = CmpInst::isSigned(
466         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
467     unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
468     unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
469     if (IsSigned) {
470       MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
471       MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
472     } else {
473       MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
474       MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
475     }
476     MIRBuilder.buildICmp(
477         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
478         MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
479     MI.eraseFromParent();
480     return Legalized;
481   }
482   case TargetOpcode::G_GEP: {
483     assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
484     unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
485     MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
486     MI.getOperand(2).setReg(OffsetExt);
487     return Legalized;
488   }
489   }
490 }
491 
492 LegalizerHelper::LegalizeResult
493 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
494   using namespace TargetOpcode;
495   MIRBuilder.setInstr(MI);
496 
497   switch(MI.getOpcode()) {
498   default:
499     return UnableToLegalize;
500   case TargetOpcode::G_SREM:
501   case TargetOpcode::G_UREM: {
502     unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
503     MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
504         .addDef(QuotReg)
505         .addUse(MI.getOperand(1).getReg())
506         .addUse(MI.getOperand(2).getReg());
507 
508     unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
509     MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
510     MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
511                         ProdReg);
512     MI.eraseFromParent();
513     return Legalized;
514   }
515   case TargetOpcode::G_SMULO:
516   case TargetOpcode::G_UMULO: {
517     // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
518     // result.
519     unsigned Res = MI.getOperand(0).getReg();
520     unsigned Overflow = MI.getOperand(1).getReg();
521     unsigned LHS = MI.getOperand(2).getReg();
522     unsigned RHS = MI.getOperand(3).getReg();
523 
524     MIRBuilder.buildMul(Res, LHS, RHS);
525 
526     unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
527                           ? TargetOpcode::G_SMULH
528                           : TargetOpcode::G_UMULH;
529 
530     unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
531     MIRBuilder.buildInstr(Opcode)
532       .addDef(HiPart)
533       .addUse(LHS)
534       .addUse(RHS);
535 
536     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
537     MIRBuilder.buildConstant(Zero, 0);
538     MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
539     MI.eraseFromParent();
540     return Legalized;
541   }
542   case TargetOpcode::G_FNEG: {
543     // TODO: Handle vector types once we are able to
544     // represent them.
545     if (Ty.isVector())
546       return UnableToLegalize;
547     unsigned Res = MI.getOperand(0).getReg();
548     Type *ZeroTy;
549     LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
550     switch (Ty.getSizeInBits()) {
551     case 16:
552       ZeroTy = Type::getHalfTy(Ctx);
553       break;
554     case 32:
555       ZeroTy = Type::getFloatTy(Ctx);
556       break;
557     case 64:
558       ZeroTy = Type::getDoubleTy(Ctx);
559       break;
560     default:
561       llvm_unreachable("unexpected floating-point type");
562     }
563     ConstantFP &ZeroForNegation =
564         *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
565     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
566     MIRBuilder.buildFConstant(Zero, ZeroForNegation);
567     MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
568         .addDef(Res)
569         .addUse(Zero)
570         .addUse(MI.getOperand(1).getReg());
571     MI.eraseFromParent();
572     return Legalized;
573   }
574   case TargetOpcode::G_FSUB: {
575     // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
576     // First, check if G_FNEG is marked as Lower. If so, we may
577     // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
578     if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
579       return UnableToLegalize;
580     unsigned Res = MI.getOperand(0).getReg();
581     unsigned LHS = MI.getOperand(1).getReg();
582     unsigned RHS = MI.getOperand(2).getReg();
583     unsigned Neg = MRI.createGenericVirtualRegister(Ty);
584     MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
585     MIRBuilder.buildInstr(TargetOpcode::G_FADD)
586         .addDef(Res)
587         .addUse(LHS)
588         .addUse(Neg);
589     MI.eraseFromParent();
590     return Legalized;
591   }
592   }
593 }
594 
595 LegalizerHelper::LegalizeResult
596 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
597                                      LLT NarrowTy) {
598   // FIXME: Don't know how to handle secondary types yet.
599   if (TypeIdx != 0)
600     return UnableToLegalize;
601   switch (MI.getOpcode()) {
602   default:
603     return UnableToLegalize;
604   case TargetOpcode::G_ADD: {
605     unsigned NarrowSize = NarrowTy.getSizeInBits();
606     unsigned DstReg = MI.getOperand(0).getReg();
607     int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
608 
609     MIRBuilder.setInstr(MI);
610 
611     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
612     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
613     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
614 
615     for (int i = 0; i < NumParts; ++i) {
616       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
617       MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
618       DstRegs.push_back(DstReg);
619     }
620 
621     MIRBuilder.buildMerge(DstReg, DstRegs);
622     MI.eraseFromParent();
623     return Legalized;
624   }
625   }
626 }
627