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/CodeGen/TargetLowering.h"
21 #include "llvm/CodeGen/TargetSubtargetInfo.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 
26 #define DEBUG_TYPE "legalizer"
27 
28 using namespace llvm;
29 using namespace LegalizeActions;
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   DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
39 
40   auto Step = LI.getAction(MI, MRI);
41   switch (Step.Action) {
42   case Legal:
43     DEBUG(dbgs() << ".. Already legal\n");
44     return AlreadyLegal;
45   case Libcall:
46     DEBUG(dbgs() << ".. Convert to libcall\n");
47     return libcall(MI);
48   case NarrowScalar:
49     DEBUG(dbgs() << ".. Narrow scalar\n");
50     return narrowScalar(MI, Step.TypeIdx, Step.NewType);
51   case WidenScalar:
52     DEBUG(dbgs() << ".. Widen scalar\n");
53     return widenScalar(MI, Step.TypeIdx, Step.NewType);
54   case Lower:
55     DEBUG(dbgs() << ".. Lower\n");
56     return lower(MI, Step.TypeIdx, Step.NewType);
57   case FewerElements:
58     DEBUG(dbgs() << ".. Reduce number of elements\n");
59     return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
60   case Custom:
61     DEBUG(dbgs() << ".. Custom legalization\n");
62     return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
63                                                   : UnableToLegalize;
64   default:
65     DEBUG(dbgs() << ".. Unable to legalize\n");
66     return UnableToLegalize;
67   }
68 }
69 
70 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
71                                    SmallVectorImpl<unsigned> &VRegs) {
72   for (int i = 0; i < NumParts; ++i)
73     VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
74   MIRBuilder.buildUnmerge(VRegs, Reg);
75 }
76 
77 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
78   switch (Opcode) {
79   case TargetOpcode::G_SDIV:
80     assert(Size == 32 && "Unsupported size");
81     return RTLIB::SDIV_I32;
82   case TargetOpcode::G_UDIV:
83     assert(Size == 32 && "Unsupported size");
84     return RTLIB::UDIV_I32;
85   case TargetOpcode::G_SREM:
86     assert(Size == 32 && "Unsupported size");
87     return RTLIB::SREM_I32;
88   case TargetOpcode::G_UREM:
89     assert(Size == 32 && "Unsupported size");
90     return RTLIB::UREM_I32;
91   case TargetOpcode::G_FADD:
92     assert((Size == 32 || Size == 64) && "Unsupported size");
93     return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
94   case TargetOpcode::G_FSUB:
95     assert((Size == 32 || Size == 64) && "Unsupported size");
96     return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32;
97   case TargetOpcode::G_FMUL:
98     assert((Size == 32 || Size == 64) && "Unsupported size");
99     return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32;
100   case TargetOpcode::G_FDIV:
101     assert((Size == 32 || Size == 64) && "Unsupported size");
102     return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32;
103   case TargetOpcode::G_FREM:
104     return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
105   case TargetOpcode::G_FPOW:
106     return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
107   case TargetOpcode::G_FMA:
108     assert((Size == 32 || Size == 64) && "Unsupported size");
109     return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32;
110   }
111   llvm_unreachable("Unknown libcall function");
112 }
113 
114 LegalizerHelper::LegalizeResult
115 llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
116                     const CallLowering::ArgInfo &Result,
117                     ArrayRef<CallLowering::ArgInfo> Args) {
118   auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
119   auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
120   const char *Name = TLI.getLibcallName(Libcall);
121 
122   MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
123   if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
124                      MachineOperand::CreateES(Name), Result, Args))
125     return LegalizerHelper::UnableToLegalize;
126 
127   return LegalizerHelper::Legalized;
128 }
129 
130 // Useful for libcalls where all operands have the same type.
131 static LegalizerHelper::LegalizeResult
132 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
133               Type *OpType) {
134   auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
135 
136   SmallVector<CallLowering::ArgInfo, 3> Args;
137   for (unsigned i = 1; i < MI.getNumOperands(); i++)
138     Args.push_back({MI.getOperand(i).getReg(), OpType});
139   return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType},
140                        Args);
141 }
142 
143 static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
144                                        Type *FromType) {
145   auto ToMVT = MVT::getVT(ToType);
146   auto FromMVT = MVT::getVT(FromType);
147 
148   switch (Opcode) {
149   case TargetOpcode::G_FPEXT:
150     return RTLIB::getFPEXT(FromMVT, ToMVT);
151   case TargetOpcode::G_FPTRUNC:
152     return RTLIB::getFPROUND(FromMVT, ToMVT);
153   case TargetOpcode::G_FPTOSI:
154     return RTLIB::getFPTOSINT(FromMVT, ToMVT);
155   case TargetOpcode::G_FPTOUI:
156     return RTLIB::getFPTOUINT(FromMVT, ToMVT);
157   case TargetOpcode::G_SITOFP:
158     return RTLIB::getSINTTOFP(FromMVT, ToMVT);
159   case TargetOpcode::G_UITOFP:
160     return RTLIB::getUINTTOFP(FromMVT, ToMVT);
161   }
162   llvm_unreachable("Unsupported libcall function");
163 }
164 
165 static LegalizerHelper::LegalizeResult
166 conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
167                   Type *FromType) {
168   RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
169   return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType},
170                        {{MI.getOperand(1).getReg(), FromType}});
171 }
172 
173 LegalizerHelper::LegalizeResult
174 LegalizerHelper::libcall(MachineInstr &MI) {
175   LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
176   unsigned Size = LLTy.getSizeInBits();
177   auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
178 
179   MIRBuilder.setInstr(MI);
180 
181   switch (MI.getOpcode()) {
182   default:
183     return UnableToLegalize;
184   case TargetOpcode::G_SDIV:
185   case TargetOpcode::G_UDIV:
186   case TargetOpcode::G_SREM:
187   case TargetOpcode::G_UREM: {
188     Type *HLTy = Type::getInt32Ty(Ctx);
189     auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
190     if (Status != Legalized)
191       return Status;
192     break;
193   }
194   case TargetOpcode::G_FADD:
195   case TargetOpcode::G_FSUB:
196   case TargetOpcode::G_FMUL:
197   case TargetOpcode::G_FDIV:
198   case TargetOpcode::G_FMA:
199   case TargetOpcode::G_FPOW:
200   case TargetOpcode::G_FREM: {
201     Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
202     auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy);
203     if (Status != Legalized)
204       return Status;
205     break;
206   }
207   case TargetOpcode::G_FPEXT: {
208     // FIXME: Support other floating point types (half, fp128 etc)
209     unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
210     unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
211     if (ToSize != 64 || FromSize != 32)
212       return UnableToLegalize;
213     LegalizeResult Status = conversionLibcall(
214         MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx));
215     if (Status != Legalized)
216       return Status;
217     break;
218   }
219   case TargetOpcode::G_FPTRUNC: {
220     // FIXME: Support other floating point types (half, fp128 etc)
221     unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
222     unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
223     if (ToSize != 32 || FromSize != 64)
224       return UnableToLegalize;
225     LegalizeResult Status = conversionLibcall(
226         MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx));
227     if (Status != Legalized)
228       return Status;
229     break;
230   }
231   case TargetOpcode::G_FPTOSI:
232   case TargetOpcode::G_FPTOUI: {
233     // FIXME: Support other types
234     unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
235     unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
236     if (ToSize != 32 || (FromSize != 32 && FromSize != 64))
237       return UnableToLegalize;
238     LegalizeResult Status = conversionLibcall(
239         MI, MIRBuilder, Type::getInt32Ty(Ctx),
240         FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx));
241     if (Status != Legalized)
242       return Status;
243     break;
244   }
245   case TargetOpcode::G_SITOFP:
246   case TargetOpcode::G_UITOFP: {
247     // FIXME: Support other types
248     unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
249     unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
250     if (FromSize != 32 || (ToSize != 32 && ToSize != 64))
251       return UnableToLegalize;
252     LegalizeResult Status = conversionLibcall(
253         MI, MIRBuilder,
254         ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx),
255         Type::getInt32Ty(Ctx));
256     if (Status != Legalized)
257       return Status;
258     break;
259   }
260   }
261 
262   MI.eraseFromParent();
263   return Legalized;
264 }
265 
266 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
267                                                               unsigned TypeIdx,
268                                                               LLT NarrowTy) {
269   // FIXME: Don't know how to handle secondary types yet.
270   if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT)
271     return UnableToLegalize;
272 
273   MIRBuilder.setInstr(MI);
274 
275   int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
276   int64_t NarrowSize = NarrowTy.getSizeInBits();
277 
278   switch (MI.getOpcode()) {
279   default:
280     return UnableToLegalize;
281   case TargetOpcode::G_IMPLICIT_DEF: {
282     // FIXME: add support for when SizeOp0 isn't an exact multiple of
283     // NarrowSize.
284     if (SizeOp0 % NarrowSize != 0)
285       return UnableToLegalize;
286     int NumParts = SizeOp0 / NarrowSize;
287 
288     SmallVector<unsigned, 2> DstRegs;
289     for (int i = 0; i < NumParts; ++i)
290       DstRegs.push_back(
291           MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg());
292     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
293     MI.eraseFromParent();
294     return Legalized;
295   }
296   case TargetOpcode::G_ADD: {
297     // FIXME: add support for when SizeOp0 isn't an exact multiple of
298     // NarrowSize.
299     if (SizeOp0 % NarrowSize != 0)
300       return UnableToLegalize;
301     // Expand in terms of carry-setting/consuming G_ADDE instructions.
302     int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
303 
304     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
305     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
306     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
307 
308     unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
309     MIRBuilder.buildConstant(CarryIn, 0);
310 
311     for (int i = 0; i < NumParts; ++i) {
312       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
313       unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
314 
315       MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
316                             Src2Regs[i], CarryIn);
317 
318       DstRegs.push_back(DstReg);
319       CarryIn = CarryOut;
320     }
321     unsigned DstReg = MI.getOperand(0).getReg();
322     MIRBuilder.buildMerge(DstReg, DstRegs);
323     MI.eraseFromParent();
324     return Legalized;
325   }
326   case TargetOpcode::G_EXTRACT: {
327     if (TypeIdx != 1)
328       return UnableToLegalize;
329 
330     int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
331     // FIXME: add support for when SizeOp1 isn't an exact multiple of
332     // NarrowSize.
333     if (SizeOp1 % NarrowSize != 0)
334       return UnableToLegalize;
335     int NumParts = SizeOp1 / NarrowSize;
336 
337     SmallVector<unsigned, 2> SrcRegs, DstRegs;
338     SmallVector<uint64_t, 2> Indexes;
339     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
340 
341     unsigned OpReg = MI.getOperand(0).getReg();
342     int64_t OpStart = MI.getOperand(2).getImm();
343     int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
344     for (int i = 0; i < NumParts; ++i) {
345       unsigned SrcStart = i * NarrowSize;
346 
347       if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
348         // No part of the extract uses this subregister, ignore it.
349         continue;
350       } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
351         // The entire subregister is extracted, forward the value.
352         DstRegs.push_back(SrcRegs[i]);
353         continue;
354       }
355 
356       // OpSegStart is where this destination segment would start in OpReg if it
357       // extended infinitely in both directions.
358       int64_t ExtractOffset, SegSize;
359       if (OpStart < SrcStart) {
360         ExtractOffset = 0;
361         SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
362       } else {
363         ExtractOffset = OpStart - SrcStart;
364         SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
365       }
366 
367       unsigned SegReg = SrcRegs[i];
368       if (ExtractOffset != 0 || SegSize != NarrowSize) {
369         // A genuine extract is needed.
370         SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
371         MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
372       }
373 
374       DstRegs.push_back(SegReg);
375     }
376 
377     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
378     MI.eraseFromParent();
379     return Legalized;
380   }
381   case TargetOpcode::G_INSERT: {
382     // FIXME: add support for when SizeOp0 isn't an exact multiple of
383     // NarrowSize.
384     if (SizeOp0 % NarrowSize != 0)
385       return UnableToLegalize;
386 
387     int NumParts = SizeOp0 / NarrowSize;
388 
389     SmallVector<unsigned, 2> SrcRegs, DstRegs;
390     SmallVector<uint64_t, 2> Indexes;
391     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
392 
393     unsigned OpReg = MI.getOperand(2).getReg();
394     int64_t OpStart = MI.getOperand(3).getImm();
395     int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
396     for (int i = 0; i < NumParts; ++i) {
397       unsigned DstStart = i * NarrowSize;
398 
399       if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
400         // No part of the insert affects this subregister, forward the original.
401         DstRegs.push_back(SrcRegs[i]);
402         continue;
403       } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
404         // The entire subregister is defined by this insert, forward the new
405         // value.
406         DstRegs.push_back(OpReg);
407         continue;
408       }
409 
410       // OpSegStart is where this destination segment would start in OpReg if it
411       // extended infinitely in both directions.
412       int64_t ExtractOffset, InsertOffset, SegSize;
413       if (OpStart < DstStart) {
414         InsertOffset = 0;
415         ExtractOffset = DstStart - OpStart;
416         SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
417       } else {
418         InsertOffset = OpStart - DstStart;
419         ExtractOffset = 0;
420         SegSize =
421             std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
422       }
423 
424       unsigned SegReg = OpReg;
425       if (ExtractOffset != 0 || SegSize != OpSize) {
426         // A genuine extract is needed.
427         SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
428         MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
429       }
430 
431       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
432       MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
433       DstRegs.push_back(DstReg);
434     }
435 
436     assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
437     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
438     MI.eraseFromParent();
439     return Legalized;
440   }
441   case TargetOpcode::G_LOAD: {
442     // FIXME: add support for when SizeOp0 isn't an exact multiple of
443     // NarrowSize.
444     if (SizeOp0 % NarrowSize != 0)
445       return UnableToLegalize;
446     int NumParts = SizeOp0 / NarrowSize;
447     LLT OffsetTy = LLT::scalar(
448         MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
449 
450     SmallVector<unsigned, 2> DstRegs;
451     for (int i = 0; i < NumParts; ++i) {
452       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
453       unsigned SrcReg = 0;
454       unsigned Adjustment = i * NarrowSize / 8;
455 
456       MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
457                                 Adjustment);
458 
459       // TODO: This is conservatively correct, but we probably want to split the
460       // memory operands in the future.
461       MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
462 
463       DstRegs.push_back(DstReg);
464     }
465     unsigned DstReg = MI.getOperand(0).getReg();
466     MIRBuilder.buildMerge(DstReg, DstRegs);
467     MI.eraseFromParent();
468     return Legalized;
469   }
470   case TargetOpcode::G_STORE: {
471     // FIXME: add support for when SizeOp0 isn't an exact multiple of
472     // NarrowSize.
473     if (SizeOp0 % NarrowSize != 0)
474       return UnableToLegalize;
475     int NumParts = SizeOp0 / NarrowSize;
476     LLT OffsetTy = LLT::scalar(
477         MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
478 
479     SmallVector<unsigned, 2> SrcRegs;
480     extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
481 
482     for (int i = 0; i < NumParts; ++i) {
483       unsigned DstReg = 0;
484       unsigned Adjustment = i * NarrowSize / 8;
485 
486       MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
487                                 Adjustment);
488 
489       // TODO: This is conservatively correct, but we probably want to split the
490       // memory operands in the future.
491       MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
492     }
493     MI.eraseFromParent();
494     return Legalized;
495   }
496   case TargetOpcode::G_CONSTANT: {
497     // FIXME: add support for when SizeOp0 isn't an exact multiple of
498     // NarrowSize.
499     if (SizeOp0 % NarrowSize != 0)
500       return UnableToLegalize;
501     int NumParts = SizeOp0 / NarrowSize;
502     const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
503     LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
504 
505     SmallVector<unsigned, 2> DstRegs;
506     for (int i = 0; i < NumParts; ++i) {
507       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
508       ConstantInt *CI =
509           ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
510       MIRBuilder.buildConstant(DstReg, *CI);
511       DstRegs.push_back(DstReg);
512     }
513     unsigned DstReg = MI.getOperand(0).getReg();
514     MIRBuilder.buildMerge(DstReg, DstRegs);
515     MI.eraseFromParent();
516     return Legalized;
517   }
518   case TargetOpcode::G_OR: {
519     // Legalize bitwise operation:
520     // A = BinOp<Ty> B, C
521     // into:
522     // B1, ..., BN = G_UNMERGE_VALUES B
523     // C1, ..., CN = G_UNMERGE_VALUES C
524     // A1 = BinOp<Ty/N> B1, C2
525     // ...
526     // AN = BinOp<Ty/N> BN, CN
527     // A = G_MERGE_VALUES A1, ..., AN
528 
529     // FIXME: add support for when SizeOp0 isn't an exact multiple of
530     // NarrowSize.
531     if (SizeOp0 % NarrowSize != 0)
532       return UnableToLegalize;
533     int NumParts = SizeOp0 / NarrowSize;
534 
535     // List the registers where the destination will be scattered.
536     SmallVector<unsigned, 2> DstRegs;
537     // List the registers where the first argument will be split.
538     SmallVector<unsigned, 2> SrcsReg1;
539     // List the registers where the second argument will be split.
540     SmallVector<unsigned, 2> SrcsReg2;
541     // Create all the temporary registers.
542     for (int i = 0; i < NumParts; ++i) {
543       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
544       unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
545       unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
546 
547       DstRegs.push_back(DstReg);
548       SrcsReg1.push_back(SrcReg1);
549       SrcsReg2.push_back(SrcReg2);
550     }
551     // Explode the big arguments into smaller chunks.
552     MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
553     MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
554 
555     // Do the operation on each small part.
556     for (int i = 0; i < NumParts; ++i)
557       MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
558 
559     // Gather the destination registers into the final destination.
560     unsigned DstReg = MI.getOperand(0).getReg();
561     MIRBuilder.buildMerge(DstReg, DstRegs);
562     MI.eraseFromParent();
563     return Legalized;
564   }
565   }
566 }
567 
568 LegalizerHelper::LegalizeResult
569 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
570   MIRBuilder.setInstr(MI);
571 
572   switch (MI.getOpcode()) {
573   default:
574     return UnableToLegalize;
575   case TargetOpcode::G_ADD:
576   case TargetOpcode::G_AND:
577   case TargetOpcode::G_MUL:
578   case TargetOpcode::G_OR:
579   case TargetOpcode::G_XOR:
580   case TargetOpcode::G_SUB:
581   case TargetOpcode::G_SHL: {
582     // Perform operation at larger width (any extension is fine here, high bits
583     // don't affect the result) and then truncate the result back to the
584     // original type.
585     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
586     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
587     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
588     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
589 
590     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
591     MIRBuilder.buildInstr(MI.getOpcode())
592         .addDef(DstExt)
593         .addUse(Src1Ext)
594         .addUse(Src2Ext);
595 
596     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
597     MI.eraseFromParent();
598     return Legalized;
599   }
600   case TargetOpcode::G_SDIV:
601   case TargetOpcode::G_UDIV:
602   case TargetOpcode::G_SREM:
603   case TargetOpcode::G_UREM:
604   case TargetOpcode::G_ASHR:
605   case TargetOpcode::G_LSHR: {
606     unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
607                              MI.getOpcode() == TargetOpcode::G_SREM ||
608                              MI.getOpcode() == TargetOpcode::G_ASHR
609                          ? TargetOpcode::G_SEXT
610                          : TargetOpcode::G_ZEXT;
611 
612     unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
613     MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
614         MI.getOperand(1).getReg());
615 
616     unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
617     MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
618         MI.getOperand(2).getReg());
619 
620     unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
621     MIRBuilder.buildInstr(MI.getOpcode())
622         .addDef(ResExt)
623         .addUse(LHSExt)
624         .addUse(RHSExt);
625 
626     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
627     MI.eraseFromParent();
628     return Legalized;
629   }
630   case TargetOpcode::G_SELECT: {
631     if (TypeIdx != 0)
632       return UnableToLegalize;
633 
634     // Perform operation at larger width (any extension is fine here, high bits
635     // don't affect the result) and then truncate the result back to the
636     // original type.
637     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
638     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
639     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
640     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
641 
642     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
643     MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
644         .addDef(DstExt)
645         .addReg(MI.getOperand(1).getReg())
646         .addUse(Src1Ext)
647         .addUse(Src2Ext);
648 
649     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
650     MI.eraseFromParent();
651     return Legalized;
652   }
653   case TargetOpcode::G_FPTOSI:
654   case TargetOpcode::G_FPTOUI: {
655     if (TypeIdx != 0)
656       return UnableToLegalize;
657 
658     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
659     MIRBuilder.buildInstr(MI.getOpcode())
660         .addDef(DstExt)
661         .addUse(MI.getOperand(1).getReg());
662 
663     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
664     MI.eraseFromParent();
665     return Legalized;
666   }
667   case TargetOpcode::G_SITOFP:
668   case TargetOpcode::G_UITOFP: {
669     if (TypeIdx != 1)
670       return UnableToLegalize;
671 
672     unsigned Src = MI.getOperand(1).getReg();
673     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
674 
675     if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
676       MIRBuilder.buildSExt(SrcExt, Src);
677     } else {
678       assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
679       MIRBuilder.buildZExt(SrcExt, Src);
680     }
681 
682     MIRBuilder.buildInstr(MI.getOpcode())
683         .addDef(MI.getOperand(0).getReg())
684         .addUse(SrcExt);
685 
686     MI.eraseFromParent();
687     return Legalized;
688   }
689   case TargetOpcode::G_INSERT: {
690     if (TypeIdx != 0)
691       return UnableToLegalize;
692 
693     unsigned Src = MI.getOperand(1).getReg();
694     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
695     MIRBuilder.buildAnyExt(SrcExt, Src);
696 
697     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
698     auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
699                                       MI.getOperand(3).getImm());
700     for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
701       MIB.addReg(MI.getOperand(OpNum).getReg());
702       MIB.addImm(MI.getOperand(OpNum + 1).getImm());
703     }
704 
705     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
706     MI.eraseFromParent();
707     return Legalized;
708   }
709   case TargetOpcode::G_LOAD: {
710     // For some types like i24, we might try to widen to i32. To properly handle
711     // this we should be using a dedicated extending load, until then avoid
712     // trying to legalize.
713     if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) !=
714         WideTy.getSizeInBits())
715       return UnableToLegalize;
716 
717     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
718     MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
719                          **MI.memoperands_begin());
720     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
721     MI.eraseFromParent();
722     return Legalized;
723   }
724   case TargetOpcode::G_STORE: {
725     if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
726         WideTy != LLT::scalar(8))
727       return UnableToLegalize;
728 
729     auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
730     auto Content = TLI.getBooleanContents(false, false);
731 
732     unsigned ExtOp = TargetOpcode::G_ANYEXT;
733     if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
734       ExtOp = TargetOpcode::G_ZEXT;
735     else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
736       ExtOp = TargetOpcode::G_SEXT;
737     else
738       ExtOp = TargetOpcode::G_ANYEXT;
739 
740     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
741     MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
742         MI.getOperand(0).getReg());
743     MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
744                           **MI.memoperands_begin());
745     MI.eraseFromParent();
746     return Legalized;
747   }
748   case TargetOpcode::G_CONSTANT: {
749     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
750     MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
751     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
752     MI.eraseFromParent();
753     return Legalized;
754   }
755   case TargetOpcode::G_FCONSTANT: {
756     const ConstantFP *CFP = MI.getOperand(1).getFPImm();
757     APFloat Val = CFP->getValueAPF();
758     LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
759     auto LLT2Sem = [](LLT Ty) {
760       switch (Ty.getSizeInBits()) {
761       case 32:
762         return &APFloat::IEEEsingle();
763         break;
764       case 64:
765         return &APFloat::IEEEdouble();
766         break;
767       default:
768         llvm_unreachable("Unhandled fp widen type");
769       }
770     };
771     bool LosesInfo;
772     Val.convert(*LLT2Sem(WideTy), APFloat::rmTowardZero, &LosesInfo);
773     auto Cst = MIRBuilder.buildFConstant(WideTy, *ConstantFP::get(Ctx, Val));
774     MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), Cst);
775     MI.eraseFromParent();
776     return Legalized;
777   }
778   case TargetOpcode::G_BRCOND: {
779     unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
780     MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
781     MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
782     MI.eraseFromParent();
783     return Legalized;
784   }
785   case TargetOpcode::G_FCMP: {
786     unsigned Op0Ext, Op1Ext, DstReg;
787     unsigned Cmp1 = MI.getOperand(2).getReg();
788     unsigned Cmp2 = MI.getOperand(3).getReg();
789     if (TypeIdx == 0) {
790       Op0Ext = Cmp1;
791       Op1Ext = Cmp2;
792       DstReg = MRI.createGenericVirtualRegister(WideTy);
793     } else {
794       Op0Ext = MRI.createGenericVirtualRegister(WideTy);
795       Op1Ext = MRI.createGenericVirtualRegister(WideTy);
796       DstReg = MI.getOperand(0).getReg();
797       MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1);
798       MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2);
799     }
800     MIRBuilder.buildFCmp(
801         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
802         DstReg, Op0Ext, Op1Ext);
803     if (TypeIdx == 0)
804       MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
805                             DstReg);
806     MI.eraseFromParent();
807     return Legalized;
808   }
809   case TargetOpcode::G_ICMP: {
810     bool IsSigned = CmpInst::isSigned(
811         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
812     unsigned Cmp1 = MI.getOperand(2).getReg();
813     unsigned Cmp2 = MI.getOperand(3).getReg();
814     unsigned Op0Ext, Op1Ext, DstReg;
815     if (TypeIdx == 0) {
816       Op0Ext = Cmp1;
817       Op1Ext = Cmp2;
818       DstReg = MRI.createGenericVirtualRegister(WideTy);
819     } else {
820       Op0Ext = MRI.createGenericVirtualRegister(WideTy);
821       Op1Ext = MRI.createGenericVirtualRegister(WideTy);
822       DstReg = MI.getOperand(0).getReg();
823       if (IsSigned) {
824         MIRBuilder.buildSExt(Op0Ext, Cmp1);
825         MIRBuilder.buildSExt(Op1Ext, Cmp2);
826       } else {
827         MIRBuilder.buildZExt(Op0Ext, Cmp1);
828         MIRBuilder.buildZExt(Op1Ext, Cmp2);
829       }
830     }
831     MIRBuilder.buildICmp(
832         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
833         DstReg, Op0Ext, Op1Ext);
834     if (TypeIdx == 0)
835       MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(),
836                             DstReg);
837     MI.eraseFromParent();
838     return Legalized;
839   }
840   case TargetOpcode::G_GEP: {
841     assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
842     unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
843     MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
844     MI.getOperand(2).setReg(OffsetExt);
845     return Legalized;
846   }
847   case TargetOpcode::G_PHI: {
848     assert(TypeIdx == 0 && "Expecting only Idx 0");
849     auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) {
850       auto FirstTermIt = MBB.getFirstTerminator();
851       MIRBuilder.setInsertPt(MBB, FirstTermIt);
852       MachineInstr *DefMI = MRI.getVRegDef(Reg);
853       MachineInstrBuilder MIB;
854       if (DefMI->getOpcode() == TargetOpcode::G_TRUNC)
855         MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy,
856                                             DefMI->getOperand(1).getReg());
857       else
858         MIB = MIRBuilder.buildAnyExt(WideTy, Reg);
859       return MIB->getOperand(0).getReg();
860     };
861     auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy);
862     for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end();
863          OpIt != OpE;) {
864       unsigned Reg = OpIt++->getReg();
865       MachineBasicBlock *OpMBB = OpIt++->getMBB();
866       MIB.addReg(getExtendedReg(Reg, *OpMBB));
867       MIB.addMBB(OpMBB);
868     }
869     auto *MBB = MI.getParent();
870     MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI());
871     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(),
872                           MIB->getOperand(0).getReg());
873     MI.eraseFromParent();
874     return Legalized;
875   }
876   }
877 }
878 
879 LegalizerHelper::LegalizeResult
880 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
881   using namespace TargetOpcode;
882   MIRBuilder.setInstr(MI);
883 
884   switch(MI.getOpcode()) {
885   default:
886     return UnableToLegalize;
887   case TargetOpcode::G_SREM:
888   case TargetOpcode::G_UREM: {
889     unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
890     MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
891         .addDef(QuotReg)
892         .addUse(MI.getOperand(1).getReg())
893         .addUse(MI.getOperand(2).getReg());
894 
895     unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
896     MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
897     MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
898                         ProdReg);
899     MI.eraseFromParent();
900     return Legalized;
901   }
902   case TargetOpcode::G_SMULO:
903   case TargetOpcode::G_UMULO: {
904     // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
905     // result.
906     unsigned Res = MI.getOperand(0).getReg();
907     unsigned Overflow = MI.getOperand(1).getReg();
908     unsigned LHS = MI.getOperand(2).getReg();
909     unsigned RHS = MI.getOperand(3).getReg();
910 
911     MIRBuilder.buildMul(Res, LHS, RHS);
912 
913     unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
914                           ? TargetOpcode::G_SMULH
915                           : TargetOpcode::G_UMULH;
916 
917     unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
918     MIRBuilder.buildInstr(Opcode)
919       .addDef(HiPart)
920       .addUse(LHS)
921       .addUse(RHS);
922 
923     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
924     MIRBuilder.buildConstant(Zero, 0);
925 
926     // For *signed* multiply, overflow is detected by checking:
927     // (hi != (lo >> bitwidth-1))
928     if (Opcode == TargetOpcode::G_SMULH) {
929       unsigned Shifted = MRI.createGenericVirtualRegister(Ty);
930       unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty);
931       MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1);
932       MIRBuilder.buildInstr(TargetOpcode::G_ASHR)
933         .addDef(Shifted)
934         .addUse(Res)
935         .addUse(ShiftAmt);
936       MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
937     } else {
938       MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
939     }
940     MI.eraseFromParent();
941     return Legalized;
942   }
943   case TargetOpcode::G_FNEG: {
944     // TODO: Handle vector types once we are able to
945     // represent them.
946     if (Ty.isVector())
947       return UnableToLegalize;
948     unsigned Res = MI.getOperand(0).getReg();
949     Type *ZeroTy;
950     LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
951     switch (Ty.getSizeInBits()) {
952     case 16:
953       ZeroTy = Type::getHalfTy(Ctx);
954       break;
955     case 32:
956       ZeroTy = Type::getFloatTy(Ctx);
957       break;
958     case 64:
959       ZeroTy = Type::getDoubleTy(Ctx);
960       break;
961     case 128:
962       ZeroTy = Type::getFP128Ty(Ctx);
963       break;
964     default:
965       llvm_unreachable("unexpected floating-point type");
966     }
967     ConstantFP &ZeroForNegation =
968         *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
969     auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation);
970     MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
971         .addDef(Res)
972         .addUse(Zero->getOperand(0).getReg())
973         .addUse(MI.getOperand(1).getReg());
974     MI.eraseFromParent();
975     return Legalized;
976   }
977   case TargetOpcode::G_FSUB: {
978     // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
979     // First, check if G_FNEG is marked as Lower. If so, we may
980     // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
981     if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
982       return UnableToLegalize;
983     unsigned Res = MI.getOperand(0).getReg();
984     unsigned LHS = MI.getOperand(1).getReg();
985     unsigned RHS = MI.getOperand(2).getReg();
986     unsigned Neg = MRI.createGenericVirtualRegister(Ty);
987     MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
988     MIRBuilder.buildInstr(TargetOpcode::G_FADD)
989         .addDef(Res)
990         .addUse(LHS)
991         .addUse(Neg);
992     MI.eraseFromParent();
993     return Legalized;
994   }
995   case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
996     unsigned OldValRes = MI.getOperand(0).getReg();
997     unsigned SuccessRes = MI.getOperand(1).getReg();
998     unsigned Addr = MI.getOperand(2).getReg();
999     unsigned CmpVal = MI.getOperand(3).getReg();
1000     unsigned NewVal = MI.getOperand(4).getReg();
1001     MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1002                                   **MI.memoperands_begin());
1003     MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1004     MI.eraseFromParent();
1005     return Legalized;
1006   }
1007   }
1008 }
1009 
1010 LegalizerHelper::LegalizeResult
1011 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1012                                      LLT NarrowTy) {
1013   // FIXME: Don't know how to handle secondary types yet.
1014   if (TypeIdx != 0)
1015     return UnableToLegalize;
1016   switch (MI.getOpcode()) {
1017   default:
1018     return UnableToLegalize;
1019   case TargetOpcode::G_ADD: {
1020     unsigned NarrowSize = NarrowTy.getSizeInBits();
1021     unsigned DstReg = MI.getOperand(0).getReg();
1022     unsigned Size = MRI.getType(DstReg).getSizeInBits();
1023     int NumParts = Size / NarrowSize;
1024     // FIXME: Don't know how to handle the situation where the small vectors
1025     // aren't all the same size yet.
1026     if (Size % NarrowSize != 0)
1027       return UnableToLegalize;
1028 
1029     MIRBuilder.setInstr(MI);
1030 
1031     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1032     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
1033     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
1034 
1035     for (int i = 0; i < NumParts; ++i) {
1036       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1037       MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
1038       DstRegs.push_back(DstReg);
1039     }
1040 
1041     MIRBuilder.buildMerge(DstReg, DstRegs);
1042     MI.eraseFromParent();
1043     return Legalized;
1044   }
1045   }
1046 }
1047