1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \file This file implements the LegalizerHelper class to legalize
11 /// individual instructions and the LegalizeMachineIR wrapper pass for the
12 /// primary legalization.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
18 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Target/TargetLowering.h"
23 #include "llvm/Target/TargetSubtargetInfo.h"
27 #define DEBUG_TYPE "legalize-mir"
31 LegalizerHelper::LegalizerHelper(MachineFunction &MF)
32 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
36 LegalizerHelper::LegalizeResult
37 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
38 auto Action = LI.getAction(MI, MRI);
39 switch (std::get<0>(Action)) {
40 case LegalizerInfo::Legal:
42 case LegalizerInfo::Libcall:
44 case LegalizerInfo::NarrowScalar:
45 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
46 case LegalizerInfo::WidenScalar:
47 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
48 case LegalizerInfo::Lower:
49 return lower(MI, std::get<1>(Action), std::get<2>(Action));
50 case LegalizerInfo::FewerElements:
51 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
52 case LegalizerInfo::Custom:
53 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
56 return UnableToLegalize;
60 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
61 SmallVectorImpl<unsigned> &VRegs) {
62 for (int i = 0; i < NumParts; ++i)
63 VRegs.push_back(MRI.createGenericVirtualRegister(Ty));
64 MIRBuilder.buildUnmerge(VRegs, Reg);
67 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
69 case TargetOpcode::G_FADD:
70 assert((Size == 32 || Size == 64) && "Unsupported size");
71 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
72 case TargetOpcode::G_FREM:
73 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32;
74 case TargetOpcode::G_FPOW:
75 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32;
77 llvm_unreachable("Unknown libcall function");
80 LegalizerHelper::LegalizeResult
81 LegalizerHelper::libcall(MachineInstr &MI) {
82 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
83 unsigned Size = Ty.getSizeInBits();
84 MIRBuilder.setInstr(MI);
86 switch (MI.getOpcode()) {
88 return UnableToLegalize;
89 case TargetOpcode::G_FADD:
90 case TargetOpcode::G_FPOW:
91 case TargetOpcode::G_FREM: {
92 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
93 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
94 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
95 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
96 auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
97 const char *Name = TLI.getLibcallName(Libcall);
98 MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
100 MIRBuilder, TLI.getLibcallCallingConv(Libcall),
101 MachineOperand::CreateES(Name), {MI.getOperand(0).getReg(), Ty},
102 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}});
103 MI.eraseFromParent();
109 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
112 // FIXME: Don't know how to handle secondary types yet.
114 return UnableToLegalize;
116 MIRBuilder.setInstr(MI);
118 switch (MI.getOpcode()) {
120 return UnableToLegalize;
121 case TargetOpcode::G_ADD: {
122 // Expand in terms of carry-setting/consuming G_ADDE instructions.
123 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() /
124 NarrowTy.getSizeInBits();
126 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
127 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
128 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
130 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1));
131 MIRBuilder.buildConstant(CarryIn, 0);
133 for (int i = 0; i < NumParts; ++i) {
134 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
135 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1));
137 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i],
138 Src2Regs[i], CarryIn);
140 DstRegs.push_back(DstReg);
143 unsigned DstReg = MI.getOperand(0).getReg();
144 MIRBuilder.buildMerge(DstReg, DstRegs);
145 MI.eraseFromParent();
148 case TargetOpcode::G_INSERT: {
150 return UnableToLegalize;
152 int64_t NarrowSize = NarrowTy.getSizeInBits();
154 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
156 SmallVector<unsigned, 2> SrcRegs, DstRegs;
157 SmallVector<uint64_t, 2> Indexes;
158 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs);
160 unsigned OpReg = MI.getOperand(2).getReg();
161 int64_t OpStart = MI.getOperand(3).getImm();
162 int64_t OpSize = MRI.getType(OpReg).getSizeInBits();
163 for (int i = 0; i < NumParts; ++i) {
164 unsigned DstStart = i * NarrowSize;
166 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
167 // No part of the insert affects this subregister, forward the original.
168 DstRegs.push_back(SrcRegs[i]);
170 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
171 // The entire subregister is defined by this insert, forward the new
173 DstRegs.push_back(OpReg);
177 // OpSegStart is where this destination segment would start in OpReg if it
178 // extended infinitely in both directions.
179 int64_t ExtractOffset, InsertOffset, SegSize;
180 if (OpStart < DstStart) {
182 ExtractOffset = DstStart - OpStart;
183 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
185 InsertOffset = OpStart - DstStart;
188 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
191 unsigned SegReg = OpReg;
192 if (ExtractOffset != 0 || SegSize != OpSize) {
193 // A genuine extract is needed.
194 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
195 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
198 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
199 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset);
200 DstRegs.push_back(DstReg);
203 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered");
204 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs);
205 MI.eraseFromParent();
208 case TargetOpcode::G_LOAD: {
209 unsigned NarrowSize = NarrowTy.getSizeInBits();
211 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
212 LLT NarrowPtrTy = LLT::pointer(
213 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
215 SmallVector<unsigned, 2> DstRegs;
216 for (int i = 0; i < NumParts; ++i) {
217 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
218 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
219 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
221 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
222 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
223 // TODO: This is conservatively correct, but we probably want to split the
224 // memory operands in the future.
225 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
227 DstRegs.push_back(DstReg);
229 unsigned DstReg = MI.getOperand(0).getReg();
230 MIRBuilder.buildMerge(DstReg, DstRegs);
231 MI.eraseFromParent();
234 case TargetOpcode::G_STORE: {
235 unsigned NarrowSize = NarrowTy.getSizeInBits();
237 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
238 LLT NarrowPtrTy = LLT::pointer(
239 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
241 SmallVector<unsigned, 2> SrcRegs;
242 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
244 for (int i = 0; i < NumParts; ++i) {
245 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
246 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
247 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
248 MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
249 // TODO: This is conservatively correct, but we probably want to split the
250 // memory operands in the future.
251 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
253 MI.eraseFromParent();
256 case TargetOpcode::G_CONSTANT: {
257 unsigned NarrowSize = NarrowTy.getSizeInBits();
259 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
260 const APInt &Cst = MI.getOperand(1).getCImm()->getValue();
261 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
263 SmallVector<unsigned, 2> DstRegs;
264 for (int i = 0; i < NumParts; ++i) {
265 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
267 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize));
268 MIRBuilder.buildConstant(DstReg, *CI);
269 DstRegs.push_back(DstReg);
271 unsigned DstReg = MI.getOperand(0).getReg();
272 MIRBuilder.buildMerge(DstReg, DstRegs);
273 MI.eraseFromParent();
279 LegalizerHelper::LegalizeResult
280 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
281 MIRBuilder.setInstr(MI);
283 switch (MI.getOpcode()) {
285 return UnableToLegalize;
286 case TargetOpcode::G_ADD:
287 case TargetOpcode::G_AND:
288 case TargetOpcode::G_MUL:
289 case TargetOpcode::G_OR:
290 case TargetOpcode::G_XOR:
291 case TargetOpcode::G_SUB:
292 case TargetOpcode::G_SHL: {
293 // Perform operation at larger width (any extension is fine here, high bits
294 // don't affect the result) and then truncate the result back to the
296 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
297 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
298 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg());
299 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg());
301 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
302 MIRBuilder.buildInstr(MI.getOpcode())
307 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
308 MI.eraseFromParent();
311 case TargetOpcode::G_SDIV:
312 case TargetOpcode::G_UDIV:
313 case TargetOpcode::G_ASHR:
314 case TargetOpcode::G_LSHR: {
315 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV ||
316 MI.getOpcode() == TargetOpcode::G_ASHR
317 ? TargetOpcode::G_SEXT
318 : TargetOpcode::G_ZEXT;
320 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy);
321 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse(
322 MI.getOperand(1).getReg());
324 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy);
325 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse(
326 MI.getOperand(2).getReg());
328 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy);
329 MIRBuilder.buildInstr(MI.getOpcode())
334 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt);
335 MI.eraseFromParent();
338 case TargetOpcode::G_SELECT: {
340 return UnableToLegalize;
342 // Perform operation at larger width (any extension is fine here, high bits
343 // don't affect the result) and then truncate the result back to the
345 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy);
346 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy);
347 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg());
348 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg());
350 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
351 MIRBuilder.buildInstr(TargetOpcode::G_SELECT)
353 .addReg(MI.getOperand(1).getReg())
357 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
358 MI.eraseFromParent();
361 case TargetOpcode::G_FPTOSI:
362 case TargetOpcode::G_FPTOUI: {
364 return UnableToLegalize;
366 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
367 MIRBuilder.buildInstr(MI.getOpcode())
369 .addUse(MI.getOperand(1).getReg());
371 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
372 MI.eraseFromParent();
375 case TargetOpcode::G_SITOFP:
376 case TargetOpcode::G_UITOFP: {
378 return UnableToLegalize;
380 unsigned Src = MI.getOperand(1).getReg();
381 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
383 if (MI.getOpcode() == TargetOpcode::G_SITOFP) {
384 MIRBuilder.buildSExt(SrcExt, Src);
386 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op");
387 MIRBuilder.buildZExt(SrcExt, Src);
390 MIRBuilder.buildInstr(MI.getOpcode())
391 .addDef(MI.getOperand(0).getReg())
394 MI.eraseFromParent();
397 case TargetOpcode::G_INSERT: {
399 return UnableToLegalize;
401 unsigned Src = MI.getOperand(1).getReg();
402 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
403 MIRBuilder.buildAnyExt(SrcExt, Src);
405 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
406 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(),
407 MI.getOperand(3).getImm());
408 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) {
409 MIB.addReg(MI.getOperand(OpNum).getReg());
410 MIB.addImm(MI.getOperand(OpNum + 1).getImm());
413 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
414 MI.eraseFromParent();
417 case TargetOpcode::G_LOAD: {
418 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) ==
419 WideTy.getSizeInBits() &&
420 "illegal to increase number of bytes loaded");
422 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
423 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(),
424 **MI.memoperands_begin());
425 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
426 MI.eraseFromParent();
429 case TargetOpcode::G_STORE: {
430 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) ||
431 WideTy != LLT::scalar(8))
432 return UnableToLegalize;
434 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
435 auto Content = TLI.getBooleanContents(false, false);
437 unsigned ExtOp = TargetOpcode::G_ANYEXT;
438 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent)
439 ExtOp = TargetOpcode::G_ZEXT;
440 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent)
441 ExtOp = TargetOpcode::G_SEXT;
443 ExtOp = TargetOpcode::G_ANYEXT;
445 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy);
446 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse(
447 MI.getOperand(0).getReg());
448 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(),
449 **MI.memoperands_begin());
450 MI.eraseFromParent();
453 case TargetOpcode::G_CONSTANT: {
454 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
455 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm());
456 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt);
457 MI.eraseFromParent();
460 case TargetOpcode::G_FCONSTANT: {
461 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy);
462 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm());
463 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt);
464 MI.eraseFromParent();
467 case TargetOpcode::G_BRCOND: {
468 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy);
469 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg());
470 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB());
471 MI.eraseFromParent();
474 case TargetOpcode::G_ICMP: {
475 assert(TypeIdx == 1 && "unable to legalize predicate");
476 bool IsSigned = CmpInst::isSigned(
477 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
478 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy);
479 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy);
481 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg());
482 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg());
484 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg());
485 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg());
487 MIRBuilder.buildICmp(
488 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()),
489 MI.getOperand(0).getReg(), Op0Ext, Op1Ext);
490 MI.eraseFromParent();
493 case TargetOpcode::G_GEP: {
494 assert(TypeIdx == 1 && "unable to legalize pointer of GEP");
495 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy);
496 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg());
497 MI.getOperand(2).setReg(OffsetExt);
503 LegalizerHelper::LegalizeResult
504 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
505 using namespace TargetOpcode;
506 MIRBuilder.setInstr(MI);
508 switch(MI.getOpcode()) {
510 return UnableToLegalize;
511 case TargetOpcode::G_SREM:
512 case TargetOpcode::G_UREM: {
513 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty);
514 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV)
516 .addUse(MI.getOperand(1).getReg())
517 .addUse(MI.getOperand(2).getReg());
519 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty);
520 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg());
521 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
523 MI.eraseFromParent();
526 case TargetOpcode::G_SMULO:
527 case TargetOpcode::G_UMULO: {
528 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
530 unsigned Res = MI.getOperand(0).getReg();
531 unsigned Overflow = MI.getOperand(1).getReg();
532 unsigned LHS = MI.getOperand(2).getReg();
533 unsigned RHS = MI.getOperand(3).getReg();
535 MIRBuilder.buildMul(Res, LHS, RHS);
537 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
538 ? TargetOpcode::G_SMULH
539 : TargetOpcode::G_UMULH;
541 unsigned HiPart = MRI.createGenericVirtualRegister(Ty);
542 MIRBuilder.buildInstr(Opcode)
547 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
548 MIRBuilder.buildConstant(Zero, 0);
549 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
550 MI.eraseFromParent();
553 case TargetOpcode::G_FNEG: {
554 // TODO: Handle vector types once we are able to
557 return UnableToLegalize;
558 unsigned Res = MI.getOperand(0).getReg();
560 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext();
561 switch (Ty.getSizeInBits()) {
563 ZeroTy = Type::getHalfTy(Ctx);
566 ZeroTy = Type::getFloatTy(Ctx);
569 ZeroTy = Type::getDoubleTy(Ctx);
572 llvm_unreachable("unexpected floating-point type");
574 ConstantFP &ZeroForNegation =
575 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy));
576 unsigned Zero = MRI.createGenericVirtualRegister(Ty);
577 MIRBuilder.buildFConstant(Zero, ZeroForNegation);
578 MIRBuilder.buildInstr(TargetOpcode::G_FSUB)
581 .addUse(MI.getOperand(1).getReg());
582 MI.eraseFromParent();
585 case TargetOpcode::G_FSUB: {
586 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
587 // First, check if G_FNEG is marked as Lower. If so, we may
588 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
589 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
590 return UnableToLegalize;
591 unsigned Res = MI.getOperand(0).getReg();
592 unsigned LHS = MI.getOperand(1).getReg();
593 unsigned RHS = MI.getOperand(2).getReg();
594 unsigned Neg = MRI.createGenericVirtualRegister(Ty);
595 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS);
596 MIRBuilder.buildInstr(TargetOpcode::G_FADD)
600 MI.eraseFromParent();
606 LegalizerHelper::LegalizeResult
607 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
609 // FIXME: Don't know how to handle secondary types yet.
611 return UnableToLegalize;
612 switch (MI.getOpcode()) {
614 return UnableToLegalize;
615 case TargetOpcode::G_ADD: {
616 unsigned NarrowSize = NarrowTy.getSizeInBits();
617 unsigned DstReg = MI.getOperand(0).getReg();
618 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize;
620 MIRBuilder.setInstr(MI);
622 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
623 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
624 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
626 for (int i = 0; i < NumParts; ++i) {
627 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
628 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]);
629 DstRegs.push_back(DstReg);
632 MIRBuilder.buildMerge(DstReg, DstRegs);
633 MI.eraseFromParent();