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 "legalizer" 28 29 using namespace llvm; 30 31 LegalizerHelper::LegalizerHelper(MachineFunction &MF) 32 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) { 33 MIRBuilder.setMF(MF); 34 } 35 36 LegalizerHelper::LegalizeResult 37 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) { 38 DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs())); 39 40 auto Action = LI.getAction(MI, MRI); 41 switch (std::get<0>(Action)) { 42 case LegalizerInfo::Legal: 43 DEBUG(dbgs() << ".. Already legal\n"); 44 return AlreadyLegal; 45 case LegalizerInfo::Libcall: 46 DEBUG(dbgs() << ".. Convert to libcall\n"); 47 return libcall(MI); 48 case LegalizerInfo::NarrowScalar: 49 DEBUG(dbgs() << ".. Narrow scalar\n"); 50 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action)); 51 case LegalizerInfo::WidenScalar: 52 DEBUG(dbgs() << ".. Widen scalar\n"); 53 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action)); 54 case LegalizerInfo::Lower: 55 DEBUG(dbgs() << ".. Lower\n"); 56 return lower(MI, std::get<1>(Action), std::get<2>(Action)); 57 case LegalizerInfo::FewerElements: 58 DEBUG(dbgs() << ".. Reduce number of elements\n"); 59 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action)); 60 case LegalizerInfo::Custom: 61 DEBUG(dbgs() << ".. Custom legalization\n"); 62 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized 63 : UnableToLegalize; 64 default: 65 DEBUG(dbgs() << ".. Unable to legalize\n"); 66 return UnableToLegalize; 67 } 68 } 69 70 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts, 71 SmallVectorImpl<unsigned> &VRegs) { 72 for (int i = 0; i < NumParts; ++i) 73 VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); 74 MIRBuilder.buildUnmerge(VRegs, Reg); 75 } 76 77 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { 78 switch (Opcode) { 79 case TargetOpcode::G_FADD: 80 assert((Size == 32 || Size == 64) && "Unsupported size"); 81 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; 82 case TargetOpcode::G_FREM: 83 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; 84 case TargetOpcode::G_FPOW: 85 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; 86 } 87 llvm_unreachable("Unknown libcall function"); 88 } 89 90 LegalizerHelper::LegalizeResult 91 LegalizerHelper::libcall(MachineInstr &MI) { 92 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 93 unsigned Size = Ty.getSizeInBits(); 94 MIRBuilder.setInstr(MI); 95 96 switch (MI.getOpcode()) { 97 default: 98 return UnableToLegalize; 99 case TargetOpcode::G_FADD: 100 case TargetOpcode::G_FPOW: 101 case TargetOpcode::G_FREM: { 102 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 103 Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); 104 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 105 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 106 auto Libcall = getRTLibDesc(MI.getOpcode(), Size); 107 const char *Name = TLI.getLibcallName(Libcall); 108 MIRBuilder.getMF().getFrameInfo().setHasCalls(true); 109 CLI.lowerCall( 110 MIRBuilder, TLI.getLibcallCallingConv(Libcall), 111 MachineOperand::CreateES(Name), {MI.getOperand(0).getReg(), Ty}, 112 {{MI.getOperand(1).getReg(), Ty}, {MI.getOperand(2).getReg(), Ty}}); 113 MI.eraseFromParent(); 114 return Legalized; 115 } 116 } 117 } 118 119 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 120 unsigned TypeIdx, 121 LLT NarrowTy) { 122 // FIXME: Don't know how to handle secondary types yet. 123 if (TypeIdx != 0) 124 return UnableToLegalize; 125 126 MIRBuilder.setInstr(MI); 127 128 switch (MI.getOpcode()) { 129 default: 130 return UnableToLegalize; 131 case TargetOpcode::G_ADD: { 132 // Expand in terms of carry-setting/consuming G_ADDE instructions. 133 int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / 134 NarrowTy.getSizeInBits(); 135 136 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 137 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 138 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 139 140 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1)); 141 MIRBuilder.buildConstant(CarryIn, 0); 142 143 for (int i = 0; i < NumParts; ++i) { 144 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 145 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 146 147 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], 148 Src2Regs[i], CarryIn); 149 150 DstRegs.push_back(DstReg); 151 CarryIn = CarryOut; 152 } 153 unsigned DstReg = MI.getOperand(0).getReg(); 154 MIRBuilder.buildMerge(DstReg, DstRegs); 155 MI.eraseFromParent(); 156 return Legalized; 157 } 158 case TargetOpcode::G_INSERT: { 159 if (TypeIdx != 0) 160 return UnableToLegalize; 161 162 int64_t NarrowSize = NarrowTy.getSizeInBits(); 163 int NumParts = 164 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 165 166 SmallVector<unsigned, 2> SrcRegs, DstRegs; 167 SmallVector<uint64_t, 2> Indexes; 168 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 169 170 unsigned OpReg = MI.getOperand(2).getReg(); 171 int64_t OpStart = MI.getOperand(3).getImm(); 172 int64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 173 for (int i = 0; i < NumParts; ++i) { 174 unsigned DstStart = i * NarrowSize; 175 176 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { 177 // No part of the insert affects this subregister, forward the original. 178 DstRegs.push_back(SrcRegs[i]); 179 continue; 180 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 181 // The entire subregister is defined by this insert, forward the new 182 // value. 183 DstRegs.push_back(OpReg); 184 continue; 185 } 186 187 // OpSegStart is where this destination segment would start in OpReg if it 188 // extended infinitely in both directions. 189 int64_t ExtractOffset, InsertOffset, SegSize; 190 if (OpStart < DstStart) { 191 InsertOffset = 0; 192 ExtractOffset = DstStart - OpStart; 193 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); 194 } else { 195 InsertOffset = OpStart - DstStart; 196 ExtractOffset = 0; 197 SegSize = 198 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); 199 } 200 201 unsigned SegReg = OpReg; 202 if (ExtractOffset != 0 || SegSize != OpSize) { 203 // A genuine extract is needed. 204 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 205 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); 206 } 207 208 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 209 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); 210 DstRegs.push_back(DstReg); 211 } 212 213 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); 214 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 215 MI.eraseFromParent(); 216 return Legalized; 217 } 218 case TargetOpcode::G_LOAD: { 219 unsigned NarrowSize = NarrowTy.getSizeInBits(); 220 int NumParts = 221 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 222 LLT NarrowPtrTy = LLT::pointer( 223 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize); 224 225 SmallVector<unsigned, 2> DstRegs; 226 for (int i = 0; i < NumParts; ++i) { 227 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 228 unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy); 229 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64)); 230 231 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8); 232 MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset); 233 // TODO: This is conservatively correct, but we probably want to split the 234 // memory operands in the future. 235 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin()); 236 237 DstRegs.push_back(DstReg); 238 } 239 unsigned DstReg = MI.getOperand(0).getReg(); 240 MIRBuilder.buildMerge(DstReg, DstRegs); 241 MI.eraseFromParent(); 242 return Legalized; 243 } 244 case TargetOpcode::G_STORE: { 245 unsigned NarrowSize = NarrowTy.getSizeInBits(); 246 int NumParts = 247 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 248 LLT NarrowPtrTy = LLT::pointer( 249 MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize); 250 251 SmallVector<unsigned, 2> SrcRegs; 252 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs); 253 254 for (int i = 0; i < NumParts; ++i) { 255 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy); 256 unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64)); 257 MIRBuilder.buildConstant(Offset, i * NarrowSize / 8); 258 MIRBuilder.buildGEP(DstReg, 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.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin()); 262 } 263 MI.eraseFromParent(); 264 return Legalized; 265 } 266 case TargetOpcode::G_CONSTANT: { 267 unsigned NarrowSize = NarrowTy.getSizeInBits(); 268 int NumParts = 269 MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; 270 const APInt &Cst = MI.getOperand(1).getCImm()->getValue(); 271 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 272 273 SmallVector<unsigned, 2> DstRegs; 274 for (int i = 0; i < NumParts; ++i) { 275 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 276 ConstantInt *CI = 277 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize)); 278 MIRBuilder.buildConstant(DstReg, *CI); 279 DstRegs.push_back(DstReg); 280 } 281 unsigned DstReg = MI.getOperand(0).getReg(); 282 MIRBuilder.buildMerge(DstReg, DstRegs); 283 MI.eraseFromParent(); 284 return Legalized; 285 } 286 } 287 } 288 289 LegalizerHelper::LegalizeResult 290 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 291 MIRBuilder.setInstr(MI); 292 293 switch (MI.getOpcode()) { 294 default: 295 return UnableToLegalize; 296 case TargetOpcode::G_ADD: 297 case TargetOpcode::G_AND: 298 case TargetOpcode::G_MUL: 299 case TargetOpcode::G_OR: 300 case TargetOpcode::G_XOR: 301 case TargetOpcode::G_SUB: 302 case TargetOpcode::G_SHL: { 303 // Perform operation at larger width (any extension is fine here, high bits 304 // don't affect the result) and then truncate the result back to the 305 // original type. 306 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 307 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 308 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg()); 309 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg()); 310 311 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 312 MIRBuilder.buildInstr(MI.getOpcode()) 313 .addDef(DstExt) 314 .addUse(Src1Ext) 315 .addUse(Src2Ext); 316 317 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 318 MI.eraseFromParent(); 319 return Legalized; 320 } 321 case TargetOpcode::G_SDIV: 322 case TargetOpcode::G_UDIV: 323 case TargetOpcode::G_ASHR: 324 case TargetOpcode::G_LSHR: { 325 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV || 326 MI.getOpcode() == TargetOpcode::G_ASHR 327 ? TargetOpcode::G_SEXT 328 : TargetOpcode::G_ZEXT; 329 330 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy); 331 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse( 332 MI.getOperand(1).getReg()); 333 334 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy); 335 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse( 336 MI.getOperand(2).getReg()); 337 338 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy); 339 MIRBuilder.buildInstr(MI.getOpcode()) 340 .addDef(ResExt) 341 .addUse(LHSExt) 342 .addUse(RHSExt); 343 344 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt); 345 MI.eraseFromParent(); 346 return Legalized; 347 } 348 case TargetOpcode::G_SELECT: { 349 if (TypeIdx != 0) 350 return UnableToLegalize; 351 352 // Perform operation at larger width (any extension is fine here, high bits 353 // don't affect the result) and then truncate the result back to the 354 // original type. 355 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 356 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 357 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg()); 358 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg()); 359 360 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 361 MIRBuilder.buildInstr(TargetOpcode::G_SELECT) 362 .addDef(DstExt) 363 .addReg(MI.getOperand(1).getReg()) 364 .addUse(Src1Ext) 365 .addUse(Src2Ext); 366 367 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 368 MI.eraseFromParent(); 369 return Legalized; 370 } 371 case TargetOpcode::G_FPTOSI: 372 case TargetOpcode::G_FPTOUI: { 373 if (TypeIdx != 0) 374 return UnableToLegalize; 375 376 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 377 MIRBuilder.buildInstr(MI.getOpcode()) 378 .addDef(DstExt) 379 .addUse(MI.getOperand(1).getReg()); 380 381 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 382 MI.eraseFromParent(); 383 return Legalized; 384 } 385 case TargetOpcode::G_SITOFP: 386 case TargetOpcode::G_UITOFP: { 387 if (TypeIdx != 1) 388 return UnableToLegalize; 389 390 unsigned Src = MI.getOperand(1).getReg(); 391 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 392 393 if (MI.getOpcode() == TargetOpcode::G_SITOFP) { 394 MIRBuilder.buildSExt(SrcExt, Src); 395 } else { 396 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op"); 397 MIRBuilder.buildZExt(SrcExt, Src); 398 } 399 400 MIRBuilder.buildInstr(MI.getOpcode()) 401 .addDef(MI.getOperand(0).getReg()) 402 .addUse(SrcExt); 403 404 MI.eraseFromParent(); 405 return Legalized; 406 } 407 case TargetOpcode::G_INSERT: { 408 if (TypeIdx != 0) 409 return UnableToLegalize; 410 411 unsigned Src = MI.getOperand(1).getReg(); 412 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 413 MIRBuilder.buildAnyExt(SrcExt, Src); 414 415 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 416 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(), 417 MI.getOperand(3).getImm()); 418 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) { 419 MIB.addReg(MI.getOperand(OpNum).getReg()); 420 MIB.addImm(MI.getOperand(OpNum + 1).getImm()); 421 } 422 423 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 424 MI.eraseFromParent(); 425 return Legalized; 426 } 427 case TargetOpcode::G_LOAD: { 428 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) == 429 WideTy.getSizeInBits() && 430 "illegal to increase number of bytes loaded"); 431 432 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 433 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(), 434 **MI.memoperands_begin()); 435 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 436 MI.eraseFromParent(); 437 return Legalized; 438 } 439 case TargetOpcode::G_STORE: { 440 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) || 441 WideTy != LLT::scalar(8)) 442 return UnableToLegalize; 443 444 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 445 auto Content = TLI.getBooleanContents(false, false); 446 447 unsigned ExtOp = TargetOpcode::G_ANYEXT; 448 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent) 449 ExtOp = TargetOpcode::G_ZEXT; 450 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent) 451 ExtOp = TargetOpcode::G_SEXT; 452 else 453 ExtOp = TargetOpcode::G_ANYEXT; 454 455 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 456 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse( 457 MI.getOperand(0).getReg()); 458 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(), 459 **MI.memoperands_begin()); 460 MI.eraseFromParent(); 461 return Legalized; 462 } 463 case TargetOpcode::G_CONSTANT: { 464 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 465 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm()); 466 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 467 MI.eraseFromParent(); 468 return Legalized; 469 } 470 case TargetOpcode::G_FCONSTANT: { 471 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 472 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm()); 473 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt); 474 MI.eraseFromParent(); 475 return Legalized; 476 } 477 case TargetOpcode::G_BRCOND: { 478 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy); 479 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg()); 480 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB()); 481 MI.eraseFromParent(); 482 return Legalized; 483 } 484 case TargetOpcode::G_ICMP: { 485 assert(TypeIdx == 1 && "unable to legalize predicate"); 486 bool IsSigned = CmpInst::isSigned( 487 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate())); 488 unsigned Op0Ext = MRI.createGenericVirtualRegister(WideTy); 489 unsigned Op1Ext = MRI.createGenericVirtualRegister(WideTy); 490 if (IsSigned) { 491 MIRBuilder.buildSExt(Op0Ext, MI.getOperand(2).getReg()); 492 MIRBuilder.buildSExt(Op1Ext, MI.getOperand(3).getReg()); 493 } else { 494 MIRBuilder.buildZExt(Op0Ext, MI.getOperand(2).getReg()); 495 MIRBuilder.buildZExt(Op1Ext, MI.getOperand(3).getReg()); 496 } 497 MIRBuilder.buildICmp( 498 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 499 MI.getOperand(0).getReg(), Op0Ext, Op1Ext); 500 MI.eraseFromParent(); 501 return Legalized; 502 } 503 case TargetOpcode::G_GEP: { 504 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 505 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy); 506 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg()); 507 MI.getOperand(2).setReg(OffsetExt); 508 return Legalized; 509 } 510 } 511 } 512 513 LegalizerHelper::LegalizeResult 514 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 515 using namespace TargetOpcode; 516 MIRBuilder.setInstr(MI); 517 518 switch(MI.getOpcode()) { 519 default: 520 return UnableToLegalize; 521 case TargetOpcode::G_SREM: 522 case TargetOpcode::G_UREM: { 523 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty); 524 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 525 .addDef(QuotReg) 526 .addUse(MI.getOperand(1).getReg()) 527 .addUse(MI.getOperand(2).getReg()); 528 529 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty); 530 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 531 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 532 ProdReg); 533 MI.eraseFromParent(); 534 return Legalized; 535 } 536 case TargetOpcode::G_SMULO: 537 case TargetOpcode::G_UMULO: { 538 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 539 // result. 540 unsigned Res = MI.getOperand(0).getReg(); 541 unsigned Overflow = MI.getOperand(1).getReg(); 542 unsigned LHS = MI.getOperand(2).getReg(); 543 unsigned RHS = MI.getOperand(3).getReg(); 544 545 MIRBuilder.buildMul(Res, LHS, RHS); 546 547 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 548 ? TargetOpcode::G_SMULH 549 : TargetOpcode::G_UMULH; 550 551 unsigned HiPart = MRI.createGenericVirtualRegister(Ty); 552 MIRBuilder.buildInstr(Opcode) 553 .addDef(HiPart) 554 .addUse(LHS) 555 .addUse(RHS); 556 557 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 558 MIRBuilder.buildConstant(Zero, 0); 559 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 560 MI.eraseFromParent(); 561 return Legalized; 562 } 563 case TargetOpcode::G_FNEG: { 564 // TODO: Handle vector types once we are able to 565 // represent them. 566 if (Ty.isVector()) 567 return UnableToLegalize; 568 unsigned Res = MI.getOperand(0).getReg(); 569 Type *ZeroTy; 570 LLVMContext &Ctx = MIRBuilder.getMF().getFunction()->getContext(); 571 switch (Ty.getSizeInBits()) { 572 case 16: 573 ZeroTy = Type::getHalfTy(Ctx); 574 break; 575 case 32: 576 ZeroTy = Type::getFloatTy(Ctx); 577 break; 578 case 64: 579 ZeroTy = Type::getDoubleTy(Ctx); 580 break; 581 default: 582 llvm_unreachable("unexpected floating-point type"); 583 } 584 ConstantFP &ZeroForNegation = 585 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); 586 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 587 MIRBuilder.buildFConstant(Zero, ZeroForNegation); 588 MIRBuilder.buildInstr(TargetOpcode::G_FSUB) 589 .addDef(Res) 590 .addUse(Zero) 591 .addUse(MI.getOperand(1).getReg()); 592 MI.eraseFromParent(); 593 return Legalized; 594 } 595 case TargetOpcode::G_FSUB: { 596 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 597 // First, check if G_FNEG is marked as Lower. If so, we may 598 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 599 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower) 600 return UnableToLegalize; 601 unsigned Res = MI.getOperand(0).getReg(); 602 unsigned LHS = MI.getOperand(1).getReg(); 603 unsigned RHS = MI.getOperand(2).getReg(); 604 unsigned Neg = MRI.createGenericVirtualRegister(Ty); 605 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); 606 MIRBuilder.buildInstr(TargetOpcode::G_FADD) 607 .addDef(Res) 608 .addUse(LHS) 609 .addUse(Neg); 610 MI.eraseFromParent(); 611 return Legalized; 612 } 613 } 614 } 615 616 LegalizerHelper::LegalizeResult 617 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 618 LLT NarrowTy) { 619 // FIXME: Don't know how to handle secondary types yet. 620 if (TypeIdx != 0) 621 return UnableToLegalize; 622 switch (MI.getOpcode()) { 623 default: 624 return UnableToLegalize; 625 case TargetOpcode::G_ADD: { 626 unsigned NarrowSize = NarrowTy.getSizeInBits(); 627 unsigned DstReg = MI.getOperand(0).getReg(); 628 int NumParts = MRI.getType(DstReg).getSizeInBits() / NarrowSize; 629 630 MIRBuilder.setInstr(MI); 631 632 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 633 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 634 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 635 636 for (int i = 0; i < NumParts; ++i) { 637 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 638 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]); 639 DstRegs.push_back(DstReg); 640 } 641 642 MIRBuilder.buildMerge(DstReg, DstRegs); 643 MI.eraseFromParent(); 644 return Legalized; 645 } 646 } 647 } 648