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       unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy);
291       MIRBuilder.buildUndef(Dst);
292       DstRegs.push_back(Dst);
293     }
294     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
295     MI.eraseFromParent();
296     return Legalized;
297   }
298   case TargetOpcode::G_ADD: {
299     // FIXME: add support for when SizeOp0 isn't an exact multiple of
300     // NarrowSize.
301     if (SizeOp0 % NarrowSize != 0)
302       return UnableToLegalize;
303     // Expand in terms of carry-setting/consuming G_ADDE instructions.
304     int NumParts = SizeOp0 / NarrowTy.getSizeInBits();
305 
306     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
307     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
308     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
309 
310     unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
311     MIRBuilder.buildConstant(CarryIn, 0);
312 
313     for (int i = 0; i < NumParts; ++i) {
314       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
315       unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
316 
317       MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
318                             Src2Regs[i], CarryIn);
319 
320       DstRegs.push_back(DstReg);
321       CarryIn = CarryOut;
322     }
323     unsigned DstReg = MI.getOperand(0).getReg();
324     MIRBuilder.buildMerge(DstReg, DstRegs);
325     MI.eraseFromParent();
326     return Legalized;
327   }
328   case TargetOpcode::G_EXTRACT: {
329     if (TypeIdx != 1)
330       return UnableToLegalize;
331 
332     int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
333     // FIXME: add support for when SizeOp1 isn't an exact multiple of
334     // NarrowSize.
335     if (SizeOp1 % NarrowSize != 0)
336       return UnableToLegalize;
337     int NumParts = SizeOp1 / NarrowSize;
338 
339     SmallVector<unsigned, 2> SrcRegs, DstRegs;
340     SmallVector<uint64_t, 2> Indexes;
341     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
342 
343     unsigned OpReg = MI.getOperand(0).getReg();
344     int64_t OpStart = MI.getOperand(2).getImm();
345     int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
346     for (int i = 0; i < NumParts; ++i) {
347       unsigned SrcStart = i * NarrowSize;
348 
349       if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
350         // No part of the extract uses this subregister, ignore it.
351         continue;
352       } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
353         // The entire subregister is extracted, forward the value.
354         DstRegs.push_back(SrcRegs[i]);
355         continue;
356       }
357 
358       // OpSegStart is where this destination segment would start in OpReg if it
359       // extended infinitely in both directions.
360       int64_t ExtractOffset, SegSize;
361       if (OpStart < SrcStart) {
362         ExtractOffset = 0;
363         SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
364       } else {
365         ExtractOffset = OpStart - SrcStart;
366         SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
367       }
368 
369       unsigned SegReg = SrcRegs[i];
370       if (ExtractOffset != 0 || SegSize != NarrowSize) {
371         // A genuine extract is needed.
372         SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
373         MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
374       }
375 
376       DstRegs.push_back(SegReg);
377     }
378 
379     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
380     MI.eraseFromParent();
381     return Legalized;
382   }
383   case TargetOpcode::G_INSERT: {
384     // FIXME: add support for when SizeOp0 isn't an exact multiple of
385     // NarrowSize.
386     if (SizeOp0 % NarrowSize != 0)
387       return UnableToLegalize;
388 
389     int NumParts = SizeOp0 / NarrowSize;
390 
391     SmallVector<unsigned, 2> SrcRegs, DstRegs;
392     SmallVector<uint64_t, 2> Indexes;
393     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
394 
395     unsigned OpReg = MI.getOperand(2).getReg();
396     int64_t OpStart = MI.getOperand(3).getImm();
397     int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
398     for (int i = 0; i < NumParts; ++i) {
399       unsigned DstStart = i * NarrowSize;
400 
401       if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
402         // No part of the insert affects this subregister, forward the original.
403         DstRegs.push_back(SrcRegs[i]);
404         continue;
405       } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
406         // The entire subregister is defined by this insert, forward the new
407         // value.
408         DstRegs.push_back(OpReg);
409         continue;
410       }
411 
412       // OpSegStart is where this destination segment would start in OpReg if it
413       // extended infinitely in both directions.
414       int64_t ExtractOffset, InsertOffset, SegSize;
415       if (OpStart < DstStart) {
416         InsertOffset = 0;
417         ExtractOffset = DstStart - OpStart;
418         SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
419       } else {
420         InsertOffset = OpStart - DstStart;
421         ExtractOffset = 0;
422         SegSize =
423             std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
424       }
425 
426       unsigned SegReg = OpReg;
427       if (ExtractOffset != 0 || SegSize != OpSize) {
428         // A genuine extract is needed.
429         SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
430         MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
431       }
432 
433       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
434       MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
435       DstRegs.push_back(DstReg);
436     }
437 
438     assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
439     MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
440     MI.eraseFromParent();
441     return Legalized;
442   }
443   case TargetOpcode::G_LOAD: {
444     // FIXME: add support for when SizeOp0 isn't an exact multiple of
445     // NarrowSize.
446     if (SizeOp0 % NarrowSize != 0)
447       return UnableToLegalize;
448     int NumParts = SizeOp0 / NarrowSize;
449     LLT OffsetTy = LLT::scalar(
450         MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
451 
452     SmallVector<unsigned, 2> DstRegs;
453     for (int i = 0; i < NumParts; ++i) {
454       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
455       unsigned SrcReg = 0;
456       unsigned Adjustment = i * NarrowSize / 8;
457 
458       MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
459                                 Adjustment);
460 
461       // TODO: This is conservatively correct, but we probably want to split the
462       // memory operands in the future.
463       MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
464 
465       DstRegs.push_back(DstReg);
466     }
467     unsigned DstReg = MI.getOperand(0).getReg();
468     MIRBuilder.buildMerge(DstReg, DstRegs);
469     MI.eraseFromParent();
470     return Legalized;
471   }
472   case TargetOpcode::G_STORE: {
473     // FIXME: add support for when SizeOp0 isn't an exact multiple of
474     // NarrowSize.
475     if (SizeOp0 % NarrowSize != 0)
476       return UnableToLegalize;
477     int NumParts = SizeOp0 / NarrowSize;
478     LLT OffsetTy = LLT::scalar(
479         MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
480 
481     SmallVector<unsigned, 2> SrcRegs;
482     extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
483 
484     for (int i = 0; i < NumParts; ++i) {
485       unsigned DstReg = 0;
486       unsigned Adjustment = i * NarrowSize / 8;
487 
488       MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
489                                 Adjustment);
490 
491       // TODO: This is conservatively correct, but we probably want to split the
492       // memory operands in the future.
493       MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
494     }
495     MI.eraseFromParent();
496     return Legalized;
497   }
498   case TargetOpcode::G_CONSTANT: {
499     // FIXME: add support for when SizeOp0 isn't an exact multiple of
500     // NarrowSize.
501     if (SizeOp0 % NarrowSize != 0)
502       return UnableToLegalize;
503     int NumParts = SizeOp0 / NarrowSize;
504     const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
505     LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
506 
507     SmallVector<unsigned, 2> DstRegs;
508     for (int i = 0; i < NumParts; ++i) {
509       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
510       ConstantInt *CI =
511           ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
512       MIRBuilder.buildConstant(DstReg, *CI);
513       DstRegs.push_back(DstReg);
514     }
515     unsigned DstReg = MI.getOperand(0).getReg();
516     MIRBuilder.buildMerge(DstReg, DstRegs);
517     MI.eraseFromParent();
518     return Legalized;
519   }
520   case TargetOpcode::G_OR: {
521     // Legalize bitwise operation:
522     // A = BinOp<Ty> B, C
523     // into:
524     // B1, ..., BN = G_UNMERGE_VALUES B
525     // C1, ..., CN = G_UNMERGE_VALUES C
526     // A1 = BinOp<Ty/N> B1, C2
527     // ...
528     // AN = BinOp<Ty/N> BN, CN
529     // A = G_MERGE_VALUES A1, ..., AN
530 
531     // FIXME: add support for when SizeOp0 isn't an exact multiple of
532     // NarrowSize.
533     if (SizeOp0 % NarrowSize != 0)
534       return UnableToLegalize;
535     int NumParts = SizeOp0 / NarrowSize;
536 
537     // List the registers where the destination will be scattered.
538     SmallVector<unsigned, 2> DstRegs;
539     // List the registers where the first argument will be split.
540     SmallVector<unsigned, 2> SrcsReg1;
541     // List the registers where the second argument will be split.
542     SmallVector<unsigned, 2> SrcsReg2;
543     // Create all the temporary registers.
544     for (int i = 0; i < NumParts; ++i) {
545       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
546       unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy);
547       unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy);
548 
549       DstRegs.push_back(DstReg);
550       SrcsReg1.push_back(SrcReg1);
551       SrcsReg2.push_back(SrcReg2);
552     }
553     // Explode the big arguments into smaller chunks.
554     MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg());
555     MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg());
556 
557     // Do the operation on each small part.
558     for (int i = 0; i < NumParts; ++i)
559       MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]);
560 
561     // Gather the destination registers into the final destination.
562     unsigned DstReg = MI.getOperand(0).getReg();
563     MIRBuilder.buildMerge(DstReg, DstRegs);
564     MI.eraseFromParent();
565     return Legalized;
566   }
567   }
568 }
569 
570 LegalizerHelper::LegalizeResult
571 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
572   MIRBuilder.setInstr(MI);
573 
574   switch (MI.getOpcode()) {
575   default:
576     return UnableToLegalize;
577   case TargetOpcode::G_ADD:
578   case TargetOpcode::G_AND:
579   case TargetOpcode::G_MUL:
580   case TargetOpcode::G_OR:
581   case TargetOpcode::G_XOR:
582   case TargetOpcode::G_SUB:
583   case TargetOpcode::G_SHL: {
584     // Perform operation at larger width (any extension is fine here, high bits
585     // don't affect the result) and then truncate the result back to the
586     // original type.
587     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
588     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
589     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
590     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
591 
592     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
593     MIRBuilder.buildInstr(MI.getOpcode())
594         .addDef(DstExt)
595         .addUse(Src1Ext)
596         .addUse(Src2Ext);
597 
598     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
599     MI.eraseFromParent();
600     return Legalized;
601   }
602   case TargetOpcode::G_SDIV:
603   case TargetOpcode::G_UDIV:
604   case TargetOpcode::G_SREM:
605   case TargetOpcode::G_UREM:
606   case TargetOpcode::G_ASHR:
607   case TargetOpcode::G_LSHR: {
608     unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
609                              MI.getOpcode() == TargetOpcode::G_SREM ||
610                              MI.getOpcode() == TargetOpcode::G_ASHR
611                          ? TargetOpcode::G_SEXT
612                          : TargetOpcode::G_ZEXT;
613 
614     unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
615     MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
616         MI.getOperand(1).getReg());
617 
618     unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
619     MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
620         MI.getOperand(2).getReg());
621 
622     unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
623     MIRBuilder.buildInstr(MI.getOpcode())
624         .addDef(ResExt)
625         .addUse(LHSExt)
626         .addUse(RHSExt);
627 
628     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
629     MI.eraseFromParent();
630     return Legalized;
631   }
632   case TargetOpcode::G_SELECT: {
633     if (TypeIdx != 0)
634       return UnableToLegalize;
635 
636     // Perform operation at larger width (any extension is fine here, high bits
637     // don't affect the result) and then truncate the result back to the
638     // original type.
639     unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
640     unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
641     MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
642     MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
643 
644     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
645     MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
646         .addDef(DstExt)
647         .addReg(MI.getOperand(1).getReg())
648         .addUse(Src1Ext)
649         .addUse(Src2Ext);
650 
651     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
652     MI.eraseFromParent();
653     return Legalized;
654   }
655   case TargetOpcode::G_FPTOSI:
656   case TargetOpcode::G_FPTOUI: {
657     if (TypeIdx != 0)
658       return UnableToLegalize;
659 
660     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
661     MIRBuilder.buildInstr(MI.getOpcode())
662         .addDef(DstExt)
663         .addUse(MI.getOperand(1).getReg());
664 
665     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
666     MI.eraseFromParent();
667     return Legalized;
668   }
669   case TargetOpcode::G_SITOFP:
670   case TargetOpcode::G_UITOFP: {
671     if (TypeIdx != 1)
672       return UnableToLegalize;
673 
674     unsigned Src = MI.getOperand(1).getReg();
675     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
676 
677     if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
678       MIRBuilder.buildSExt(SrcExt, Src);
679     } else {
680       assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
681       MIRBuilder.buildZExt(SrcExt, Src);
682     }
683 
684     MIRBuilder.buildInstr(MI.getOpcode())
685         .addDef(MI.getOperand(0).getReg())
686         .addUse(SrcExt);
687 
688     MI.eraseFromParent();
689     return Legalized;
690   }
691   case TargetOpcode::G_INSERT: {
692     if (TypeIdx != 0)
693       return UnableToLegalize;
694 
695     unsigned Src = MI.getOperand(1).getReg();
696     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
697     MIRBuilder.buildAnyExt(SrcExt, Src);
698 
699     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
700     auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
701                                       MI.getOperand(3).getImm());
702     for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
703       MIB.addReg(MI.getOperand(OpNum).getReg());
704       MIB.addImm(MI.getOperand(OpNum + 1).getImm());
705     }
706 
707     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
708     MI.eraseFromParent();
709     return Legalized;
710   }
711   case TargetOpcode::G_LOAD: {
712     assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
713                WideTy.getSizeInBits() &&
714            "illegal to increase number of bytes loaded");
715 
716     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
717     MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
718                          **MI.memoperands_begin());
719     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
720     MI.eraseFromParent();
721     return Legalized;
722   }
723   case TargetOpcode::G_STORE: {
724     if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
725         WideTy != LLT::scalar(8))
726       return UnableToLegalize;
727 
728     auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
729     auto Content = TLI.getBooleanContents(false, false);
730 
731     unsigned ExtOp = TargetOpcode::G_ANYEXT;
732     if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
733       ExtOp = TargetOpcode::G_ZEXT;
734     else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
735       ExtOp = TargetOpcode::G_SEXT;
736     else
737       ExtOp = TargetOpcode::G_ANYEXT;
738 
739     unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
740     MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
741         MI.getOperand(0).getReg());
742     MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
743                           **MI.memoperands_begin());
744     MI.eraseFromParent();
745     return Legalized;
746   }
747   case TargetOpcode::G_CONSTANT: {
748     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
749     MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
750     MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
751     MI.eraseFromParent();
752     return Legalized;
753   }
754   case TargetOpcode::G_FCONSTANT: {
755     unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
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     MIRBuilder.buildFConstant(DstExt, *ConstantFP::get(Ctx, Val));
774     MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
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     unsigned Zero = MRI.createGenericVirtualRegister(Ty);
970     MIRBuilder.buildFConstant(Zero, ZeroForNegation);
971     MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
972         .addDef(Res)
973         .addUse(Zero)
974         .addUse(MI.getOperand(1).getReg());
975     MI.eraseFromParent();
976     return Legalized;
977   }
978   case TargetOpcode::G_FSUB: {
979     // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
980     // First, check if G_FNEG is marked as Lower. If so, we may
981     // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
982     if (LI.getAction({G_FNEG, {Ty}}).Action == Lower)
983       return UnableToLegalize;
984     unsigned Res = MI.getOperand(0).getReg();
985     unsigned LHS = MI.getOperand(1).getReg();
986     unsigned RHS = MI.getOperand(2).getReg();
987     unsigned Neg = MRI.createGenericVirtualRegister(Ty);
988     MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
989     MIRBuilder.buildInstr(TargetOpcode::G_FADD)
990         .addDef(Res)
991         .addUse(LHS)
992         .addUse(Neg);
993     MI.eraseFromParent();
994     return Legalized;
995   }
996   case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
997     unsigned OldValRes = MI.getOperand(0).getReg();
998     unsigned SuccessRes = MI.getOperand(1).getReg();
999     unsigned Addr = MI.getOperand(2).getReg();
1000     unsigned CmpVal = MI.getOperand(3).getReg();
1001     unsigned NewVal = MI.getOperand(4).getReg();
1002     MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal,
1003                                   **MI.memoperands_begin());
1004     MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal);
1005     MI.eraseFromParent();
1006     return Legalized;
1007   }
1008   }
1009 }
1010 
1011 LegalizerHelper::LegalizeResult
1012 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
1013                                      LLT NarrowTy) {
1014   // FIXME: Don't know how to handle secondary types yet.
1015   if (TypeIdx != 0)
1016     return UnableToLegalize;
1017   switch (MI.getOpcode()) {
1018   default:
1019     return UnableToLegalize;
1020   case TargetOpcode::G_ADD: {
1021     unsigned NarrowSize = NarrowTy.getSizeInBits();
1022     unsigned DstReg = MI.getOperand(0).getReg();
1023     unsigned Size = MRI.getType(DstReg).getSizeInBits();
1024     int NumParts = Size / NarrowSize;
1025     // FIXME: Don't know how to handle the situation where the small vectors
1026     // aren't all the same size yet.
1027     if (Size % NarrowSize != 0)
1028       return UnableToLegalize;
1029 
1030     MIRBuilder.setInstr(MI);
1031 
1032     SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
1033     extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
1034     extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
1035 
1036     for (int i = 0; i < NumParts; ++i) {
1037       unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
1038       MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
1039       DstRegs.push_back(DstReg);
1040     }
1041 
1042     MIRBuilder.buildMerge(DstReg, DstRegs);
1043     MI.eraseFromParent();
1044     return Legalized;
1045   }
1046   }
1047 }
1048