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