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