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