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