1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file This file implements the LegalizerHelper class to legalize 11 /// individual instructions and the LegalizeMachineIR wrapper pass for the 12 /// primary legalization. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 17 #include "llvm/CodeGen/GlobalISel/CallLowering.h" 18 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 19 #include "llvm/CodeGen/MachineRegisterInfo.h" 20 #include "llvm/Support/Debug.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include "llvm/Target/TargetLowering.h" 23 #include "llvm/Target/TargetSubtargetInfo.h" 24 25 #include <sstream> 26 27 #define DEBUG_TYPE "legalize-mir" 28 29 using namespace llvm; 30 31 LegalizerHelper::LegalizerHelper(MachineFunction &MF) 32 : MRI(MF.getRegInfo()) { 33 MIRBuilder.setMF(MF); 34 } 35 36 LegalizerHelper::LegalizeResult 37 LegalizerHelper::legalizeInstrStep(MachineInstr &MI, 38 const LegalizerInfo &LegalizerInfo) { 39 auto Action = LegalizerInfo.getAction(MI, MRI); 40 switch (std::get<0>(Action)) { 41 case LegalizerInfo::Legal: 42 return AlreadyLegal; 43 case LegalizerInfo::Libcall: 44 return libcall(MI); 45 case LegalizerInfo::NarrowScalar: 46 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action)); 47 case LegalizerInfo::WidenScalar: 48 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action)); 49 case LegalizerInfo::Lower: 50 return lower(MI, std::get<1>(Action), std::get<2>(Action)); 51 case LegalizerInfo::FewerElements: 52 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action)); 53 case LegalizerInfo::Custom: 54 return LegalizerInfo.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized 55 : UnableToLegalize; 56 default: 57 return UnableToLegalize; 58 } 59 } 60 61 LegalizerHelper::LegalizeResult 62 LegalizerHelper::legalizeInstr(MachineInstr &MI, 63 const LegalizerInfo &LegalizerInfo) { 64 SmallVector<MachineInstr *, 4> WorkList; 65 MIRBuilder.recordInsertions( 66 [&](MachineInstr *MI) { WorkList.push_back(MI); }); 67 WorkList.push_back(&MI); 68 69 bool Changed = false; 70 LegalizeResult Res; 71 unsigned Idx = 0; 72 do { 73 Res = legalizeInstrStep(*WorkList[Idx], LegalizerInfo); 74 if (Res == UnableToLegalize) { 75 MIRBuilder.stopRecordingInsertions(); 76 return UnableToLegalize; 77 } 78 Changed |= Res == Legalized; 79 ++Idx; 80 } while (Idx < WorkList.size()); 81 82 MIRBuilder.stopRecordingInsertions(); 83 84 return Changed ? Legalized : AlreadyLegal; 85 } 86 87 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts, 88 SmallVectorImpl<unsigned> &VRegs) { 89 unsigned Size = Ty.getSizeInBits(); 90 SmallVector<uint64_t, 4> Indexes; 91 for (int i = 0; i < NumParts; ++i) { 92 VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); 93 Indexes.push_back(i * Size); 94 } 95 MIRBuilder.buildExtract(VRegs, Indexes, Reg); 96 } 97 98 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { 99 switch (Opcode) { 100 case TargetOpcode::G_FREM: 101 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; 102 case TargetOpcode::G_FPOW: 103 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; 104 } 105 llvm_unreachable("Unknown libcall function"); 106 } 107 108 LegalizerHelper::LegalizeResult 109 LegalizerHelper::libcall(MachineInstr &MI) { 110 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 111 unsigned Size = Ty.getSizeInBits(); 112 MIRBuilder.setInstr(MI); 113 114 switch (MI.getOpcode()) { 115 default: 116 return UnableToLegalize; 117 case TargetOpcode::G_FPOW: 118 case TargetOpcode::G_FREM: { 119 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 120 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); 121 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 122 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 123 const char *Name = TLI.getLibcallName(getRTLibDesc(MI.getOpcode(), Size)); 124 CLI.lowerCall( 125 MIRBuilder, MachineOperand::CreateES(Name), 126 {MI.getOperand(0).getReg(), Ty}, 127 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}}); 128 MI.eraseFromParent(); 129 return Legalized; 130 } 131 } 132 } 133 134 void LegalizerHelper::findInsertionsForRange( 135 int64_t DstStart, int64_t DstEnd, MachineInstr::mop_iterator &CurOp, 136 MachineInstr::mop_iterator &EndOp, MachineInstr &MI) { 137 while (CurOp != MI.operands_end() && std::next(CurOp)->getImm() < DstStart) 138 CurOp += 2; 139 140 EndOp = CurOp; 141 while (EndOp != MI.operands_end() && std::next(EndOp)->getImm() < DstEnd) 142 EndOp += 2; 143 } 144 145 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 146 unsigned TypeIdx, 147 LLT NarrowTy) { 148 // FIXME: Don't know how to handle secondary types yet. 149 if (TypeIdx != 0) 150 return UnableToLegalize; 151 152 MIRBuilder.setInstr(MI); 153 154 switch (MI.getOpcode()) { 155 default: 156 return UnableToLegalize; 157 case TargetOpcode::G_ADD: { 158 // Expand in terms of carry-setting/consuming G_ADDE instructions. 159 unsigned NarrowSize = NarrowTy.getSizeInBits(); 160 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / 161 NarrowTy.getSizeInBits(); 162 163 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 164 SmallVector<uint64_t, 2> Indexes; 165 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 166 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 167 168 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1)); 169 MIRBuilder.buildConstant(CarryIn, 0); 170 171 for (int i = 0; i < NumParts; ++i) { 172 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 173 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 174 175 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], 176 Src2Regs[i], CarryIn); 177 178 DstRegs.push_back(DstReg); 179 Indexes.push_back(i * NarrowSize); 180 CarryIn = CarryOut; 181 } 182 unsigned DstReg = MI.getOperand(0).getReg(); 183 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes); 184 MI.eraseFromParent(); 185 return Legalized; 186 } 187 case TargetOpcode::G_INSERT: { 188 if (TypeIdx != 0) 189 return UnableToLegalize; 190 191 unsigned NarrowSize = NarrowTy.getSizeInBits(); 192 int NumParts = 193 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 194 195 SmallVector<unsigned, 2> SrcRegs, DstRegs; 196 SmallVector<uint64_t, 2> Indexes; 197 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 198 199 MachineInstr::mop_iterator CurOp = MI.operands_begin() + 2, EndOp; 200 for (int i = 0; i < NumParts; ++i) { 201 unsigned DstStart = i * NarrowSize; 202 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 203 Indexes.push_back(DstStart); 204 205 findInsertionsForRange(DstStart, DstStart + NarrowSize, CurOp, EndOp, MI); 206 207 if (CurOp == EndOp) { 208 // No part of the insert affects this subregister, forward the original. 209 DstRegs.push_back(SrcRegs[i]); 210 continue; 211 } else if (MRI.getType(CurOp->getReg()) == NarrowTy && 212 std::next(CurOp)->getImm() == DstStart) { 213 // The entire subregister is defined by this insert, forward the new 214 // value. 215 DstRegs.push_back(CurOp->getReg()); 216 continue; 217 } 218 219 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_INSERT) 220 .addDef(DstReg) 221 .addUse(SrcRegs[i]); 222 223 for (; CurOp != EndOp; CurOp += 2) { 224 unsigned Reg = CurOp->getReg(); 225 uint64_t Offset = std::next(CurOp)->getImm() - DstStart; 226 227 // Make sure we don't have a cross-register insert. 228 if (Offset + MRI.getType(Reg).getSizeInBits() > NarrowSize) { 229 // FIXME: we should handle this case, though it's unlikely to be 230 // common given ABI-related layout restrictions. 231 return UnableToLegalize; 232 } 233 234 MIB.addUse(Reg); 235 MIB.addImm(Offset); 236 } 237 238 DstRegs.push_back(DstReg); 239 } 240 241 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); 242 MIRBuilder.buildSequence(MI.getOperand(0).getReg(), DstRegs, Indexes); 243 MI.eraseFromParent(); 244 return Legalized; 245 } 246 case TargetOpcode::G_LOAD: { 247 unsigned NarrowSize = NarrowTy.getSizeInBits(); 248 int NumParts = 249 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 250 LLT NarrowPtrTy = LLT::pointer( 251 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize); 252 253 SmallVector<unsigned, 2> DstRegs; 254 SmallVector<uint64_t, 2> Indexes; 255 for (int i = 0; i < NumParts; ++i) { 256 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 257 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy); 258 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64)); 259 260 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8); 261 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset); 262 // TODO: This is conservatively correct, but we probably want to split the 263 // memory operands in the future. 264 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin()); 265 266 DstRegs.push_back(DstReg); 267 Indexes.push_back(i * NarrowSize); 268 } 269 unsigned DstReg = MI.getOperand(0).getReg(); 270 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes); 271 MI.eraseFromParent(); 272 return Legalized; 273 } 274 case TargetOpcode::G_STORE: { 275 unsigned NarrowSize = NarrowTy.getSizeInBits(); 276 int NumParts = 277 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 278 LLT NarrowPtrTy = LLT::pointer( 279 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize); 280 281 SmallVector<unsigned, 2> SrcRegs; 282 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs); 283 284 for (int i = 0; i < NumParts; ++i) { 285 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy); 286 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64)); 287 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8); 288 MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset); 289 // TODO: This is conservatively correct, but we probably want to split the 290 // memory operands in the future. 291 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin()); 292 } 293 MI.eraseFromParent(); 294 return Legalized; 295 } 296 } 297 } 298 299 LegalizerHelper::LegalizeResult 300 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 301 MIRBuilder.setInstr(MI); 302 303 switch (MI.getOpcode()) { 304 default: 305 return UnableToLegalize; 306 case TargetOpcode::G_ADD: 307 case TargetOpcode::G_AND: 308 case TargetOpcode::G_MUL: 309 case TargetOpcode::G_OR: 310 case TargetOpcode::G_XOR: 311 case TargetOpcode::G_SUB: 312 case TargetOpcode::G_SHL: { 313 // Perform operation at larger width (any extension is fine here, high bits 314 // don't affect the result) and then truncate the result back to the 315 // original type. 316 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 317 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 318 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg()); 319 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg()); 320 321 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 322 MIRBuilder.buildInstr(MI.getOpcode()) 323 .addDef(DstExt) 324 .addUse(Src1Ext) 325 .addUse(Src2Ext); 326 327 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 328 MI.eraseFromParent(); 329 return Legalized; 330 } 331 case TargetOpcode::G_SDIV: 332 case TargetOpcode::G_UDIV: 333 case TargetOpcode::G_ASHR: 334 case TargetOpcode::G_LSHR: { 335 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV || 336 MI.getOpcode() == TargetOpcode::G_ASHR 337 ? TargetOpcode::G_SEXT 338 : TargetOpcode::G_ZEXT; 339 340 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy); 341 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse( 342 MI.getOperand(1).getReg()); 343 344 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy); 345 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse( 346 MI.getOperand(2).getReg()); 347 348 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy); 349 MIRBuilder.buildInstr(MI.getOpcode()) 350 .addDef(ResExt) 351 .addUse(LHSExt) 352 .addUse(RHSExt); 353 354 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt); 355 MI.eraseFromParent(); 356 return Legalized; 357 } 358 case TargetOpcode::G_SELECT: { 359 if (TypeIdx != 0) 360 return UnableToLegalize; 361 362 // Perform operation at larger width (any extension is fine here, high bits 363 // don't affect the result) and then truncate the result back to the 364 // original type. 365 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 366 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 367 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg()); 368 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg()); 369 370 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 371 MIRBuilder.buildInstr(TargetOpcode::G_SELECT) 372 .addDef(DstExt) 373 .addReg(MI.getOperand(1).getReg()) 374 .addUse(Src1Ext) 375 .addUse(Src2Ext); 376 377 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 378 MI.eraseFromParent(); 379 return Legalized; 380 } 381 case TargetOpcode::G_FPTOSI: 382 case TargetOpcode::G_FPTOUI: { 383 if (TypeIdx != 0) 384 return UnableToLegalize; 385 386 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 387 MIRBuilder.buildInstr(MI.getOpcode()) 388 .addDef(DstExt) 389 .addUse(MI.getOperand(1).getReg()); 390 391 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 392 MI.eraseFromParent(); 393 return Legalized; 394 } 395 case TargetOpcode::G_SITOFP: 396 case TargetOpcode::G_UITOFP: { 397 if (TypeIdx != 1) 398 return UnableToLegalize; 399 400 unsigned Src = MI.getOperand(1).getReg(); 401 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 402 403 if (MI.getOpcode() == TargetOpcode::G_SITOFP) { 404 MIRBuilder.buildSExt(SrcExt, Src); 405 } else { 406 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op"); 407 MIRBuilder.buildZExt(SrcExt, Src); 408 } 409 410 MIRBuilder.buildInstr(MI.getOpcode()) 411 .addDef(MI.getOperand(0).getReg()) 412 .addUse(SrcExt); 413 414 MI.eraseFromParent(); 415 return Legalized; 416 } 417 case TargetOpcode::G_INSERT: { 418 if (TypeIdx != 0) 419 return UnableToLegalize; 420 421 unsigned Src = MI.getOperand(1).getReg(); 422 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 423 MIRBuilder.buildAnyExt(SrcExt, Src); 424 425 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 426 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(), 427 MI.getOperand(3).getImm()); 428 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) { 429 MIB.addReg(MI.getOperand(OpNum).getReg()); 430 MIB.addImm(MI.getOperand(OpNum + 1).getImm()); 431 } 432 433 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 434 MI.eraseFromParent(); 435 return Legalized; 436 } 437 case TargetOpcode::G_LOAD: { 438 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) == 439 WideTy.getSizeInBits() && 440 "illegal to increase number of bytes loaded"); 441 442 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 443 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(), 444 **MI.memoperands_begin()); 445 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 446 MI.eraseFromParent(); 447 return Legalized; 448 } 449 case TargetOpcode::G_STORE: { 450 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) == 451 WideTy.getSizeInBits() && 452 "illegal to increase number of bytes modified by a store"); 453 454 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 455 MIRBuilder.buildAnyExt(SrcExt, MI.getOperand(0).getReg()); 456 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(), 457 **MI.memoperands_begin()); 458 MI.eraseFromParent(); 459 return Legalized; 460 } 461 case TargetOpcode::G_CONSTANT: { 462 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 463 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm()); 464 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 465 MI.eraseFromParent(); 466 return Legalized; 467 } 468 case TargetOpcode::G_FCONSTANT: { 469 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 470 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm()); 471 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt); 472 MI.eraseFromParent(); 473 return Legalized; 474 } 475 case TargetOpcode::G_BRCOND: { 476 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy); 477 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg()); 478 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB()); 479 MI.eraseFromParent(); 480 return Legalized; 481 } 482 case TargetOpcode::G_ICMP: { 483 assert(TypeIdx == 1 && "unable to legalize predicate"); 484 bool IsSigned = CmpInst::isSigned( 485 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate())); 486 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy); 487 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy); 488 if (IsSigned) { 489 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg()); 490 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg()); 491 } else { 492 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg()); 493 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg()); 494 } 495 MIRBuilder.buildICmp( 496 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 497 MI.getOperand(0).getReg(), Op0Ext, Op1Ext); 498 MI.eraseFromParent(); 499 return Legalized; 500 } 501 case TargetOpcode::G_GEP: { 502 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 503 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy); 504 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg()); 505 MI.getOperand(2).setReg(OffsetExt); 506 return Legalized; 507 } 508 } 509 } 510 511 LegalizerHelper::LegalizeResult 512 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 513 using namespace TargetOpcode; 514 MIRBuilder.setInstr(MI); 515 516 switch(MI.getOpcode()) { 517 default: 518 return UnableToLegalize; 519 case TargetOpcode::G_SREM: 520 case TargetOpcode::G_UREM: { 521 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty); 522 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 523 .addDef(QuotReg) 524 .addUse(MI.getOperand(1).getReg()) 525 .addUse(MI.getOperand(2).getReg()); 526 527 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty); 528 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 529 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 530 ProdReg); 531 MI.eraseFromParent(); 532 return Legalized; 533 } 534 case TargetOpcode::G_SMULO: 535 case TargetOpcode::G_UMULO: { 536 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 537 // result. 538 unsigned Res = MI.getOperand(0).getReg(); 539 unsigned Overflow = MI.getOperand(1).getReg(); 540 unsigned LHS = MI.getOperand(2).getReg(); 541 unsigned RHS = MI.getOperand(3).getReg(); 542 543 MIRBuilder.buildMul(Res, LHS, RHS); 544 545 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 546 ? TargetOpcode::G_SMULH 547 : TargetOpcode::G_UMULH; 548 549 unsigned HiPart = MRI.createGenericVirtualRegister(Ty); 550 MIRBuilder.buildInstr(Opcode) 551 .addDef(HiPart) 552 .addUse(LHS) 553 .addUse(RHS); 554 555 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 556 MIRBuilder.buildConstant(Zero, 0); 557 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 558 MI.eraseFromParent(); 559 return Legalized; 560 } 561 } 562 } 563 564 LegalizerHelper::LegalizeResult 565 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 566 LLT NarrowTy) { 567 // FIXME: Don't know how to handle secondary types yet. 568 if (TypeIdx != 0) 569 return UnableToLegalize; 570 switch (MI.getOpcode()) { 571 default: 572 return UnableToLegalize; 573 case TargetOpcode::G_ADD: { 574 unsigned NarrowSize = NarrowTy.getSizeInBits(); 575 unsigned DstReg = MI.getOperand(0).getReg(); 576 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize; 577 578 MIRBuilder.setInstr(MI); 579 580 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 581 SmallVector<uint64_t, 2> Indexes; 582 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 583 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 584 585 for (int i = 0; i < NumParts; ++i) { 586 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 587 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]); 588 DstRegs.push_back(DstReg); 589 Indexes.push_back(i * NarrowSize); 590 } 591 592 MIRBuilder.buildSequence(DstReg, DstRegs, Indexes); 593 MI.eraseFromParent(); 594 return Legalized; 595 } 596 } 597 } 598