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