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/CodeGen/TargetLowering.h" 21 #include "llvm/CodeGen/TargetSubtargetInfo.h" 22 #include "llvm/Support/Debug.h" 23 #include "llvm/Support/raw_ostream.h" 24 25 26 #define DEBUG_TYPE "legalizer" 27 28 using namespace llvm; 29 30 LegalizerHelper::LegalizerHelper(MachineFunction &MF) 31 : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) { 32 MIRBuilder.setMF(MF); 33 } 34 35 LegalizerHelper::LegalizeResult 36 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) { 37 DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs())); 38 39 auto Action = LI.getAction(MI, MRI); 40 switch (std::get<0>(Action)) { 41 case LegalizerInfo::Legal: 42 DEBUG(dbgs() << ".. Already legal\n"); 43 return AlreadyLegal; 44 case LegalizerInfo::Libcall: 45 DEBUG(dbgs() << ".. Convert to libcall\n"); 46 return libcall(MI); 47 case LegalizerInfo::NarrowScalar: 48 DEBUG(dbgs() << ".. Narrow scalar\n"); 49 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action)); 50 case LegalizerInfo::WidenScalar: 51 DEBUG(dbgs() << ".. Widen scalar\n"); 52 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action)); 53 case LegalizerInfo::Lower: 54 DEBUG(dbgs() << ".. Lower\n"); 55 return lower(MI, std::get<1>(Action), std::get<2>(Action)); 56 case LegalizerInfo::FewerElements: 57 DEBUG(dbgs() << ".. Reduce number of elements\n"); 58 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action)); 59 case LegalizerInfo::Custom: 60 DEBUG(dbgs() << ".. Custom legalization\n"); 61 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized 62 : UnableToLegalize; 63 default: 64 DEBUG(dbgs() << ".. Unable to legalize\n"); 65 return UnableToLegalize; 66 } 67 } 68 69 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts, 70 SmallVectorImpl<unsigned> &VRegs) { 71 for (int i = 0; i < NumParts; ++i) 72 VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); 73 MIRBuilder.buildUnmerge(VRegs, Reg); 74 } 75 76 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { 77 switch (Opcode) { 78 case TargetOpcode::G_SDIV: 79 assert(Size == 32 && "Unsupported size"); 80 return RTLIB::SDIV_I32; 81 case TargetOpcode::G_UDIV: 82 assert(Size == 32 && "Unsupported size"); 83 return RTLIB::UDIV_I32; 84 case TargetOpcode::G_SREM: 85 assert(Size == 32 && "Unsupported size"); 86 return RTLIB::SREM_I32; 87 case TargetOpcode::G_UREM: 88 assert(Size == 32 && "Unsupported size"); 89 return RTLIB::UREM_I32; 90 case TargetOpcode::G_FADD: 91 assert((Size == 32 || Size == 64) && "Unsupported size"); 92 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; 93 case TargetOpcode::G_FSUB: 94 assert((Size == 32 || Size == 64) && "Unsupported size"); 95 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32; 96 case TargetOpcode::G_FMUL: 97 assert((Size == 32 || Size == 64) && "Unsupported size"); 98 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32; 99 case TargetOpcode::G_FDIV: 100 assert((Size == 32 || Size == 64) && "Unsupported size"); 101 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32; 102 case TargetOpcode::G_FREM: 103 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; 104 case TargetOpcode::G_FPOW: 105 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; 106 } 107 llvm_unreachable("Unknown libcall function"); 108 } 109 110 LegalizerHelper::LegalizeResult 111 llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, 112 const CallLowering::ArgInfo &Result, 113 ArrayRef<CallLowering::ArgInfo> Args) { 114 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 115 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 116 const char *Name = TLI.getLibcallName(Libcall); 117 118 MIRBuilder.getMF().getFrameInfo().setHasCalls(true); 119 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall), 120 MachineOperand::CreateES(Name), Result, Args)) 121 return LegalizerHelper::UnableToLegalize; 122 123 return LegalizerHelper::Legalized; 124 } 125 126 static LegalizerHelper::LegalizeResult 127 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, 128 Type *OpType) { 129 auto Libcall = getRTLibDesc(MI.getOpcode(), Size); 130 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType}, 131 {{MI.getOperand(1).getReg(), OpType}, 132 {MI.getOperand(2).getReg(), OpType}}); 133 } 134 135 LegalizerHelper::LegalizeResult 136 LegalizerHelper::libcall(MachineInstr &MI) { 137 LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); 138 unsigned Size = LLTy.getSizeInBits(); 139 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 140 141 MIRBuilder.setInstr(MI); 142 143 switch (MI.getOpcode()) { 144 default: 145 return UnableToLegalize; 146 case TargetOpcode::G_SDIV: 147 case TargetOpcode::G_UDIV: 148 case TargetOpcode::G_SREM: 149 case TargetOpcode::G_UREM: { 150 Type *HLTy = Type::getInt32Ty(Ctx); 151 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 152 if (Status != Legalized) 153 return Status; 154 break; 155 } 156 case TargetOpcode::G_FADD: 157 case TargetOpcode::G_FSUB: 158 case TargetOpcode::G_FMUL: 159 case TargetOpcode::G_FDIV: 160 case TargetOpcode::G_FPOW: 161 case TargetOpcode::G_FREM: { 162 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); 163 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 164 if (Status != Legalized) 165 return Status; 166 break; 167 } 168 } 169 170 MI.eraseFromParent(); 171 return Legalized; 172 } 173 174 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 175 unsigned TypeIdx, 176 LLT NarrowTy) { 177 // FIXME: Don't know how to handle secondary types yet. 178 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT) 179 return UnableToLegalize; 180 181 MIRBuilder.setInstr(MI); 182 183 int64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 184 int64_t NarrowSize = NarrowTy.getSizeInBits(); 185 186 switch (MI.getOpcode()) { 187 default: 188 return UnableToLegalize; 189 case TargetOpcode::G_IMPLICIT_DEF: { 190 // FIXME: add support for when SizeOp0 isn't an exact multiple of 191 // NarrowSize. 192 if (SizeOp0 % NarrowSize != 0) 193 return UnableToLegalize; 194 int NumParts = SizeOp0 / NarrowSize; 195 196 SmallVector<unsigned, 2> DstRegs; 197 for (int i = 0; i < NumParts; ++i) { 198 unsigned Dst = MRI.createGenericVirtualRegister(NarrowTy); 199 MIRBuilder.buildUndef(Dst); 200 DstRegs.push_back(Dst); 201 } 202 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 203 MI.eraseFromParent(); 204 return Legalized; 205 } 206 case TargetOpcode::G_ADD: { 207 // FIXME: add support for when SizeOp0 isn't an exact multiple of 208 // NarrowSize. 209 if (SizeOp0 % NarrowSize != 0) 210 return UnableToLegalize; 211 // Expand in terms of carry-setting/consuming G_ADDE instructions. 212 int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); 213 214 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 215 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 216 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 217 218 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1)); 219 MIRBuilder.buildConstant(CarryIn, 0); 220 221 for (int i = 0; i < NumParts; ++i) { 222 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 223 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 224 225 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], 226 Src2Regs[i], CarryIn); 227 228 DstRegs.push_back(DstReg); 229 CarryIn = CarryOut; 230 } 231 unsigned DstReg = MI.getOperand(0).getReg(); 232 MIRBuilder.buildMerge(DstReg, DstRegs); 233 MI.eraseFromParent(); 234 return Legalized; 235 } 236 case TargetOpcode::G_EXTRACT: { 237 if (TypeIdx != 1) 238 return UnableToLegalize; 239 240 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 241 // FIXME: add support for when SizeOp1 isn't an exact multiple of 242 // NarrowSize. 243 if (SizeOp1 % NarrowSize != 0) 244 return UnableToLegalize; 245 int NumParts = SizeOp1 / NarrowSize; 246 247 SmallVector<unsigned, 2> SrcRegs, DstRegs; 248 SmallVector<uint64_t, 2> Indexes; 249 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 250 251 unsigned OpReg = MI.getOperand(0).getReg(); 252 int64_t OpStart = MI.getOperand(2).getImm(); 253 int64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 254 for (int i = 0; i < NumParts; ++i) { 255 unsigned SrcStart = i * NarrowSize; 256 257 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) { 258 // No part of the extract uses this subregister, ignore it. 259 continue; 260 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 261 // The entire subregister is extracted, forward the value. 262 DstRegs.push_back(SrcRegs[i]); 263 continue; 264 } 265 266 // OpSegStart is where this destination segment would start in OpReg if it 267 // extended infinitely in both directions. 268 int64_t ExtractOffset, SegSize; 269 if (OpStart < SrcStart) { 270 ExtractOffset = 0; 271 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart); 272 } else { 273 ExtractOffset = OpStart - SrcStart; 274 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize); 275 } 276 277 unsigned SegReg = SrcRegs[i]; 278 if (ExtractOffset != 0 || SegSize != NarrowSize) { 279 // A genuine extract is needed. 280 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 281 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset); 282 } 283 284 DstRegs.push_back(SegReg); 285 } 286 287 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 288 MI.eraseFromParent(); 289 return Legalized; 290 } 291 case TargetOpcode::G_INSERT: { 292 // FIXME: add support for when SizeOp0 isn't an exact multiple of 293 // NarrowSize. 294 if (SizeOp0 % NarrowSize != 0) 295 return UnableToLegalize; 296 297 int NumParts = SizeOp0 / NarrowSize; 298 299 SmallVector<unsigned, 2> SrcRegs, DstRegs; 300 SmallVector<uint64_t, 2> Indexes; 301 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 302 303 unsigned OpReg = MI.getOperand(2).getReg(); 304 int64_t OpStart = MI.getOperand(3).getImm(); 305 int64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 306 for (int i = 0; i < NumParts; ++i) { 307 unsigned DstStart = i * NarrowSize; 308 309 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { 310 // No part of the insert affects this subregister, forward the original. 311 DstRegs.push_back(SrcRegs[i]); 312 continue; 313 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 314 // The entire subregister is defined by this insert, forward the new 315 // value. 316 DstRegs.push_back(OpReg); 317 continue; 318 } 319 320 // OpSegStart is where this destination segment would start in OpReg if it 321 // extended infinitely in both directions. 322 int64_t ExtractOffset, InsertOffset, SegSize; 323 if (OpStart < DstStart) { 324 InsertOffset = 0; 325 ExtractOffset = DstStart - OpStart; 326 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); 327 } else { 328 InsertOffset = OpStart - DstStart; 329 ExtractOffset = 0; 330 SegSize = 331 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); 332 } 333 334 unsigned SegReg = OpReg; 335 if (ExtractOffset != 0 || SegSize != OpSize) { 336 // A genuine extract is needed. 337 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 338 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); 339 } 340 341 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 342 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); 343 DstRegs.push_back(DstReg); 344 } 345 346 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); 347 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 348 MI.eraseFromParent(); 349 return Legalized; 350 } 351 case TargetOpcode::G_LOAD: { 352 // FIXME: add support for when SizeOp0 isn't an exact multiple of 353 // NarrowSize. 354 if (SizeOp0 % NarrowSize != 0) 355 return UnableToLegalize; 356 int NumParts = SizeOp0 / NarrowSize; 357 LLT OffsetTy = LLT::scalar( 358 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); 359 360 SmallVector<unsigned, 2> DstRegs; 361 for (int i = 0; i < NumParts; ++i) { 362 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 363 unsigned SrcReg = 0; 364 unsigned Adjustment = i * NarrowSize / 8; 365 366 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy, 367 Adjustment); 368 369 // TODO: This is conservatively correct, but we probably want to split the 370 // memory operands in the future. 371 MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin()); 372 373 DstRegs.push_back(DstReg); 374 } 375 unsigned DstReg = MI.getOperand(0).getReg(); 376 MIRBuilder.buildMerge(DstReg, DstRegs); 377 MI.eraseFromParent(); 378 return Legalized; 379 } 380 case TargetOpcode::G_STORE: { 381 // FIXME: add support for when SizeOp0 isn't an exact multiple of 382 // NarrowSize. 383 if (SizeOp0 % NarrowSize != 0) 384 return UnableToLegalize; 385 int NumParts = SizeOp0 / NarrowSize; 386 LLT OffsetTy = LLT::scalar( 387 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); 388 389 SmallVector<unsigned, 2> SrcRegs; 390 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs); 391 392 for (int i = 0; i < NumParts; ++i) { 393 unsigned DstReg = 0; 394 unsigned Adjustment = i * NarrowSize / 8; 395 396 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy, 397 Adjustment); 398 399 // TODO: This is conservatively correct, but we probably want to split the 400 // memory operands in the future. 401 MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin()); 402 } 403 MI.eraseFromParent(); 404 return Legalized; 405 } 406 case TargetOpcode::G_CONSTANT: { 407 // FIXME: add support for when SizeOp0 isn't an exact multiple of 408 // NarrowSize. 409 if (SizeOp0 % NarrowSize != 0) 410 return UnableToLegalize; 411 int NumParts = SizeOp0 / NarrowSize; 412 const APInt &Cst = MI.getOperand(1).getCImm()->getValue(); 413 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 414 415 SmallVector<unsigned, 2> DstRegs; 416 for (int i = 0; i < NumParts; ++i) { 417 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 418 ConstantInt *CI = 419 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize)); 420 MIRBuilder.buildConstant(DstReg, *CI); 421 DstRegs.push_back(DstReg); 422 } 423 unsigned DstReg = MI.getOperand(0).getReg(); 424 MIRBuilder.buildMerge(DstReg, DstRegs); 425 MI.eraseFromParent(); 426 return Legalized; 427 } 428 case TargetOpcode::G_OR: { 429 // Legalize bitwise operation: 430 // A = BinOp<Ty> B, C 431 // into: 432 // B1, ..., BN = G_UNMERGE_VALUES B 433 // C1, ..., CN = G_UNMERGE_VALUES C 434 // A1 = BinOp<Ty/N> B1, C2 435 // ... 436 // AN = BinOp<Ty/N> BN, CN 437 // A = G_MERGE_VALUES A1, ..., AN 438 439 // FIXME: add support for when SizeOp0 isn't an exact multiple of 440 // NarrowSize. 441 if (SizeOp0 % NarrowSize != 0) 442 return UnableToLegalize; 443 int NumParts = SizeOp0 / NarrowSize; 444 445 // List the registers where the destination will be scattered. 446 SmallVector<unsigned, 2> DstRegs; 447 // List the registers where the first argument will be split. 448 SmallVector<unsigned, 2> SrcsReg1; 449 // List the registers where the second argument will be split. 450 SmallVector<unsigned, 2> SrcsReg2; 451 // Create all the temporary registers. 452 for (int i = 0; i < NumParts; ++i) { 453 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 454 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy); 455 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy); 456 457 DstRegs.push_back(DstReg); 458 SrcsReg1.push_back(SrcReg1); 459 SrcsReg2.push_back(SrcReg2); 460 } 461 // Explode the big arguments into smaller chunks. 462 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg()); 463 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg()); 464 465 // Do the operation on each small part. 466 for (int i = 0; i < NumParts; ++i) 467 MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]); 468 469 // Gather the destination registers into the final destination. 470 unsigned DstReg = MI.getOperand(0).getReg(); 471 MIRBuilder.buildMerge(DstReg, DstRegs); 472 MI.eraseFromParent(); 473 return Legalized; 474 } 475 } 476 } 477 478 LegalizerHelper::LegalizeResult 479 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 480 MIRBuilder.setInstr(MI); 481 482 switch (MI.getOpcode()) { 483 default: 484 return UnableToLegalize; 485 case TargetOpcode::G_ADD: 486 case TargetOpcode::G_AND: 487 case TargetOpcode::G_MUL: 488 case TargetOpcode::G_OR: 489 case TargetOpcode::G_XOR: 490 case TargetOpcode::G_SUB: 491 case TargetOpcode::G_SHL: { 492 // Perform operation at larger width (any extension is fine here, high bits 493 // don't affect the result) and then truncate the result back to the 494 // original type. 495 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 496 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 497 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg()); 498 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg()); 499 500 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 501 MIRBuilder.buildInstr(MI.getOpcode()) 502 .addDef(DstExt) 503 .addUse(Src1Ext) 504 .addUse(Src2Ext); 505 506 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 507 MI.eraseFromParent(); 508 return Legalized; 509 } 510 case TargetOpcode::G_SDIV: 511 case TargetOpcode::G_UDIV: 512 case TargetOpcode::G_SREM: 513 case TargetOpcode::G_UREM: 514 case TargetOpcode::G_ASHR: 515 case TargetOpcode::G_LSHR: { 516 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV || 517 MI.getOpcode() == TargetOpcode::G_SREM || 518 MI.getOpcode() == TargetOpcode::G_ASHR 519 ? TargetOpcode::G_SEXT 520 : TargetOpcode::G_ZEXT; 521 522 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy); 523 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse( 524 MI.getOperand(1).getReg()); 525 526 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy); 527 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse( 528 MI.getOperand(2).getReg()); 529 530 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy); 531 MIRBuilder.buildInstr(MI.getOpcode()) 532 .addDef(ResExt) 533 .addUse(LHSExt) 534 .addUse(RHSExt); 535 536 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt); 537 MI.eraseFromParent(); 538 return Legalized; 539 } 540 case TargetOpcode::G_SELECT: { 541 if (TypeIdx != 0) 542 return UnableToLegalize; 543 544 // Perform operation at larger width (any extension is fine here, high bits 545 // don't affect the result) and then truncate the result back to the 546 // original type. 547 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 548 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 549 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg()); 550 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg()); 551 552 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 553 MIRBuilder.buildInstr(TargetOpcode::G_SELECT) 554 .addDef(DstExt) 555 .addReg(MI.getOperand(1).getReg()) 556 .addUse(Src1Ext) 557 .addUse(Src2Ext); 558 559 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 560 MI.eraseFromParent(); 561 return Legalized; 562 } 563 case TargetOpcode::G_FPTOSI: 564 case TargetOpcode::G_FPTOUI: { 565 if (TypeIdx != 0) 566 return UnableToLegalize; 567 568 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 569 MIRBuilder.buildInstr(MI.getOpcode()) 570 .addDef(DstExt) 571 .addUse(MI.getOperand(1).getReg()); 572 573 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 574 MI.eraseFromParent(); 575 return Legalized; 576 } 577 case TargetOpcode::G_SITOFP: 578 case TargetOpcode::G_UITOFP: { 579 if (TypeIdx != 1) 580 return UnableToLegalize; 581 582 unsigned Src = MI.getOperand(1).getReg(); 583 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 584 585 if (MI.getOpcode() == TargetOpcode::G_SITOFP) { 586 MIRBuilder.buildSExt(SrcExt, Src); 587 } else { 588 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op"); 589 MIRBuilder.buildZExt(SrcExt, Src); 590 } 591 592 MIRBuilder.buildInstr(MI.getOpcode()) 593 .addDef(MI.getOperand(0).getReg()) 594 .addUse(SrcExt); 595 596 MI.eraseFromParent(); 597 return Legalized; 598 } 599 case TargetOpcode::G_INSERT: { 600 if (TypeIdx != 0) 601 return UnableToLegalize; 602 603 unsigned Src = MI.getOperand(1).getReg(); 604 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 605 MIRBuilder.buildAnyExt(SrcExt, Src); 606 607 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 608 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(), 609 MI.getOperand(3).getImm()); 610 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) { 611 MIB.addReg(MI.getOperand(OpNum).getReg()); 612 MIB.addImm(MI.getOperand(OpNum + 1).getImm()); 613 } 614 615 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 616 MI.eraseFromParent(); 617 return Legalized; 618 } 619 case TargetOpcode::G_LOAD: { 620 assert(alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) == 621 WideTy.getSizeInBits() && 622 "illegal to increase number of bytes loaded"); 623 624 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 625 MIRBuilder.buildLoad(DstExt, MI.getOperand(1).getReg(), 626 **MI.memoperands_begin()); 627 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 628 MI.eraseFromParent(); 629 return Legalized; 630 } 631 case TargetOpcode::G_STORE: { 632 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) || 633 WideTy != LLT::scalar(8)) 634 return UnableToLegalize; 635 636 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 637 auto Content = TLI.getBooleanContents(false, false); 638 639 unsigned ExtOp = TargetOpcode::G_ANYEXT; 640 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent) 641 ExtOp = TargetOpcode::G_ZEXT; 642 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent) 643 ExtOp = TargetOpcode::G_SEXT; 644 else 645 ExtOp = TargetOpcode::G_ANYEXT; 646 647 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 648 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse( 649 MI.getOperand(0).getReg()); 650 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(), 651 **MI.memoperands_begin()); 652 MI.eraseFromParent(); 653 return Legalized; 654 } 655 case TargetOpcode::G_CONSTANT: { 656 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 657 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm()); 658 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 659 MI.eraseFromParent(); 660 return Legalized; 661 } 662 case TargetOpcode::G_FCONSTANT: { 663 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 664 MIRBuilder.buildFConstant(DstExt, *MI.getOperand(1).getFPImm()); 665 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt); 666 MI.eraseFromParent(); 667 return Legalized; 668 } 669 case TargetOpcode::G_BRCOND: { 670 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy); 671 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg()); 672 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB()); 673 MI.eraseFromParent(); 674 return Legalized; 675 } 676 case TargetOpcode::G_FCMP: { 677 unsigned Op0Ext, Op1Ext, DstReg; 678 unsigned Cmp1 = MI.getOperand(2).getReg(); 679 unsigned Cmp2 = MI.getOperand(3).getReg(); 680 if (TypeIdx == 0) { 681 Op0Ext = Cmp1; 682 Op1Ext = Cmp2; 683 DstReg = MRI.createGenericVirtualRegister(WideTy); 684 } else { 685 Op0Ext = MRI.createGenericVirtualRegister(WideTy); 686 Op1Ext = MRI.createGenericVirtualRegister(WideTy); 687 DstReg = MI.getOperand(0).getReg(); 688 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1); 689 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2); 690 } 691 MIRBuilder.buildFCmp( 692 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 693 DstReg, Op0Ext, Op1Ext); 694 if (TypeIdx == 0) 695 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(), 696 DstReg); 697 MI.eraseFromParent(); 698 return Legalized; 699 } 700 case TargetOpcode::G_ICMP: { 701 bool IsSigned = CmpInst::isSigned( 702 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate())); 703 unsigned Cmp1 = MI.getOperand(2).getReg(); 704 unsigned Cmp2 = MI.getOperand(3).getReg(); 705 unsigned Op0Ext, Op1Ext, DstReg; 706 if (TypeIdx == 0) { 707 Op0Ext = Cmp1; 708 Op1Ext = Cmp2; 709 DstReg = MRI.createGenericVirtualRegister(WideTy); 710 } else { 711 Op0Ext = MRI.createGenericVirtualRegister(WideTy); 712 Op1Ext = MRI.createGenericVirtualRegister(WideTy); 713 DstReg = MI.getOperand(0).getReg(); 714 if (IsSigned) { 715 MIRBuilder.buildSExt(Op0Ext, Cmp1); 716 MIRBuilder.buildSExt(Op1Ext, Cmp2); 717 } else { 718 MIRBuilder.buildZExt(Op0Ext, Cmp1); 719 MIRBuilder.buildZExt(Op1Ext, Cmp2); 720 } 721 } 722 MIRBuilder.buildICmp( 723 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 724 DstReg, Op0Ext, Op1Ext); 725 if (TypeIdx == 0) 726 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(), 727 DstReg); 728 MI.eraseFromParent(); 729 return Legalized; 730 } 731 case TargetOpcode::G_GEP: { 732 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 733 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy); 734 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg()); 735 MI.getOperand(2).setReg(OffsetExt); 736 return Legalized; 737 } 738 case TargetOpcode::G_PHI: { 739 assert(TypeIdx == 0 && "Expecting only Idx 0"); 740 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) { 741 auto FirstTermIt = MBB.getFirstTerminator(); 742 MIRBuilder.setInsertPt(MBB, FirstTermIt); 743 MachineInstr *DefMI = MRI.getVRegDef(Reg); 744 MachineInstrBuilder MIB; 745 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) 746 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy, 747 DefMI->getOperand(1).getReg()); 748 else 749 MIB = MIRBuilder.buildAnyExt(WideTy, Reg); 750 return MIB->getOperand(0).getReg(); 751 }; 752 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy); 753 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end(); 754 OpIt != OpE;) { 755 unsigned Reg = OpIt++->getReg(); 756 MachineBasicBlock *OpMBB = OpIt++->getMBB(); 757 MIB.addReg(getExtendedReg(Reg, *OpMBB)); 758 MIB.addMBB(OpMBB); 759 } 760 auto *MBB = MI.getParent(); 761 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI()); 762 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), 763 MIB->getOperand(0).getReg()); 764 MI.eraseFromParent(); 765 return Legalized; 766 } 767 } 768 } 769 770 LegalizerHelper::LegalizeResult 771 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 772 using namespace TargetOpcode; 773 MIRBuilder.setInstr(MI); 774 775 switch(MI.getOpcode()) { 776 default: 777 return UnableToLegalize; 778 case TargetOpcode::G_SREM: 779 case TargetOpcode::G_UREM: { 780 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty); 781 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 782 .addDef(QuotReg) 783 .addUse(MI.getOperand(1).getReg()) 784 .addUse(MI.getOperand(2).getReg()); 785 786 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty); 787 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 788 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 789 ProdReg); 790 MI.eraseFromParent(); 791 return Legalized; 792 } 793 case TargetOpcode::G_SMULO: 794 case TargetOpcode::G_UMULO: { 795 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 796 // result. 797 unsigned Res = MI.getOperand(0).getReg(); 798 unsigned Overflow = MI.getOperand(1).getReg(); 799 unsigned LHS = MI.getOperand(2).getReg(); 800 unsigned RHS = MI.getOperand(3).getReg(); 801 802 MIRBuilder.buildMul(Res, LHS, RHS); 803 804 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 805 ? TargetOpcode::G_SMULH 806 : TargetOpcode::G_UMULH; 807 808 unsigned HiPart = MRI.createGenericVirtualRegister(Ty); 809 MIRBuilder.buildInstr(Opcode) 810 .addDef(HiPart) 811 .addUse(LHS) 812 .addUse(RHS); 813 814 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 815 MIRBuilder.buildConstant(Zero, 0); 816 817 // For *signed* multiply, overflow is detected by checking: 818 // (hi != (lo >> bitwidth-1)) 819 if (Opcode == TargetOpcode::G_SMULH) { 820 unsigned Shifted = MRI.createGenericVirtualRegister(Ty); 821 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty); 822 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1); 823 MIRBuilder.buildInstr(TargetOpcode::G_ASHR) 824 .addDef(Shifted) 825 .addUse(Res) 826 .addUse(ShiftAmt); 827 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted); 828 } else { 829 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 830 } 831 MI.eraseFromParent(); 832 return Legalized; 833 } 834 case TargetOpcode::G_FNEG: { 835 // TODO: Handle vector types once we are able to 836 // represent them. 837 if (Ty.isVector()) 838 return UnableToLegalize; 839 unsigned Res = MI.getOperand(0).getReg(); 840 Type *ZeroTy; 841 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 842 switch (Ty.getSizeInBits()) { 843 case 16: 844 ZeroTy = Type::getHalfTy(Ctx); 845 break; 846 case 32: 847 ZeroTy = Type::getFloatTy(Ctx); 848 break; 849 case 64: 850 ZeroTy = Type::getDoubleTy(Ctx); 851 break; 852 case 128: 853 ZeroTy = Type::getFP128Ty(Ctx); 854 break; 855 default: 856 llvm_unreachable("unexpected floating-point type"); 857 } 858 ConstantFP &ZeroForNegation = 859 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); 860 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 861 MIRBuilder.buildFConstant(Zero, ZeroForNegation); 862 MIRBuilder.buildInstr(TargetOpcode::G_FSUB) 863 .addDef(Res) 864 .addUse(Zero) 865 .addUse(MI.getOperand(1).getReg()); 866 MI.eraseFromParent(); 867 return Legalized; 868 } 869 case TargetOpcode::G_FSUB: { 870 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 871 // First, check if G_FNEG is marked as Lower. If so, we may 872 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 873 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower) 874 return UnableToLegalize; 875 unsigned Res = MI.getOperand(0).getReg(); 876 unsigned LHS = MI.getOperand(1).getReg(); 877 unsigned RHS = MI.getOperand(2).getReg(); 878 unsigned Neg = MRI.createGenericVirtualRegister(Ty); 879 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); 880 MIRBuilder.buildInstr(TargetOpcode::G_FADD) 881 .addDef(Res) 882 .addUse(LHS) 883 .addUse(Neg); 884 MI.eraseFromParent(); 885 return Legalized; 886 } 887 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { 888 unsigned OldValRes = MI.getOperand(0).getReg(); 889 unsigned SuccessRes = MI.getOperand(1).getReg(); 890 unsigned Addr = MI.getOperand(2).getReg(); 891 unsigned CmpVal = MI.getOperand(3).getReg(); 892 unsigned NewVal = MI.getOperand(4).getReg(); 893 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, 894 **MI.memoperands_begin()); 895 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); 896 MI.eraseFromParent(); 897 return Legalized; 898 } 899 } 900 } 901 902 LegalizerHelper::LegalizeResult 903 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 904 LLT NarrowTy) { 905 // FIXME: Don't know how to handle secondary types yet. 906 if (TypeIdx != 0) 907 return UnableToLegalize; 908 switch (MI.getOpcode()) { 909 default: 910 return UnableToLegalize; 911 case TargetOpcode::G_ADD: { 912 unsigned NarrowSize = NarrowTy.getSizeInBits(); 913 unsigned DstReg = MI.getOperand(0).getReg(); 914 unsigned Size = MRI.getType(DstReg).getSizeInBits(); 915 int NumParts = Size / NarrowSize; 916 // FIXME: Don't know how to handle the situation where the small vectors 917 // aren't all the same size yet. 918 if (Size % NarrowSize != 0) 919 return UnableToLegalize; 920 921 MIRBuilder.setInstr(MI); 922 923 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 924 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 925 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 926 927 for (int i = 0; i < NumParts; ++i) { 928 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 929 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]); 930 DstRegs.push_back(DstReg); 931 } 932 933 MIRBuilder.buildMerge(DstReg, DstRegs); 934 MI.eraseFromParent(); 935 return Legalized; 936 } 937 } 938 } 939