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