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 using namespace LegalizeActions; 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 Step = LI.getAction(MI, MRI); 41 switch (Step.Action) { 42 case Legal: 43 DEBUG(dbgs() << ".. Already legal\n"); 44 return AlreadyLegal; 45 case Libcall: 46 DEBUG(dbgs() << ".. Convert to libcall\n"); 47 return libcall(MI); 48 case NarrowScalar: 49 DEBUG(dbgs() << ".. Narrow scalar\n"); 50 return narrowScalar(MI, Step.TypeIdx, Step.NewType); 51 case WidenScalar: 52 DEBUG(dbgs() << ".. Widen scalar\n"); 53 return widenScalar(MI, Step.TypeIdx, Step.NewType); 54 case Lower: 55 DEBUG(dbgs() << ".. Lower\n"); 56 return lower(MI, Step.TypeIdx, Step.NewType); 57 case FewerElements: 58 DEBUG(dbgs() << ".. Reduce number of elements\n"); 59 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType); 60 case 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_FMUL: 98 assert((Size == 32 || Size == 64) && "Unsupported size"); 99 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32; 100 case TargetOpcode::G_FDIV: 101 assert((Size == 32 || Size == 64) && "Unsupported size"); 102 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32; 103 case TargetOpcode::G_FREM: 104 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; 105 case TargetOpcode::G_FPOW: 106 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; 107 case TargetOpcode::G_FMA: 108 assert((Size == 32 || Size == 64) && "Unsupported size"); 109 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32; 110 } 111 llvm_unreachable("Unknown libcall function"); 112 } 113 114 LegalizerHelper::LegalizeResult 115 llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, 116 const CallLowering::ArgInfo &Result, 117 ArrayRef<CallLowering::ArgInfo> Args) { 118 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 119 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 120 const char *Name = TLI.getLibcallName(Libcall); 121 122 MIRBuilder.getMF().getFrameInfo().setHasCalls(true); 123 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall), 124 MachineOperand::CreateES(Name), Result, Args)) 125 return LegalizerHelper::UnableToLegalize; 126 127 return LegalizerHelper::Legalized; 128 } 129 130 // Useful for libcalls where all operands have the same type. 131 static LegalizerHelper::LegalizeResult 132 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, 133 Type *OpType) { 134 auto Libcall = getRTLibDesc(MI.getOpcode(), Size); 135 136 SmallVector<CallLowering::ArgInfo, 3> Args; 137 for (unsigned i = 1; i < MI.getNumOperands(); i++) 138 Args.push_back({MI.getOperand(i).getReg(), OpType}); 139 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType}, 140 Args); 141 } 142 143 static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, 144 Type *FromType) { 145 auto ToMVT = MVT::getVT(ToType); 146 auto FromMVT = MVT::getVT(FromType); 147 148 switch (Opcode) { 149 case TargetOpcode::G_FPEXT: 150 return RTLIB::getFPEXT(FromMVT, ToMVT); 151 case TargetOpcode::G_FPTRUNC: 152 return RTLIB::getFPROUND(FromMVT, ToMVT); 153 case TargetOpcode::G_FPTOSI: 154 return RTLIB::getFPTOSINT(FromMVT, ToMVT); 155 case TargetOpcode::G_FPTOUI: 156 return RTLIB::getFPTOUINT(FromMVT, ToMVT); 157 case TargetOpcode::G_SITOFP: 158 return RTLIB::getSINTTOFP(FromMVT, ToMVT); 159 case TargetOpcode::G_UITOFP: 160 return RTLIB::getUINTTOFP(FromMVT, ToMVT); 161 } 162 llvm_unreachable("Unsupported libcall function"); 163 } 164 165 static LegalizerHelper::LegalizeResult 166 conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, 167 Type *FromType) { 168 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType); 169 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType}, 170 {{MI.getOperand(1).getReg(), FromType}}); 171 } 172 173 LegalizerHelper::LegalizeResult 174 LegalizerHelper::libcall(MachineInstr &MI) { 175 LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); 176 unsigned Size = LLTy.getSizeInBits(); 177 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 178 179 MIRBuilder.setInstr(MI); 180 181 switch (MI.getOpcode()) { 182 default: 183 return UnableToLegalize; 184 case TargetOpcode::G_SDIV: 185 case TargetOpcode::G_UDIV: 186 case TargetOpcode::G_SREM: 187 case TargetOpcode::G_UREM: { 188 Type *HLTy = Type::getInt32Ty(Ctx); 189 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 190 if (Status != Legalized) 191 return Status; 192 break; 193 } 194 case TargetOpcode::G_FADD: 195 case TargetOpcode::G_FSUB: 196 case TargetOpcode::G_FMUL: 197 case TargetOpcode::G_FDIV: 198 case TargetOpcode::G_FMA: 199 case TargetOpcode::G_FPOW: 200 case TargetOpcode::G_FREM: { 201 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); 202 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 203 if (Status != Legalized) 204 return Status; 205 break; 206 } 207 case TargetOpcode::G_FPEXT: { 208 // FIXME: Support other floating point types (half, fp128 etc) 209 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 210 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 211 if (ToSize != 64 || FromSize != 32) 212 return UnableToLegalize; 213 LegalizeResult Status = conversionLibcall( 214 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx)); 215 if (Status != Legalized) 216 return Status; 217 break; 218 } 219 case TargetOpcode::G_FPTRUNC: { 220 // FIXME: Support other floating point types (half, fp128 etc) 221 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 222 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 223 if (ToSize != 32 || FromSize != 64) 224 return UnableToLegalize; 225 LegalizeResult Status = conversionLibcall( 226 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx)); 227 if (Status != Legalized) 228 return Status; 229 break; 230 } 231 case TargetOpcode::G_FPTOSI: 232 case TargetOpcode::G_FPTOUI: { 233 // FIXME: Support other types 234 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 235 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 236 if (ToSize != 32 || (FromSize != 32 && FromSize != 64)) 237 return UnableToLegalize; 238 LegalizeResult Status = conversionLibcall( 239 MI, MIRBuilder, Type::getInt32Ty(Ctx), 240 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx)); 241 if (Status != Legalized) 242 return Status; 243 break; 244 } 245 case TargetOpcode::G_SITOFP: 246 case TargetOpcode::G_UITOFP: { 247 // FIXME: Support other types 248 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 249 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 250 if (FromSize != 32 || (ToSize != 32 && ToSize != 64)) 251 return UnableToLegalize; 252 LegalizeResult Status = conversionLibcall( 253 MI, MIRBuilder, 254 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx), 255 Type::getInt32Ty(Ctx)); 256 if (Status != Legalized) 257 return Status; 258 break; 259 } 260 } 261 262 MI.eraseFromParent(); 263 return Legalized; 264 } 265 266 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 267 unsigned TypeIdx, 268 LLT NarrowTy) { 269 // FIXME: Don't know how to handle secondary types yet. 270 if (TypeIdx != 0 && MI.getOpcode() != TargetOpcode::G_EXTRACT) 271 return UnableToLegalize; 272 273 MIRBuilder.setInstr(MI); 274 275 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 276 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 277 278 switch (MI.getOpcode()) { 279 default: 280 return UnableToLegalize; 281 case TargetOpcode::G_IMPLICIT_DEF: { 282 // FIXME: add support for when SizeOp0 isn't an exact multiple of 283 // NarrowSize. 284 if (SizeOp0 % NarrowSize != 0) 285 return UnableToLegalize; 286 int NumParts = SizeOp0 / NarrowSize; 287 288 SmallVector<unsigned, 2> DstRegs; 289 for (int i = 0; i < NumParts; ++i) 290 DstRegs.push_back( 291 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg()); 292 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 293 MI.eraseFromParent(); 294 return Legalized; 295 } 296 case TargetOpcode::G_ADD: { 297 // FIXME: add support for when SizeOp0 isn't an exact multiple of 298 // NarrowSize. 299 if (SizeOp0 % NarrowSize != 0) 300 return UnableToLegalize; 301 // Expand in terms of carry-setting/consuming G_ADDE instructions. 302 int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); 303 304 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 305 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 306 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 307 308 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1)); 309 MIRBuilder.buildConstant(CarryIn, 0); 310 311 for (int i = 0; i < NumParts; ++i) { 312 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 313 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 314 315 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], 316 Src2Regs[i], CarryIn); 317 318 DstRegs.push_back(DstReg); 319 CarryIn = CarryOut; 320 } 321 unsigned DstReg = MI.getOperand(0).getReg(); 322 MIRBuilder.buildMerge(DstReg, DstRegs); 323 MI.eraseFromParent(); 324 return Legalized; 325 } 326 case TargetOpcode::G_EXTRACT: { 327 if (TypeIdx != 1) 328 return UnableToLegalize; 329 330 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 331 // FIXME: add support for when SizeOp1 isn't an exact multiple of 332 // NarrowSize. 333 if (SizeOp1 % NarrowSize != 0) 334 return UnableToLegalize; 335 int NumParts = SizeOp1 / NarrowSize; 336 337 SmallVector<unsigned, 2> SrcRegs, DstRegs; 338 SmallVector<uint64_t, 2> Indexes; 339 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 340 341 unsigned OpReg = MI.getOperand(0).getReg(); 342 uint64_t OpStart = MI.getOperand(2).getImm(); 343 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 344 for (int i = 0; i < NumParts; ++i) { 345 unsigned SrcStart = i * NarrowSize; 346 347 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) { 348 // No part of the extract uses this subregister, ignore it. 349 continue; 350 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 351 // The entire subregister is extracted, forward the value. 352 DstRegs.push_back(SrcRegs[i]); 353 continue; 354 } 355 356 // OpSegStart is where this destination segment would start in OpReg if it 357 // extended infinitely in both directions. 358 int64_t ExtractOffset; 359 uint64_t SegSize; 360 if (OpStart < SrcStart) { 361 ExtractOffset = 0; 362 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart); 363 } else { 364 ExtractOffset = OpStart - SrcStart; 365 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize); 366 } 367 368 unsigned SegReg = SrcRegs[i]; 369 if (ExtractOffset != 0 || SegSize != NarrowSize) { 370 // A genuine extract is needed. 371 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 372 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset); 373 } 374 375 DstRegs.push_back(SegReg); 376 } 377 378 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 379 MI.eraseFromParent(); 380 return Legalized; 381 } 382 case TargetOpcode::G_INSERT: { 383 // FIXME: add support for when SizeOp0 isn't an exact multiple of 384 // NarrowSize. 385 if (SizeOp0 % NarrowSize != 0) 386 return UnableToLegalize; 387 388 int NumParts = SizeOp0 / NarrowSize; 389 390 SmallVector<unsigned, 2> SrcRegs, DstRegs; 391 SmallVector<uint64_t, 2> Indexes; 392 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 393 394 unsigned OpReg = MI.getOperand(2).getReg(); 395 uint64_t OpStart = MI.getOperand(3).getImm(); 396 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 397 for (int i = 0; i < NumParts; ++i) { 398 unsigned DstStart = i * NarrowSize; 399 400 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { 401 // No part of the insert affects this subregister, forward the original. 402 DstRegs.push_back(SrcRegs[i]); 403 continue; 404 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 405 // The entire subregister is defined by this insert, forward the new 406 // value. 407 DstRegs.push_back(OpReg); 408 continue; 409 } 410 411 // OpSegStart is where this destination segment would start in OpReg if it 412 // extended infinitely in both directions. 413 int64_t ExtractOffset, InsertOffset; 414 uint64_t SegSize; 415 if (OpStart < DstStart) { 416 InsertOffset = 0; 417 ExtractOffset = DstStart - OpStart; 418 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); 419 } else { 420 InsertOffset = OpStart - DstStart; 421 ExtractOffset = 0; 422 SegSize = 423 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); 424 } 425 426 unsigned SegReg = OpReg; 427 if (ExtractOffset != 0 || SegSize != OpSize) { 428 // A genuine extract is needed. 429 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 430 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); 431 } 432 433 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 434 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); 435 DstRegs.push_back(DstReg); 436 } 437 438 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); 439 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 440 MI.eraseFromParent(); 441 return Legalized; 442 } 443 case TargetOpcode::G_LOAD: { 444 // FIXME: add support for when SizeOp0 isn't an exact multiple of 445 // NarrowSize. 446 if (SizeOp0 % NarrowSize != 0) 447 return UnableToLegalize; 448 449 const auto &MMO = **MI.memoperands_begin(); 450 // This implementation doesn't work for atomics. Give up instead of doing 451 // something invalid. 452 if (MMO.getOrdering() != AtomicOrdering::NotAtomic || 453 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic) 454 return UnableToLegalize; 455 456 int NumParts = SizeOp0 / NarrowSize; 457 LLT OffsetTy = LLT::scalar( 458 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); 459 460 SmallVector<unsigned, 2> DstRegs; 461 for (int i = 0; i < NumParts; ++i) { 462 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 463 unsigned SrcReg = 0; 464 unsigned Adjustment = i * NarrowSize / 8; 465 466 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand( 467 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(), 468 NarrowSize / 8, i == 0 ? MMO.getAlignment() : NarrowSize / 8, 469 MMO.getAAInfo(), MMO.getRanges(), MMO.getSyncScopeID(), 470 MMO.getOrdering(), MMO.getFailureOrdering()); 471 472 MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy, 473 Adjustment); 474 475 MIRBuilder.buildLoad(DstReg, SrcReg, *SplitMMO); 476 477 DstRegs.push_back(DstReg); 478 } 479 unsigned DstReg = MI.getOperand(0).getReg(); 480 MIRBuilder.buildMerge(DstReg, DstRegs); 481 MI.eraseFromParent(); 482 return Legalized; 483 } 484 case TargetOpcode::G_STORE: { 485 // FIXME: add support for when SizeOp0 isn't an exact multiple of 486 // NarrowSize. 487 if (SizeOp0 % NarrowSize != 0) 488 return UnableToLegalize; 489 490 const auto &MMO = **MI.memoperands_begin(); 491 // This implementation doesn't work for atomics. Give up instead of doing 492 // something invalid. 493 if (MMO.getOrdering() != AtomicOrdering::NotAtomic || 494 MMO.getFailureOrdering() != AtomicOrdering::NotAtomic) 495 return UnableToLegalize; 496 497 int NumParts = SizeOp0 / NarrowSize; 498 LLT OffsetTy = LLT::scalar( 499 MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); 500 501 SmallVector<unsigned, 2> SrcRegs; 502 extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs); 503 504 for (int i = 0; i < NumParts; ++i) { 505 unsigned DstReg = 0; 506 unsigned Adjustment = i * NarrowSize / 8; 507 508 MachineMemOperand *SplitMMO = MIRBuilder.getMF().getMachineMemOperand( 509 MMO.getPointerInfo().getWithOffset(Adjustment), MMO.getFlags(), 510 NarrowSize / 8, i == 0 ? MMO.getAlignment() : NarrowSize / 8, 511 MMO.getAAInfo(), MMO.getRanges(), MMO.getSyncScopeID(), 512 MMO.getOrdering(), MMO.getFailureOrdering()); 513 514 MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy, 515 Adjustment); 516 517 MIRBuilder.buildStore(SrcRegs[i], DstReg, *SplitMMO); 518 } 519 MI.eraseFromParent(); 520 return Legalized; 521 } 522 case TargetOpcode::G_CONSTANT: { 523 // FIXME: add support for when SizeOp0 isn't an exact multiple of 524 // NarrowSize. 525 if (SizeOp0 % NarrowSize != 0) 526 return UnableToLegalize; 527 int NumParts = SizeOp0 / NarrowSize; 528 const APInt &Cst = MI.getOperand(1).getCImm()->getValue(); 529 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 530 531 SmallVector<unsigned, 2> DstRegs; 532 for (int i = 0; i < NumParts; ++i) { 533 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 534 ConstantInt *CI = 535 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize)); 536 MIRBuilder.buildConstant(DstReg, *CI); 537 DstRegs.push_back(DstReg); 538 } 539 unsigned DstReg = MI.getOperand(0).getReg(); 540 MIRBuilder.buildMerge(DstReg, DstRegs); 541 MI.eraseFromParent(); 542 return Legalized; 543 } 544 case TargetOpcode::G_OR: { 545 // Legalize bitwise operation: 546 // A = BinOp<Ty> B, C 547 // into: 548 // B1, ..., BN = G_UNMERGE_VALUES B 549 // C1, ..., CN = G_UNMERGE_VALUES C 550 // A1 = BinOp<Ty/N> B1, C2 551 // ... 552 // AN = BinOp<Ty/N> BN, CN 553 // A = G_MERGE_VALUES A1, ..., AN 554 555 // FIXME: add support for when SizeOp0 isn't an exact multiple of 556 // NarrowSize. 557 if (SizeOp0 % NarrowSize != 0) 558 return UnableToLegalize; 559 int NumParts = SizeOp0 / NarrowSize; 560 561 // List the registers where the destination will be scattered. 562 SmallVector<unsigned, 2> DstRegs; 563 // List the registers where the first argument will be split. 564 SmallVector<unsigned, 2> SrcsReg1; 565 // List the registers where the second argument will be split. 566 SmallVector<unsigned, 2> SrcsReg2; 567 // Create all the temporary registers. 568 for (int i = 0; i < NumParts; ++i) { 569 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 570 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy); 571 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy); 572 573 DstRegs.push_back(DstReg); 574 SrcsReg1.push_back(SrcReg1); 575 SrcsReg2.push_back(SrcReg2); 576 } 577 // Explode the big arguments into smaller chunks. 578 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg()); 579 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg()); 580 581 // Do the operation on each small part. 582 for (int i = 0; i < NumParts; ++i) 583 MIRBuilder.buildOr(DstRegs[i], SrcsReg1[i], SrcsReg2[i]); 584 585 // Gather the destination registers into the final destination. 586 unsigned DstReg = MI.getOperand(0).getReg(); 587 MIRBuilder.buildMerge(DstReg, DstRegs); 588 MI.eraseFromParent(); 589 return Legalized; 590 } 591 } 592 } 593 594 LegalizerHelper::LegalizeResult 595 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 596 MIRBuilder.setInstr(MI); 597 598 switch (MI.getOpcode()) { 599 default: 600 return UnableToLegalize; 601 case TargetOpcode::G_ADD: 602 case TargetOpcode::G_AND: 603 case TargetOpcode::G_MUL: 604 case TargetOpcode::G_OR: 605 case TargetOpcode::G_XOR: 606 case TargetOpcode::G_SUB: 607 case TargetOpcode::G_SHL: { 608 // Perform operation at larger width (any extension is fine here, high bits 609 // don't affect the result) and then truncate the result back to the 610 // original type. 611 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 612 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 613 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(1).getReg()); 614 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(2).getReg()); 615 616 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 617 MIRBuilder.buildInstr(MI.getOpcode()) 618 .addDef(DstExt) 619 .addUse(Src1Ext) 620 .addUse(Src2Ext); 621 622 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 623 MI.eraseFromParent(); 624 return Legalized; 625 } 626 case TargetOpcode::G_SDIV: 627 case TargetOpcode::G_UDIV: 628 case TargetOpcode::G_SREM: 629 case TargetOpcode::G_UREM: 630 case TargetOpcode::G_ASHR: 631 case TargetOpcode::G_LSHR: { 632 unsigned ExtOp = MI.getOpcode() == TargetOpcode::G_SDIV || 633 MI.getOpcode() == TargetOpcode::G_SREM || 634 MI.getOpcode() == TargetOpcode::G_ASHR 635 ? TargetOpcode::G_SEXT 636 : TargetOpcode::G_ZEXT; 637 638 unsigned LHSExt = MRI.createGenericVirtualRegister(WideTy); 639 MIRBuilder.buildInstr(ExtOp).addDef(LHSExt).addUse( 640 MI.getOperand(1).getReg()); 641 642 unsigned RHSExt = MRI.createGenericVirtualRegister(WideTy); 643 MIRBuilder.buildInstr(ExtOp).addDef(RHSExt).addUse( 644 MI.getOperand(2).getReg()); 645 646 unsigned ResExt = MRI.createGenericVirtualRegister(WideTy); 647 MIRBuilder.buildInstr(MI.getOpcode()) 648 .addDef(ResExt) 649 .addUse(LHSExt) 650 .addUse(RHSExt); 651 652 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), ResExt); 653 MI.eraseFromParent(); 654 return Legalized; 655 } 656 case TargetOpcode::G_SELECT: { 657 if (TypeIdx != 0) 658 return UnableToLegalize; 659 660 // Perform operation at larger width (any extension is fine here, high bits 661 // don't affect the result) and then truncate the result back to the 662 // original type. 663 unsigned Src1Ext = MRI.createGenericVirtualRegister(WideTy); 664 unsigned Src2Ext = MRI.createGenericVirtualRegister(WideTy); 665 MIRBuilder.buildAnyExt(Src1Ext, MI.getOperand(2).getReg()); 666 MIRBuilder.buildAnyExt(Src2Ext, MI.getOperand(3).getReg()); 667 668 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 669 MIRBuilder.buildInstr(TargetOpcode::G_SELECT) 670 .addDef(DstExt) 671 .addReg(MI.getOperand(1).getReg()) 672 .addUse(Src1Ext) 673 .addUse(Src2Ext); 674 675 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 676 MI.eraseFromParent(); 677 return Legalized; 678 } 679 case TargetOpcode::G_FPTOSI: 680 case TargetOpcode::G_FPTOUI: { 681 if (TypeIdx != 0) 682 return UnableToLegalize; 683 684 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 685 MIRBuilder.buildInstr(MI.getOpcode()) 686 .addDef(DstExt) 687 .addUse(MI.getOperand(1).getReg()); 688 689 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 690 MI.eraseFromParent(); 691 return Legalized; 692 } 693 case TargetOpcode::G_SITOFP: 694 case TargetOpcode::G_UITOFP: { 695 if (TypeIdx != 1) 696 return UnableToLegalize; 697 698 unsigned Src = MI.getOperand(1).getReg(); 699 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 700 701 if (MI.getOpcode() == TargetOpcode::G_SITOFP) { 702 MIRBuilder.buildSExt(SrcExt, Src); 703 } else { 704 assert(MI.getOpcode() == TargetOpcode::G_UITOFP && "Unexpected conv op"); 705 MIRBuilder.buildZExt(SrcExt, Src); 706 } 707 708 MIRBuilder.buildInstr(MI.getOpcode()) 709 .addDef(MI.getOperand(0).getReg()) 710 .addUse(SrcExt); 711 712 MI.eraseFromParent(); 713 return Legalized; 714 } 715 case TargetOpcode::G_INSERT: { 716 if (TypeIdx != 0) 717 return UnableToLegalize; 718 719 unsigned Src = MI.getOperand(1).getReg(); 720 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 721 MIRBuilder.buildAnyExt(SrcExt, Src); 722 723 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 724 auto MIB = MIRBuilder.buildInsert(DstExt, SrcExt, MI.getOperand(2).getReg(), 725 MI.getOperand(3).getImm()); 726 for (unsigned OpNum = 4; OpNum < MI.getNumOperands(); OpNum += 2) { 727 MIB.addReg(MI.getOperand(OpNum).getReg()); 728 MIB.addImm(MI.getOperand(OpNum + 1).getImm()); 729 } 730 731 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 732 MI.eraseFromParent(); 733 return Legalized; 734 } 735 case TargetOpcode::G_LOAD: 736 // For some types like i24, we might try to widen to i32. To properly handle 737 // this we should be using a dedicated extending load, until then avoid 738 // trying to legalize. 739 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) != 740 WideTy.getSizeInBits()) 741 return UnableToLegalize; 742 LLVM_FALLTHROUGH; 743 case TargetOpcode::G_SEXTLOAD: 744 case TargetOpcode::G_ZEXTLOAD: { 745 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 746 MIRBuilder.buildLoadInstr(MI.getOpcode(), DstExt, MI.getOperand(1).getReg(), 747 **MI.memoperands_begin()); 748 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 749 MI.eraseFromParent(); 750 return Legalized; 751 } 752 case TargetOpcode::G_STORE: { 753 if (MRI.getType(MI.getOperand(0).getReg()) != LLT::scalar(1) || 754 WideTy != LLT::scalar(8)) 755 return UnableToLegalize; 756 757 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 758 auto Content = TLI.getBooleanContents(false, false); 759 760 unsigned ExtOp = TargetOpcode::G_ANYEXT; 761 if (Content == TargetLoweringBase::ZeroOrOneBooleanContent) 762 ExtOp = TargetOpcode::G_ZEXT; 763 else if (Content == TargetLoweringBase::ZeroOrNegativeOneBooleanContent) 764 ExtOp = TargetOpcode::G_SEXT; 765 else 766 ExtOp = TargetOpcode::G_ANYEXT; 767 768 unsigned SrcExt = MRI.createGenericVirtualRegister(WideTy); 769 MIRBuilder.buildInstr(ExtOp).addDef(SrcExt).addUse( 770 MI.getOperand(0).getReg()); 771 MIRBuilder.buildStore(SrcExt, MI.getOperand(1).getReg(), 772 **MI.memoperands_begin()); 773 MI.eraseFromParent(); 774 return Legalized; 775 } 776 case TargetOpcode::G_CONSTANT: { 777 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 778 MIRBuilder.buildConstant(DstExt, *MI.getOperand(1).getCImm()); 779 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), DstExt); 780 MI.eraseFromParent(); 781 return Legalized; 782 } 783 case TargetOpcode::G_FCONSTANT: { 784 const ConstantFP *CFP = MI.getOperand(1).getFPImm(); 785 APFloat Val = CFP->getValueAPF(); 786 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 787 auto LLT2Sem = [](LLT Ty) { 788 switch (Ty.getSizeInBits()) { 789 case 32: 790 return &APFloat::IEEEsingle(); 791 break; 792 case 64: 793 return &APFloat::IEEEdouble(); 794 break; 795 default: 796 llvm_unreachable("Unhandled fp widen type"); 797 } 798 }; 799 bool LosesInfo; 800 Val.convert(*LLT2Sem(WideTy), APFloat::rmTowardZero, &LosesInfo); 801 auto Cst = MIRBuilder.buildFConstant(WideTy, *ConstantFP::get(Ctx, Val)); 802 MIRBuilder.buildFPTrunc(MI.getOperand(0).getReg(), Cst); 803 MI.eraseFromParent(); 804 return Legalized; 805 } 806 case TargetOpcode::G_BRCOND: { 807 unsigned TstExt = MRI.createGenericVirtualRegister(WideTy); 808 MIRBuilder.buildAnyExt(TstExt, MI.getOperand(0).getReg()); 809 MIRBuilder.buildBrCond(TstExt, *MI.getOperand(1).getMBB()); 810 MI.eraseFromParent(); 811 return Legalized; 812 } 813 case TargetOpcode::G_FCMP: { 814 unsigned Op0Ext, Op1Ext, DstReg; 815 unsigned Cmp1 = MI.getOperand(2).getReg(); 816 unsigned Cmp2 = MI.getOperand(3).getReg(); 817 if (TypeIdx == 0) { 818 Op0Ext = Cmp1; 819 Op1Ext = Cmp2; 820 DstReg = MRI.createGenericVirtualRegister(WideTy); 821 } else { 822 Op0Ext = MRI.createGenericVirtualRegister(WideTy); 823 Op1Ext = MRI.createGenericVirtualRegister(WideTy); 824 DstReg = MI.getOperand(0).getReg(); 825 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op0Ext, Cmp1); 826 MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, Op1Ext, Cmp2); 827 } 828 MIRBuilder.buildFCmp( 829 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 830 DstReg, Op0Ext, Op1Ext); 831 if (TypeIdx == 0) 832 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(), 833 DstReg); 834 MI.eraseFromParent(); 835 return Legalized; 836 } 837 case TargetOpcode::G_ICMP: { 838 bool IsSigned = CmpInst::isSigned( 839 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate())); 840 unsigned Cmp1 = MI.getOperand(2).getReg(); 841 unsigned Cmp2 = MI.getOperand(3).getReg(); 842 unsigned Op0Ext, Op1Ext, DstReg; 843 if (TypeIdx == 0) { 844 Op0Ext = Cmp1; 845 Op1Ext = Cmp2; 846 DstReg = MRI.createGenericVirtualRegister(WideTy); 847 } else { 848 Op0Ext = MRI.createGenericVirtualRegister(WideTy); 849 Op1Ext = MRI.createGenericVirtualRegister(WideTy); 850 DstReg = MI.getOperand(0).getReg(); 851 if (IsSigned) { 852 MIRBuilder.buildSExt(Op0Ext, Cmp1); 853 MIRBuilder.buildSExt(Op1Ext, Cmp2); 854 } else { 855 MIRBuilder.buildZExt(Op0Ext, Cmp1); 856 MIRBuilder.buildZExt(Op1Ext, Cmp2); 857 } 858 } 859 MIRBuilder.buildICmp( 860 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()), 861 DstReg, Op0Ext, Op1Ext); 862 if (TypeIdx == 0) 863 MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, MI.getOperand(0).getReg(), 864 DstReg); 865 MI.eraseFromParent(); 866 return Legalized; 867 } 868 case TargetOpcode::G_GEP: { 869 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 870 unsigned OffsetExt = MRI.createGenericVirtualRegister(WideTy); 871 MIRBuilder.buildSExt(OffsetExt, MI.getOperand(2).getReg()); 872 MI.getOperand(2).setReg(OffsetExt); 873 return Legalized; 874 } 875 case TargetOpcode::G_PHI: { 876 assert(TypeIdx == 0 && "Expecting only Idx 0"); 877 auto getExtendedReg = [&](unsigned Reg, MachineBasicBlock &MBB) { 878 auto FirstTermIt = MBB.getFirstTerminator(); 879 MIRBuilder.setInsertPt(MBB, FirstTermIt); 880 MachineInstr *DefMI = MRI.getVRegDef(Reg); 881 MachineInstrBuilder MIB; 882 if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) 883 MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy, 884 DefMI->getOperand(1).getReg()); 885 else 886 MIB = MIRBuilder.buildAnyExt(WideTy, Reg); 887 return MIB->getOperand(0).getReg(); 888 }; 889 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy); 890 for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end(); 891 OpIt != OpE;) { 892 unsigned Reg = OpIt++->getReg(); 893 MachineBasicBlock *OpMBB = OpIt++->getMBB(); 894 MIB.addReg(getExtendedReg(Reg, *OpMBB)); 895 MIB.addMBB(OpMBB); 896 } 897 auto *MBB = MI.getParent(); 898 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI()); 899 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), 900 MIB->getOperand(0).getReg()); 901 MI.eraseFromParent(); 902 return Legalized; 903 } 904 } 905 } 906 907 LegalizerHelper::LegalizeResult 908 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 909 using namespace TargetOpcode; 910 MIRBuilder.setInstr(MI); 911 912 switch(MI.getOpcode()) { 913 default: 914 return UnableToLegalize; 915 case TargetOpcode::G_SREM: 916 case TargetOpcode::G_UREM: { 917 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty); 918 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 919 .addDef(QuotReg) 920 .addUse(MI.getOperand(1).getReg()) 921 .addUse(MI.getOperand(2).getReg()); 922 923 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty); 924 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 925 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 926 ProdReg); 927 MI.eraseFromParent(); 928 return Legalized; 929 } 930 case TargetOpcode::G_SMULO: 931 case TargetOpcode::G_UMULO: { 932 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 933 // result. 934 unsigned Res = MI.getOperand(0).getReg(); 935 unsigned Overflow = MI.getOperand(1).getReg(); 936 unsigned LHS = MI.getOperand(2).getReg(); 937 unsigned RHS = MI.getOperand(3).getReg(); 938 939 MIRBuilder.buildMul(Res, LHS, RHS); 940 941 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 942 ? TargetOpcode::G_SMULH 943 : TargetOpcode::G_UMULH; 944 945 unsigned HiPart = MRI.createGenericVirtualRegister(Ty); 946 MIRBuilder.buildInstr(Opcode) 947 .addDef(HiPart) 948 .addUse(LHS) 949 .addUse(RHS); 950 951 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 952 MIRBuilder.buildConstant(Zero, 0); 953 954 // For *signed* multiply, overflow is detected by checking: 955 // (hi != (lo >> bitwidth-1)) 956 if (Opcode == TargetOpcode::G_SMULH) { 957 unsigned Shifted = MRI.createGenericVirtualRegister(Ty); 958 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty); 959 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1); 960 MIRBuilder.buildInstr(TargetOpcode::G_ASHR) 961 .addDef(Shifted) 962 .addUse(Res) 963 .addUse(ShiftAmt); 964 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted); 965 } else { 966 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 967 } 968 MI.eraseFromParent(); 969 return Legalized; 970 } 971 case TargetOpcode::G_FNEG: { 972 // TODO: Handle vector types once we are able to 973 // represent them. 974 if (Ty.isVector()) 975 return UnableToLegalize; 976 unsigned Res = MI.getOperand(0).getReg(); 977 Type *ZeroTy; 978 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 979 switch (Ty.getSizeInBits()) { 980 case 16: 981 ZeroTy = Type::getHalfTy(Ctx); 982 break; 983 case 32: 984 ZeroTy = Type::getFloatTy(Ctx); 985 break; 986 case 64: 987 ZeroTy = Type::getDoubleTy(Ctx); 988 break; 989 case 128: 990 ZeroTy = Type::getFP128Ty(Ctx); 991 break; 992 default: 993 llvm_unreachable("unexpected floating-point type"); 994 } 995 ConstantFP &ZeroForNegation = 996 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); 997 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation); 998 MIRBuilder.buildInstr(TargetOpcode::G_FSUB) 999 .addDef(Res) 1000 .addUse(Zero->getOperand(0).getReg()) 1001 .addUse(MI.getOperand(1).getReg()); 1002 MI.eraseFromParent(); 1003 return Legalized; 1004 } 1005 case TargetOpcode::G_FSUB: { 1006 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 1007 // First, check if G_FNEG is marked as Lower. If so, we may 1008 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 1009 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower) 1010 return UnableToLegalize; 1011 unsigned Res = MI.getOperand(0).getReg(); 1012 unsigned LHS = MI.getOperand(1).getReg(); 1013 unsigned RHS = MI.getOperand(2).getReg(); 1014 unsigned Neg = MRI.createGenericVirtualRegister(Ty); 1015 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); 1016 MIRBuilder.buildInstr(TargetOpcode::G_FADD) 1017 .addDef(Res) 1018 .addUse(LHS) 1019 .addUse(Neg); 1020 MI.eraseFromParent(); 1021 return Legalized; 1022 } 1023 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { 1024 unsigned OldValRes = MI.getOperand(0).getReg(); 1025 unsigned SuccessRes = MI.getOperand(1).getReg(); 1026 unsigned Addr = MI.getOperand(2).getReg(); 1027 unsigned CmpVal = MI.getOperand(3).getReg(); 1028 unsigned NewVal = MI.getOperand(4).getReg(); 1029 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, 1030 **MI.memoperands_begin()); 1031 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); 1032 MI.eraseFromParent(); 1033 return Legalized; 1034 } 1035 case TargetOpcode::G_LOAD: 1036 case TargetOpcode::G_SEXTLOAD: 1037 case TargetOpcode::G_ZEXTLOAD: { 1038 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT 1039 unsigned DstReg = MI.getOperand(0).getReg(); 1040 unsigned PtrReg = MI.getOperand(1).getReg(); 1041 LLT DstTy = MRI.getType(DstReg); 1042 auto &MMO = **MI.memoperands_begin(); 1043 1044 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) { 1045 MIRBuilder.buildLoad(DstReg, PtrReg, MMO); 1046 MI.eraseFromParent(); 1047 return Legalized; 1048 } 1049 1050 if (DstTy.isScalar()) { 1051 unsigned TmpReg = MRI.createGenericVirtualRegister( 1052 LLT::scalar(MMO.getSize() /* in bytes */ * 8)); 1053 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); 1054 switch (MI.getOpcode()) { 1055 default: 1056 llvm_unreachable("Unexpected opcode"); 1057 case TargetOpcode::G_LOAD: 1058 MIRBuilder.buildAnyExt(DstReg, TmpReg); 1059 break; 1060 case TargetOpcode::G_SEXTLOAD: 1061 MIRBuilder.buildSExt(DstReg, TmpReg); 1062 break; 1063 case TargetOpcode::G_ZEXTLOAD: 1064 MIRBuilder.buildZExt(DstReg, TmpReg); 1065 break; 1066 } 1067 MI.eraseFromParent(); 1068 return Legalized; 1069 } 1070 1071 return UnableToLegalize; 1072 } 1073 } 1074 } 1075 1076 LegalizerHelper::LegalizeResult 1077 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 1078 LLT NarrowTy) { 1079 // FIXME: Don't know how to handle secondary types yet. 1080 if (TypeIdx != 0) 1081 return UnableToLegalize; 1082 switch (MI.getOpcode()) { 1083 default: 1084 return UnableToLegalize; 1085 case TargetOpcode::G_ADD: { 1086 unsigned NarrowSize = NarrowTy.getSizeInBits(); 1087 unsigned DstReg = MI.getOperand(0).getReg(); 1088 unsigned Size = MRI.getType(DstReg).getSizeInBits(); 1089 int NumParts = Size / NarrowSize; 1090 // FIXME: Don't know how to handle the situation where the small vectors 1091 // aren't all the same size yet. 1092 if (Size % NarrowSize != 0) 1093 return UnableToLegalize; 1094 1095 MIRBuilder.setInstr(MI); 1096 1097 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 1098 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 1099 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 1100 1101 for (int i = 0; i < NumParts; ++i) { 1102 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 1103 MIRBuilder.buildAdd(DstReg, Src1Regs[i], Src2Regs[i]); 1104 DstRegs.push_back(DstReg); 1105 } 1106 1107 MIRBuilder.buildMerge(DstReg, DstRegs); 1108 MI.eraseFromParent(); 1109 return Legalized; 1110 } 1111 } 1112 } 1113