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 const ConstantFP *CFP = MI.getOperand(1).getFPImm(); 665 APFloat Val = CFP->getValueAPF(); 666 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 667 auto LLT2Sem = [](LLT Ty) { 668 switch (Ty.getSizeInBits()) { 669 case 32: 670 return &APFloat::IEEEsingle(); 671 break; 672 case 64: 673 return &APFloat::IEEEdouble(); 674 break; 675 default: 676 llvm_unreachable("Unhandled fp widen type"); 677 } 678 }; 679 bool LosesInfo; 680 Val.convert(*LLT2Sem(WideTy), APFloat::rmTowardZero, &LosesInfo); 681 MIRBuilder.buildFConstant(DstExt, *ConstantFP::get(Ctx, Val)); 682 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), DstExt); 683 MI.eraseFromParent(); 684 return Legalized; 685 } 686 case TargetOpcode::G_BRCOND: { 687 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy); 688 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg()); 689 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB()); 690 MI.eraseFromParent(); 691 return Legalized; 692 } 693 case TargetOpcode::G_FCMP: { 694 unsigned Op0Ext, Op1Ext, DstReg; 695 unsigned Cmp1 = MI.getOperand(2).getReg(); 696 unsigned Cmp2 = MI.getOperand(3).getReg(); 697 if (TypeIdx == 0) { 698 Op0Ext = Cmp1; 699 Op1Ext = Cmp2; 700 DstReg = MRI.createGenericVirtualRegister(WideTy); 701 } else { 702 Op0Ext = MRI.createGenericVirtualRegister(WideTy); 703 Op1Ext = MRI.createGenericVirtualRegister(WideTy); 704 DstReg = MI.getOperand(0).getReg(); 705 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1); 706 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2); 707 } 708 MIRBuilder.buildFCmp( 709 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 710 DstReg, Op0Ext, Op1Ext); 711 if (TypeIdx == 0) 712 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(), 713 DstReg); 714 MI.eraseFromParent(); 715 return Legalized; 716 } 717 case TargetOpcode::G_ICMP: { 718 bool IsSigned = CmpInst::isSigned( 719 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate())); 720 unsigned Cmp1 = MI.getOperand(2).getReg(); 721 unsigned Cmp2 = MI.getOperand(3).getReg(); 722 unsigned Op0Ext, Op1Ext, DstReg; 723 if (TypeIdx == 0) { 724 Op0Ext = Cmp1; 725 Op1Ext = Cmp2; 726 DstReg = MRI.createGenericVirtualRegister(WideTy); 727 } else { 728 Op0Ext = MRI.createGenericVirtualRegister(WideTy); 729 Op1Ext = MRI.createGenericVirtualRegister(WideTy); 730 DstReg = MI.getOperand(0).getReg(); 731 if (IsSigned) { 732 MIRBuilder.buildSExt(Op0Ext, Cmp1); 733 MIRBuilder.buildSExt(Op1Ext, Cmp2); 734 } else { 735 MIRBuilder.buildZExt(Op0Ext, Cmp1); 736 MIRBuilder.buildZExt(Op1Ext, Cmp2); 737 } 738 } 739 MIRBuilder.buildICmp( 740 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 741 DstReg, Op0Ext, Op1Ext); 742 if (TypeIdx == 0) 743 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(), 744 DstReg); 745 MI.eraseFromParent(); 746 return Legalized; 747 } 748 case TargetOpcode::G_GEP: { 749 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 750 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy); 751 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg()); 752 MI.getOperand(2).setReg(OffsetExt); 753 return Legalized; 754 } 755 case TargetOpcode::G_PHI: { 756 assert(TypeIdx == 0 && "Expecting only Idx 0"); 757 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) { 758 auto FirstTermIt = MBB.getFirstTerminator(); 759 MIRBuilder.setInsertPt(MBB, FirstTermIt); 760 MachineInstr *DefMI = MRI.getVRegDef(Reg); 761 MachineInstrBuilder MIB; 762 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) 763 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy, 764 DefMI->getOperand(1).getReg()); 765 else 766 MIB = MIRBuilder.buildAnyExt(WideTy, Reg); 767 return MIB->getOperand(0).getReg(); 768 }; 769 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy); 770 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end(); 771 OpIt != OpE;) { 772 unsigned Reg = OpIt++->getReg(); 773 MachineBasicBlock *OpMBB = OpIt++->getMBB(); 774 MIB.addReg(getExtendedReg(Reg, *OpMBB)); 775 MIB.addMBB(OpMBB); 776 } 777 auto *MBB = MI.getParent(); 778 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI()); 779 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), 780 MIB->getOperand(0).getReg()); 781 MI.eraseFromParent(); 782 return Legalized; 783 } 784 } 785 } 786 787 LegalizerHelper::LegalizeResult 788 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 789 using namespace TargetOpcode; 790 MIRBuilder.setInstr(MI); 791 792 switch(MI.getOpcode()) { 793 default: 794 return UnableToLegalize; 795 case TargetOpcode::G_SREM: 796 case TargetOpcode::G_UREM: { 797 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty); 798 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 799 .addDef(QuotReg) 800 .addUse(MI.getOperand(1).getReg()) 801 .addUse(MI.getOperand(2).getReg()); 802 803 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty); 804 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 805 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 806 ProdReg); 807 MI.eraseFromParent(); 808 return Legalized; 809 } 810 case TargetOpcode::G_SMULO: 811 case TargetOpcode::G_UMULO: { 812 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 813 // result. 814 unsigned Res = MI.getOperand(0).getReg(); 815 unsigned Overflow = MI.getOperand(1).getReg(); 816 unsigned LHS = MI.getOperand(2).getReg(); 817 unsigned RHS = MI.getOperand(3).getReg(); 818 819 MIRBuilder.buildMul(Res, LHS, RHS); 820 821 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 822 ? TargetOpcode::G_SMULH 823 : TargetOpcode::G_UMULH; 824 825 unsigned HiPart = MRI.createGenericVirtualRegister(Ty); 826 MIRBuilder.buildInstr(Opcode) 827 .addDef(HiPart) 828 .addUse(LHS) 829 .addUse(RHS); 830 831 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 832 MIRBuilder.buildConstant(Zero, 0); 833 834 // For *signed* multiply, overflow is detected by checking: 835 // (hi != (lo >> bitwidth-1)) 836 if (Opcode == TargetOpcode::G_SMULH) { 837 unsigned Shifted = MRI.createGenericVirtualRegister(Ty); 838 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty); 839 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1); 840 MIRBuilder.buildInstr(TargetOpcode::G_ASHR) 841 .addDef(Shifted) 842 .addUse(Res) 843 .addUse(ShiftAmt); 844 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted); 845 } else { 846 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 847 } 848 MI.eraseFromParent(); 849 return Legalized; 850 } 851 case TargetOpcode::G_FNEG: { 852 // TODO: Handle vector types once we are able to 853 // represent them. 854 if (Ty.isVector()) 855 return UnableToLegalize; 856 unsigned Res = MI.getOperand(0).getReg(); 857 Type *ZeroTy; 858 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 859 switch (Ty.getSizeInBits()) { 860 case 16: 861 ZeroTy = Type::getHalfTy(Ctx); 862 break; 863 case 32: 864 ZeroTy = Type::getFloatTy(Ctx); 865 break; 866 case 64: 867 ZeroTy = Type::getDoubleTy(Ctx); 868 break; 869 case 128: 870 ZeroTy = Type::getFP128Ty(Ctx); 871 break; 872 default: 873 llvm_unreachable("unexpected floating-point type"); 874 } 875 ConstantFP &ZeroForNegation = 876 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); 877 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 878 MIRBuilder.buildFConstant(Zero, ZeroForNegation); 879 MIRBuilder.buildInstr(TargetOpcode::G_FSUB) 880 .addDef(Res) 881 .addUse(Zero) 882 .addUse(MI.getOperand(1).getReg()); 883 MI.eraseFromParent(); 884 return Legalized; 885 } 886 case TargetOpcode::G_FSUB: { 887 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 888 // First, check if G_FNEG is marked as Lower. If so, we may 889 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 890 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower) 891 return UnableToLegalize; 892 unsigned Res = MI.getOperand(0).getReg(); 893 unsigned LHS = MI.getOperand(1).getReg(); 894 unsigned RHS = MI.getOperand(2).getReg(); 895 unsigned Neg = MRI.createGenericVirtualRegister(Ty); 896 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); 897 MIRBuilder.buildInstr(TargetOpcode::G_FADD) 898 .addDef(Res) 899 .addUse(LHS) 900 .addUse(Neg); 901 MI.eraseFromParent(); 902 return Legalized; 903 } 904 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { 905 unsigned OldValRes = MI.getOperand(0).getReg(); 906 unsigned SuccessRes = MI.getOperand(1).getReg(); 907 unsigned Addr = MI.getOperand(2).getReg(); 908 unsigned CmpVal = MI.getOperand(3).getReg(); 909 unsigned NewVal = MI.getOperand(4).getReg(); 910 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, 911 **MI.memoperands_begin()); 912 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); 913 MI.eraseFromParent(); 914 return Legalized; 915 } 916 } 917 } 918 919 LegalizerHelper::LegalizeResult 920 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 921 LLT NarrowTy) { 922 // FIXME: Don't know how to handle secondary types yet. 923 if (TypeIdx != 0) 924 return UnableToLegalize; 925 switch (MI.getOpcode()) { 926 default: 927 return UnableToLegalize; 928 case TargetOpcode::G_ADD: { 929 unsigned NarrowSize = NarrowTy.getSizeInBits(); 930 unsigned DstReg = MI.getOperand(0).getReg(); 931 unsigned Size = MRI.getType(DstReg).getSizeInBits(); 932 int NumParts = Size / NarrowSize; 933 // FIXME: Don't know how to handle the situation where the small vectors 934 // aren't all the same size yet. 935 if (Size % NarrowSize != 0) 936 return UnableToLegalize; 937 938 MIRBuilder.setInstr(MI); 939 940 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 941 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 942 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 943 944 for (int i = 0; i < NumParts; ++i) { 945 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 946 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]); 947 DstRegs.push_back(DstReg); 948 } 949 950 MIRBuilder.buildMerge(DstReg, DstRegs); 951 MI.eraseFromParent(); 952 return Legalized; 953 } 954 } 955 } 956