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