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     const char *Name = TLI.getLibcallName(getRTLibDesc(MI.getOpcode(), Size));
118     MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
119     CLI.lowerCall(
120         MIRBuilder, MachineOperand::CreateES(Name),
121         {MI.getOperand(0).getReg(), Ty},
122         {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
123     MI.eraseFromParent();
124     return Legalized;
125   }
126   }
127 }
128 
129 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
130                                                               unsigned TypeIdx,
131                                                               LLT NarrowTy) {
132   // FIXME: Don't know how to handle secondary types yet.
133   if (TypeIdx != 0)
134     return UnableToLegalize;
135 
136   MIRBuilder.setInstr(MI);
137 
138   switch (MI.getOpcode()) {
139   default:
140     return UnableToLegalize;
141   case TargetOpcode::G_ADD: {
142     // Expand in terms of carry-setting/consuming G_ADDE instructions.
143     int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
144                    NarrowTy.getSizeInBits();
145 
146     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
147     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
148     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
149 
150     unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
151     MIRBuilder.buildConstant(CarryIn, 0);
152 
153     for (int i = 0; i < NumParts; ++i) {
154       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
155       unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
156 
157       MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
158                             Src2Regs[i], CarryIn);
159 
160       DstRegs.push_back(DstReg);
161       CarryIn = CarryOut;
162     }
163     unsigned DstReg = MI.getOperand(0).getReg();
164     MIRBuilder.buildMerge(DstReg, DstRegs);
165     MI.eraseFromParent();
166     return Legalized;
167   }
168   case TargetOpcode::G_INSERT: {
169     if (TypeIdx != 0)
170       return UnableToLegalize;
171 
172     int64_t NarrowSize = NarrowTy.getSizeInBits();
173     int NumParts =
174         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
175 
176     SmallVector<unsigned, 2> SrcRegs, DstRegs;
177     SmallVector<uint64_t, 2> Indexes;
178     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
179 
180     unsigned OpReg = MI.getOperand(2).getReg();
181     int64_t OpStart = MI.getOperand(3).getImm();
182     int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
183     for (int i = 0; i < NumParts; ++i) {
184       unsigned DstStart = i * NarrowSize;
185 
186       if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
187         // No part of the insert affects this subregister, forward the original.
188         DstRegs.push_back(SrcRegs[i]);
189         continue;
190       } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
191         // The entire subregister is defined by this insert, forward the new
192         // value.
193         DstRegs.push_back(OpReg);
194         continue;
195       }
196 
197       // OpSegStart is where this destination segment would start in OpReg if it
198       // extended infinitely in both directions.
199       int64_t ExtractOffset, InsertOffset, SegSize;
200       if (OpStart < DstStart) {
201         InsertOffset = 0;
202         ExtractOffset = DstStart - OpStart;
203         SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
204       } else {
205         InsertOffset = OpStart - DstStart;
206         ExtractOffset = 0;
207         SegSize =
208             std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
209       }
210 
211       unsigned SegReg = OpReg;
212       if (ExtractOffset != 0 || SegSize != OpSize) {
213         // A genuine extract is needed.
214         SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
215         MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
216       }
217 
218       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
219       MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
220       DstRegs.push_back(DstReg);
221     }
222 
223     assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
224     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
225     MI.eraseFromParent();
226     return Legalized;
227   }
228   case TargetOpcode::G_LOAD: {
229     unsigned NarrowSize = NarrowTy.getSizeInBits();
230     int NumParts =
231         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
232     LLT NarrowPtrTy = LLT::pointer(
233         MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
234 
235     SmallVector<unsigned, 2> DstRegs;
236     for (int i = 0; i < NumParts; ++i) {
237       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
238       unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
239       unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
240 
241       MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
242       MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
243       // TODO: This is conservatively correct, but we probably want to split the
244       // memory operands in the future.
245       MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
246 
247       DstRegs.push_back(DstReg);
248     }
249     unsigned DstReg = MI.getOperand(0).getReg();
250     MIRBuilder.buildMerge(DstReg, DstRegs);
251     MI.eraseFromParent();
252     return Legalized;
253   }
254   case TargetOpcode::G_STORE: {
255     unsigned NarrowSize = NarrowTy.getSizeInBits();
256     int NumParts =
257         MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
258     LLT NarrowPtrTy = LLT::pointer(
259         MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
260 
261     SmallVector<unsigned, 2> SrcRegs;
262     extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
263 
264     for (int i = 0; i < NumParts; ++i) {
265       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
266       unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
267       MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
268       MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
269       // TODO: This is conservatively correct, but we probably want to split the
270       // memory operands in the future.
271       MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
272     }
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     assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
431                WideTy.getSizeInBits() &&
432            "illegal to increase number of bytes modified by a store");
433 
434     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
435     MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg());
436     MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
437                           **MI.memoperands_begin());
438     MI.eraseFromParent();
439     return Legalized;
440   }
441   case TargetOpcode::G_CONSTANT: {
442     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
443     MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
444     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
445     MI.eraseFromParent();
446     return Legalized;
447   }
448   case TargetOpcode::G_FCONSTANT: {
449     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
450     MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
451     MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
452     MI.eraseFromParent();
453     return Legalized;
454   }
455   case TargetOpcode::G_BRCOND: {
456     unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
457     MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
458     MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
459     MI.eraseFromParent();
460     return Legalized;
461   }
462   case TargetOpcode::G_ICMP: {
463     assert(TypeIdx == 1 && "unable to legalize predicate");
464     bool IsSigned = CmpInst::isSigned(
465         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
466     unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
467     unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
468     if (IsSigned) {
469       MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
470       MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
471     } else {
472       MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
473       MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
474     }
475     MIRBuilder.buildICmp(
476         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
477         MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
478     MI.eraseFromParent();
479     return Legalized;
480   }
481   case TargetOpcode::G_GEP: {
482     assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
483     unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
484     MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
485     MI.getOperand(2).setReg(OffsetExt);
486     return Legalized;
487   }
488   }
489 }
490 
491 LegalizerHelper::LegalizeResult
492 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
493   using namespace TargetOpcode;
494   MIRBuilder.setInstr(MI);
495 
496   switch(MI.getOpcode()) {
497   default:
498     return UnableToLegalize;
499   case TargetOpcode::G_SREM:
500   case TargetOpcode::G_UREM: {
501     unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
502     MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
503         .addDef(QuotReg)
504         .addUse(MI.getOperand(1).getReg())
505         .addUse(MI.getOperand(2).getReg());
506 
507     unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
508     MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
509     MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
510                         ProdReg);
511     MI.eraseFromParent();
512     return Legalized;
513   }
514   case TargetOpcode::G_SMULO:
515   case TargetOpcode::G_UMULO: {
516     // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
517     // result.
518     unsigned Res = MI.getOperand(0).getReg();
519     unsigned Overflow = MI.getOperand(1).getReg();
520     unsigned LHS = MI.getOperand(2).getReg();
521     unsigned RHS = MI.getOperand(3).getReg();
522 
523     MIRBuilder.buildMul(Res, LHS, RHS);
524 
525     unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
526                           ? TargetOpcode::G_SMULH
527                           : TargetOpcode::G_UMULH;
528 
529     unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
530     MIRBuilder.buildInstr(Opcode)
531       .addDef(HiPart)
532       .addUse(LHS)
533       .addUse(RHS);
534 
535     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
536     MIRBuilder.buildConstant(Zero, 0);
537     MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
538     MI.eraseFromParent();
539     return Legalized;
540   }
541   case TargetOpcode::G_FNEG: {
542     // TODO: Handle vector types once we are able to
543     // represent them.
544     if (Ty.isVector())
545       return UnableToLegalize;
546     unsigned Res = MI.getOperand(0).getReg();
547     Type *ZeroTy;
548     LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
549     switch (Ty.getSizeInBits()) {
550     case 16:
551       ZeroTy = Type::getHalfTy(Ctx);
552       break;
553     case 32:
554       ZeroTy = Type::getFloatTy(Ctx);
555       break;
556     case 64:
557       ZeroTy = Type::getDoubleTy(Ctx);
558       break;
559     default:
560       llvm_unreachable("unexpected floating-point type");
561     }
562     ConstantFP &ZeroForNegation =
563         *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
564     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
565     MIRBuilder.buildFConstant(Zero, ZeroForNegation);
566     MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
567         .addDef(Res)
568         .addUse(Zero)
569         .addUse(MI.getOperand(1).getReg());
570     MI.eraseFromParent();
571     return Legalized;
572   }
573   case TargetOpcode::G_FSUB: {
574     // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
575     // First, check if G_FNEG is marked as Lower. If so, we may
576     // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
577     if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
578       return UnableToLegalize;
579     unsigned Res = MI.getOperand(0).getReg();
580     unsigned LHS = MI.getOperand(1).getReg();
581     unsigned RHS = MI.getOperand(2).getReg();
582     unsigned Neg = MRI.createGenericVirtualRegister(Ty);
583     MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
584     MIRBuilder.buildInstr(TargetOpcode::G_FADD)
585         .addDef(Res)
586         .addUse(LHS)
587         .addUse(Neg);
588     MI.eraseFromParent();
589     return Legalized;
590   }
591   }
592 }
593 
594 LegalizerHelper::LegalizeResult
595 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
596                                      LLT NarrowTy) {
597   // FIXME: Don't know how to handle secondary types yet.
598   if (TypeIdx != 0)
599     return UnableToLegalize;
600   switch (MI.getOpcode()) {
601   default:
602     return UnableToLegalize;
603   case TargetOpcode::G_ADD: {
604     unsigned NarrowSize = NarrowTy.getSizeInBits();
605     unsigned DstReg = MI.getOperand(0).getReg();
606     int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
607 
608     MIRBuilder.setInstr(MI);
609 
610     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
611     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
612     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
613 
614     for (int i = 0; i < NumParts; ++i) {
615       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
616       MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
617       DstRegs.push_back(DstReg);
618     }
619 
620     MIRBuilder.buildMerge(DstReg, DstRegs);
621     MI.eraseFromParent();
622     return Legalized;
623   }
624   }
625 }
626