1 //===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file This file implements the LegalizerHelper class to legalize 10 /// individual instructions and the LegalizeMachineIR wrapper pass for the 11 /// primary legalization. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 16 #include "llvm/CodeGen/GlobalISel/CallLowering.h" 17 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" 18 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 19 #include "llvm/CodeGen/MachineRegisterInfo.h" 20 #include "llvm/CodeGen/TargetFrameLowering.h" 21 #include "llvm/CodeGen/TargetInstrInfo.h" 22 #include "llvm/CodeGen/TargetLowering.h" 23 #include "llvm/CodeGen/TargetSubtargetInfo.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/MathExtras.h" 26 #include "llvm/Support/raw_ostream.h" 27 28 #define DEBUG_TYPE "legalizer" 29 30 using namespace llvm; 31 using namespace LegalizeActions; 32 33 /// Try to break down \p OrigTy into \p NarrowTy sized pieces. 34 /// 35 /// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy, 36 /// with any leftover piece as type \p LeftoverTy 37 /// 38 /// Returns -1 in the first element of the pair if the breakdown is not 39 /// satisfiable. 40 static std::pair<int, int> 41 getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) { 42 assert(!LeftoverTy.isValid() && "this is an out argument"); 43 44 unsigned Size = OrigTy.getSizeInBits(); 45 unsigned NarrowSize = NarrowTy.getSizeInBits(); 46 unsigned NumParts = Size / NarrowSize; 47 unsigned LeftoverSize = Size - NumParts * NarrowSize; 48 assert(Size > NarrowSize); 49 50 if (LeftoverSize == 0) 51 return {NumParts, 0}; 52 53 if (NarrowTy.isVector()) { 54 unsigned EltSize = OrigTy.getScalarSizeInBits(); 55 if (LeftoverSize % EltSize != 0) 56 return {-1, -1}; 57 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize); 58 } else { 59 LeftoverTy = LLT::scalar(LeftoverSize); 60 } 61 62 int NumLeftover = LeftoverSize / LeftoverTy.getSizeInBits(); 63 return std::make_pair(NumParts, NumLeftover); 64 } 65 66 LegalizerHelper::LegalizerHelper(MachineFunction &MF, 67 GISelChangeObserver &Observer, 68 MachineIRBuilder &Builder) 69 : MIRBuilder(Builder), MRI(MF.getRegInfo()), 70 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) { 71 MIRBuilder.setMF(MF); 72 MIRBuilder.setChangeObserver(Observer); 73 } 74 75 LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, 76 GISelChangeObserver &Observer, 77 MachineIRBuilder &B) 78 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) { 79 MIRBuilder.setMF(MF); 80 MIRBuilder.setChangeObserver(Observer); 81 } 82 LegalizerHelper::LegalizeResult 83 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) { 84 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs())); 85 86 if (MI.getOpcode() == TargetOpcode::G_INTRINSIC || 87 MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS) 88 return LI.legalizeIntrinsic(MI, MRI, MIRBuilder) ? Legalized 89 : UnableToLegalize; 90 auto Step = LI.getAction(MI, MRI); 91 switch (Step.Action) { 92 case Legal: 93 LLVM_DEBUG(dbgs() << ".. Already legal\n"); 94 return AlreadyLegal; 95 case Libcall: 96 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n"); 97 return libcall(MI); 98 case NarrowScalar: 99 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n"); 100 return narrowScalar(MI, Step.TypeIdx, Step.NewType); 101 case WidenScalar: 102 LLVM_DEBUG(dbgs() << ".. Widen scalar\n"); 103 return widenScalar(MI, Step.TypeIdx, Step.NewType); 104 case Lower: 105 LLVM_DEBUG(dbgs() << ".. Lower\n"); 106 return lower(MI, Step.TypeIdx, Step.NewType); 107 case FewerElements: 108 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n"); 109 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType); 110 case MoreElements: 111 LLVM_DEBUG(dbgs() << ".. Increase number of elements\n"); 112 return moreElementsVector(MI, Step.TypeIdx, Step.NewType); 113 case Custom: 114 LLVM_DEBUG(dbgs() << ".. Custom legalization\n"); 115 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized 116 : UnableToLegalize; 117 default: 118 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n"); 119 return UnableToLegalize; 120 } 121 } 122 123 void LegalizerHelper::extractParts(Register Reg, LLT Ty, int NumParts, 124 SmallVectorImpl<Register> &VRegs) { 125 for (int i = 0; i < NumParts; ++i) 126 VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); 127 MIRBuilder.buildUnmerge(VRegs, Reg); 128 } 129 130 bool LegalizerHelper::extractParts(Register Reg, LLT RegTy, 131 LLT MainTy, LLT &LeftoverTy, 132 SmallVectorImpl<Register> &VRegs, 133 SmallVectorImpl<Register> &LeftoverRegs) { 134 assert(!LeftoverTy.isValid() && "this is an out argument"); 135 136 unsigned RegSize = RegTy.getSizeInBits(); 137 unsigned MainSize = MainTy.getSizeInBits(); 138 unsigned NumParts = RegSize / MainSize; 139 unsigned LeftoverSize = RegSize - NumParts * MainSize; 140 141 // Use an unmerge when possible. 142 if (LeftoverSize == 0) { 143 for (unsigned I = 0; I < NumParts; ++I) 144 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy)); 145 MIRBuilder.buildUnmerge(VRegs, Reg); 146 return true; 147 } 148 149 if (MainTy.isVector()) { 150 unsigned EltSize = MainTy.getScalarSizeInBits(); 151 if (LeftoverSize % EltSize != 0) 152 return false; 153 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize); 154 } else { 155 LeftoverTy = LLT::scalar(LeftoverSize); 156 } 157 158 // For irregular sizes, extract the individual parts. 159 for (unsigned I = 0; I != NumParts; ++I) { 160 Register NewReg = MRI.createGenericVirtualRegister(MainTy); 161 VRegs.push_back(NewReg); 162 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I); 163 } 164 165 for (unsigned Offset = MainSize * NumParts; Offset < RegSize; 166 Offset += LeftoverSize) { 167 Register NewReg = MRI.createGenericVirtualRegister(LeftoverTy); 168 LeftoverRegs.push_back(NewReg); 169 MIRBuilder.buildExtract(NewReg, Reg, Offset); 170 } 171 172 return true; 173 } 174 175 static LLT getGCDType(LLT OrigTy, LLT TargetTy) { 176 if (OrigTy.isVector() && TargetTy.isVector()) { 177 assert(OrigTy.getElementType() == TargetTy.getElementType()); 178 int GCD = greatestCommonDivisor(OrigTy.getNumElements(), 179 TargetTy.getNumElements()); 180 return LLT::scalarOrVector(GCD, OrigTy.getElementType()); 181 } 182 183 if (OrigTy.isVector() && !TargetTy.isVector()) { 184 assert(OrigTy.getElementType() == TargetTy); 185 return TargetTy; 186 } 187 188 assert(!OrigTy.isVector() && !TargetTy.isVector()); 189 190 int GCD = greatestCommonDivisor(OrigTy.getSizeInBits(), 191 TargetTy.getSizeInBits()); 192 return LLT::scalar(GCD); 193 } 194 195 void LegalizerHelper::insertParts(Register DstReg, 196 LLT ResultTy, LLT PartTy, 197 ArrayRef<Register> PartRegs, 198 LLT LeftoverTy, 199 ArrayRef<Register> LeftoverRegs) { 200 if (!LeftoverTy.isValid()) { 201 assert(LeftoverRegs.empty()); 202 203 if (!ResultTy.isVector()) { 204 MIRBuilder.buildMerge(DstReg, PartRegs); 205 return; 206 } 207 208 if (PartTy.isVector()) 209 MIRBuilder.buildConcatVectors(DstReg, PartRegs); 210 else 211 MIRBuilder.buildBuildVector(DstReg, PartRegs); 212 return; 213 } 214 215 unsigned PartSize = PartTy.getSizeInBits(); 216 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits(); 217 218 Register CurResultReg = MRI.createGenericVirtualRegister(ResultTy); 219 MIRBuilder.buildUndef(CurResultReg); 220 221 unsigned Offset = 0; 222 for (Register PartReg : PartRegs) { 223 Register NewResultReg = MRI.createGenericVirtualRegister(ResultTy); 224 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset); 225 CurResultReg = NewResultReg; 226 Offset += PartSize; 227 } 228 229 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) { 230 // Use the original output register for the final insert to avoid a copy. 231 Register NewResultReg = (I + 1 == E) ? 232 DstReg : MRI.createGenericVirtualRegister(ResultTy); 233 234 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset); 235 CurResultReg = NewResultReg; 236 Offset += LeftoverPartSize; 237 } 238 } 239 240 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { 241 switch (Opcode) { 242 case TargetOpcode::G_SDIV: 243 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 244 switch (Size) { 245 case 32: 246 return RTLIB::SDIV_I32; 247 case 64: 248 return RTLIB::SDIV_I64; 249 case 128: 250 return RTLIB::SDIV_I128; 251 default: 252 llvm_unreachable("unexpected size"); 253 } 254 case TargetOpcode::G_UDIV: 255 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 256 switch (Size) { 257 case 32: 258 return RTLIB::UDIV_I32; 259 case 64: 260 return RTLIB::UDIV_I64; 261 case 128: 262 return RTLIB::UDIV_I128; 263 default: 264 llvm_unreachable("unexpected size"); 265 } 266 case TargetOpcode::G_SREM: 267 assert((Size == 32 || Size == 64) && "Unsupported size"); 268 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32; 269 case TargetOpcode::G_UREM: 270 assert((Size == 32 || Size == 64) && "Unsupported size"); 271 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32; 272 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 273 assert(Size == 32 && "Unsupported size"); 274 return RTLIB::CTLZ_I32; 275 case TargetOpcode::G_FADD: 276 assert((Size == 32 || Size == 64) && "Unsupported size"); 277 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; 278 case TargetOpcode::G_FSUB: 279 assert((Size == 32 || Size == 64) && "Unsupported size"); 280 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32; 281 case TargetOpcode::G_FMUL: 282 assert((Size == 32 || Size == 64) && "Unsupported size"); 283 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32; 284 case TargetOpcode::G_FDIV: 285 assert((Size == 32 || Size == 64) && "Unsupported size"); 286 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32; 287 case TargetOpcode::G_FEXP: 288 assert((Size == 32 || Size == 64) && "Unsupported size"); 289 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32; 290 case TargetOpcode::G_FEXP2: 291 assert((Size == 32 || Size == 64) && "Unsupported size"); 292 return Size == 64 ? RTLIB::EXP2_F64 : RTLIB::EXP2_F32; 293 case TargetOpcode::G_FREM: 294 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; 295 case TargetOpcode::G_FPOW: 296 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; 297 case TargetOpcode::G_FMA: 298 assert((Size == 32 || Size == 64) && "Unsupported size"); 299 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32; 300 case TargetOpcode::G_FSIN: 301 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 302 return Size == 128 ? RTLIB::SIN_F128 303 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32; 304 case TargetOpcode::G_FCOS: 305 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 306 return Size == 128 ? RTLIB::COS_F128 307 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32; 308 case TargetOpcode::G_FLOG10: 309 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 310 return Size == 128 ? RTLIB::LOG10_F128 311 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32; 312 case TargetOpcode::G_FLOG: 313 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 314 return Size == 128 ? RTLIB::LOG_F128 315 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32; 316 case TargetOpcode::G_FLOG2: 317 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 318 return Size == 128 ? RTLIB::LOG2_F128 319 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32; 320 case TargetOpcode::G_FCEIL: 321 assert((Size == 32 || Size == 64) && "Unsupported size"); 322 return Size == 64 ? RTLIB::CEIL_F64 : RTLIB::CEIL_F32; 323 case TargetOpcode::G_FFLOOR: 324 assert((Size == 32 || Size == 64) && "Unsupported size"); 325 return Size == 64 ? RTLIB::FLOOR_F64 : RTLIB::FLOOR_F32; 326 } 327 llvm_unreachable("Unknown libcall function"); 328 } 329 330 LegalizerHelper::LegalizeResult 331 llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, 332 const CallLowering::ArgInfo &Result, 333 ArrayRef<CallLowering::ArgInfo> Args) { 334 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 335 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 336 const char *Name = TLI.getLibcallName(Libcall); 337 338 MIRBuilder.getMF().getFrameInfo().setHasCalls(true); 339 340 CallLowering::CallLoweringInfo Info; 341 Info.CallConv = TLI.getLibcallCallingConv(Libcall); 342 Info.Callee = MachineOperand::CreateES(Name); 343 Info.OrigRet = Result; 344 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs)); 345 if (!CLI.lowerCall(MIRBuilder, Info)) 346 return LegalizerHelper::UnableToLegalize; 347 348 return LegalizerHelper::Legalized; 349 } 350 351 // Useful for libcalls where all operands have the same type. 352 static LegalizerHelper::LegalizeResult 353 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, 354 Type *OpType) { 355 auto Libcall = getRTLibDesc(MI.getOpcode(), Size); 356 357 SmallVector<CallLowering::ArgInfo, 3> Args; 358 for (unsigned i = 1; i < MI.getNumOperands(); i++) 359 Args.push_back({MI.getOperand(i).getReg(), OpType}); 360 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType}, 361 Args); 362 } 363 364 LegalizerHelper::LegalizeResult 365 llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 366 MachineInstr &MI) { 367 assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS); 368 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 369 370 SmallVector<CallLowering::ArgInfo, 3> Args; 371 for (unsigned i = 1; i < MI.getNumOperands(); i++) { 372 Register Reg = MI.getOperand(i).getReg(); 373 374 // Need derive an IR type for call lowering. 375 LLT OpLLT = MRI.getType(Reg); 376 Type *OpTy = nullptr; 377 if (OpLLT.isPointer()) 378 OpTy = Type::getInt8PtrTy(Ctx, OpLLT.getAddressSpace()); 379 else 380 OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits()); 381 Args.push_back({Reg, OpTy}); 382 } 383 384 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 385 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 386 Intrinsic::ID ID = MI.getOperand(0).getIntrinsicID(); 387 RTLIB::Libcall RTLibcall; 388 switch (ID) { 389 case Intrinsic::memcpy: 390 RTLibcall = RTLIB::MEMCPY; 391 break; 392 case Intrinsic::memset: 393 RTLibcall = RTLIB::MEMSET; 394 break; 395 case Intrinsic::memmove: 396 RTLibcall = RTLIB::MEMMOVE; 397 break; 398 default: 399 return LegalizerHelper::UnableToLegalize; 400 } 401 const char *Name = TLI.getLibcallName(RTLibcall); 402 403 MIRBuilder.setInstr(MI); 404 MIRBuilder.getMF().getFrameInfo().setHasCalls(true); 405 406 CallLowering::CallLoweringInfo Info; 407 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall); 408 Info.Callee = MachineOperand::CreateES(Name); 409 Info.OrigRet = CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx)); 410 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs)); 411 if (!CLI.lowerCall(MIRBuilder, Info)) 412 return LegalizerHelper::UnableToLegalize; 413 414 return LegalizerHelper::Legalized; 415 } 416 417 static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, 418 Type *FromType) { 419 auto ToMVT = MVT::getVT(ToType); 420 auto FromMVT = MVT::getVT(FromType); 421 422 switch (Opcode) { 423 case TargetOpcode::G_FPEXT: 424 return RTLIB::getFPEXT(FromMVT, ToMVT); 425 case TargetOpcode::G_FPTRUNC: 426 return RTLIB::getFPROUND(FromMVT, ToMVT); 427 case TargetOpcode::G_FPTOSI: 428 return RTLIB::getFPTOSINT(FromMVT, ToMVT); 429 case TargetOpcode::G_FPTOUI: 430 return RTLIB::getFPTOUINT(FromMVT, ToMVT); 431 case TargetOpcode::G_SITOFP: 432 return RTLIB::getSINTTOFP(FromMVT, ToMVT); 433 case TargetOpcode::G_UITOFP: 434 return RTLIB::getUINTTOFP(FromMVT, ToMVT); 435 } 436 llvm_unreachable("Unsupported libcall function"); 437 } 438 439 static LegalizerHelper::LegalizeResult 440 conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, 441 Type *FromType) { 442 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType); 443 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType}, 444 {{MI.getOperand(1).getReg(), FromType}}); 445 } 446 447 LegalizerHelper::LegalizeResult 448 LegalizerHelper::libcall(MachineInstr &MI) { 449 LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); 450 unsigned Size = LLTy.getSizeInBits(); 451 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 452 453 MIRBuilder.setInstr(MI); 454 455 switch (MI.getOpcode()) { 456 default: 457 return UnableToLegalize; 458 case TargetOpcode::G_SDIV: 459 case TargetOpcode::G_UDIV: 460 case TargetOpcode::G_SREM: 461 case TargetOpcode::G_UREM: 462 case TargetOpcode::G_CTLZ_ZERO_UNDEF: { 463 Type *HLTy = IntegerType::get(Ctx, Size); 464 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 465 if (Status != Legalized) 466 return Status; 467 break; 468 } 469 case TargetOpcode::G_FADD: 470 case TargetOpcode::G_FSUB: 471 case TargetOpcode::G_FMUL: 472 case TargetOpcode::G_FDIV: 473 case TargetOpcode::G_FMA: 474 case TargetOpcode::G_FPOW: 475 case TargetOpcode::G_FREM: 476 case TargetOpcode::G_FCOS: 477 case TargetOpcode::G_FSIN: 478 case TargetOpcode::G_FLOG10: 479 case TargetOpcode::G_FLOG: 480 case TargetOpcode::G_FLOG2: 481 case TargetOpcode::G_FEXP: 482 case TargetOpcode::G_FEXP2: 483 case TargetOpcode::G_FCEIL: 484 case TargetOpcode::G_FFLOOR: { 485 if (Size > 64) { 486 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n"); 487 return UnableToLegalize; 488 } 489 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); 490 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 491 if (Status != Legalized) 492 return Status; 493 break; 494 } 495 case TargetOpcode::G_FPEXT: { 496 // FIXME: Support other floating point types (half, fp128 etc) 497 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 498 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 499 if (ToSize != 64 || FromSize != 32) 500 return UnableToLegalize; 501 LegalizeResult Status = conversionLibcall( 502 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx)); 503 if (Status != Legalized) 504 return Status; 505 break; 506 } 507 case TargetOpcode::G_FPTRUNC: { 508 // FIXME: Support other floating point types (half, fp128 etc) 509 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 510 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 511 if (ToSize != 32 || FromSize != 64) 512 return UnableToLegalize; 513 LegalizeResult Status = conversionLibcall( 514 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx)); 515 if (Status != Legalized) 516 return Status; 517 break; 518 } 519 case TargetOpcode::G_FPTOSI: 520 case TargetOpcode::G_FPTOUI: { 521 // FIXME: Support other types 522 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 523 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 524 if ((ToSize != 32 && ToSize != 64) || (FromSize != 32 && FromSize != 64)) 525 return UnableToLegalize; 526 LegalizeResult Status = conversionLibcall( 527 MI, MIRBuilder, 528 ToSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx), 529 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx)); 530 if (Status != Legalized) 531 return Status; 532 break; 533 } 534 case TargetOpcode::G_SITOFP: 535 case TargetOpcode::G_UITOFP: { 536 // FIXME: Support other types 537 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 538 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 539 if ((FromSize != 32 && FromSize != 64) || (ToSize != 32 && ToSize != 64)) 540 return UnableToLegalize; 541 LegalizeResult Status = conversionLibcall( 542 MI, MIRBuilder, 543 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx), 544 FromSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx)); 545 if (Status != Legalized) 546 return Status; 547 break; 548 } 549 } 550 551 MI.eraseFromParent(); 552 return Legalized; 553 } 554 555 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 556 unsigned TypeIdx, 557 LLT NarrowTy) { 558 MIRBuilder.setInstr(MI); 559 560 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 561 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 562 563 switch (MI.getOpcode()) { 564 default: 565 return UnableToLegalize; 566 case TargetOpcode::G_IMPLICIT_DEF: { 567 // FIXME: add support for when SizeOp0 isn't an exact multiple of 568 // NarrowSize. 569 if (SizeOp0 % NarrowSize != 0) 570 return UnableToLegalize; 571 int NumParts = SizeOp0 / NarrowSize; 572 573 SmallVector<Register, 2> DstRegs; 574 for (int i = 0; i < NumParts; ++i) 575 DstRegs.push_back( 576 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg()); 577 578 Register DstReg = MI.getOperand(0).getReg(); 579 if(MRI.getType(DstReg).isVector()) 580 MIRBuilder.buildBuildVector(DstReg, DstRegs); 581 else 582 MIRBuilder.buildMerge(DstReg, DstRegs); 583 MI.eraseFromParent(); 584 return Legalized; 585 } 586 case TargetOpcode::G_CONSTANT: { 587 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 588 const APInt &Val = MI.getOperand(1).getCImm()->getValue(); 589 unsigned TotalSize = Ty.getSizeInBits(); 590 unsigned NarrowSize = NarrowTy.getSizeInBits(); 591 int NumParts = TotalSize / NarrowSize; 592 593 SmallVector<Register, 4> PartRegs; 594 for (int I = 0; I != NumParts; ++I) { 595 unsigned Offset = I * NarrowSize; 596 auto K = MIRBuilder.buildConstant(NarrowTy, 597 Val.lshr(Offset).trunc(NarrowSize)); 598 PartRegs.push_back(K.getReg(0)); 599 } 600 601 LLT LeftoverTy; 602 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize; 603 SmallVector<Register, 1> LeftoverRegs; 604 if (LeftoverBits != 0) { 605 LeftoverTy = LLT::scalar(LeftoverBits); 606 auto K = MIRBuilder.buildConstant( 607 LeftoverTy, 608 Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits)); 609 LeftoverRegs.push_back(K.getReg(0)); 610 } 611 612 insertParts(MI.getOperand(0).getReg(), 613 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs); 614 615 MI.eraseFromParent(); 616 return Legalized; 617 } 618 case TargetOpcode::G_SEXT: { 619 if (TypeIdx != 0) 620 return UnableToLegalize; 621 622 Register SrcReg = MI.getOperand(1).getReg(); 623 LLT SrcTy = MRI.getType(SrcReg); 624 625 // FIXME: support the general case where the requested NarrowTy may not be 626 // the same as the source type. E.g. s128 = sext(s32) 627 if ((SrcTy.getSizeInBits() != SizeOp0 / 2) || 628 SrcTy.getSizeInBits() != NarrowTy.getSizeInBits()) { 629 LLVM_DEBUG(dbgs() << "Can't narrow sext to type " << NarrowTy << "\n"); 630 return UnableToLegalize; 631 } 632 633 // Shift the sign bit of the low register through the high register. 634 auto ShiftAmt = 635 MIRBuilder.buildConstant(LLT::scalar(64), NarrowTy.getSizeInBits() - 1); 636 auto Shift = MIRBuilder.buildAShr(NarrowTy, SrcReg, ShiftAmt); 637 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {SrcReg, Shift.getReg(0)}); 638 MI.eraseFromParent(); 639 return Legalized; 640 } 641 case TargetOpcode::G_ZEXT: { 642 if (TypeIdx != 0) 643 return UnableToLegalize; 644 645 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 646 uint64_t SizeOp1 = SrcTy.getSizeInBits(); 647 if (SizeOp0 % SizeOp1 != 0) 648 return UnableToLegalize; 649 650 // Generate a merge where the bottom bits are taken from the source, and 651 // zero everything else. 652 Register ZeroReg = MIRBuilder.buildConstant(SrcTy, 0).getReg(0); 653 unsigned NumParts = SizeOp0 / SizeOp1; 654 SmallVector<Register, 4> Srcs = {MI.getOperand(1).getReg()}; 655 for (unsigned Part = 1; Part < NumParts; ++Part) 656 Srcs.push_back(ZeroReg); 657 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), Srcs); 658 MI.eraseFromParent(); 659 return Legalized; 660 } 661 case TargetOpcode::G_TRUNC: { 662 if (TypeIdx != 1) 663 return UnableToLegalize; 664 665 uint64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 666 if (NarrowTy.getSizeInBits() * 2 != SizeOp1) { 667 LLVM_DEBUG(dbgs() << "Can't narrow trunc to type " << NarrowTy << "\n"); 668 return UnableToLegalize; 669 } 670 671 auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1).getReg()); 672 MIRBuilder.buildCopy(MI.getOperand(0).getReg(), Unmerge.getReg(0)); 673 MI.eraseFromParent(); 674 return Legalized; 675 } 676 677 case TargetOpcode::G_ADD: { 678 // FIXME: add support for when SizeOp0 isn't an exact multiple of 679 // NarrowSize. 680 if (SizeOp0 % NarrowSize != 0) 681 return UnableToLegalize; 682 // Expand in terms of carry-setting/consuming G_ADDE instructions. 683 int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); 684 685 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs; 686 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 687 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 688 689 Register CarryIn; 690 for (int i = 0; i < NumParts; ++i) { 691 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); 692 Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 693 694 if (i == 0) 695 MIRBuilder.buildUAddo(DstReg, CarryOut, Src1Regs[i], Src2Regs[i]); 696 else { 697 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], 698 Src2Regs[i], CarryIn); 699 } 700 701 DstRegs.push_back(DstReg); 702 CarryIn = CarryOut; 703 } 704 Register DstReg = MI.getOperand(0).getReg(); 705 if(MRI.getType(DstReg).isVector()) 706 MIRBuilder.buildBuildVector(DstReg, DstRegs); 707 else 708 MIRBuilder.buildMerge(DstReg, DstRegs); 709 MI.eraseFromParent(); 710 return Legalized; 711 } 712 case TargetOpcode::G_SUB: { 713 // FIXME: add support for when SizeOp0 isn't an exact multiple of 714 // NarrowSize. 715 if (SizeOp0 % NarrowSize != 0) 716 return UnableToLegalize; 717 718 int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); 719 720 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs; 721 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 722 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 723 724 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); 725 Register BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 726 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut}, 727 {Src1Regs[0], Src2Regs[0]}); 728 DstRegs.push_back(DstReg); 729 Register BorrowIn = BorrowOut; 730 for (int i = 1; i < NumParts; ++i) { 731 DstReg = MRI.createGenericVirtualRegister(NarrowTy); 732 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 733 734 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut}, 735 {Src1Regs[i], Src2Regs[i], BorrowIn}); 736 737 DstRegs.push_back(DstReg); 738 BorrowIn = BorrowOut; 739 } 740 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 741 MI.eraseFromParent(); 742 return Legalized; 743 } 744 case TargetOpcode::G_MUL: 745 case TargetOpcode::G_UMULH: 746 return narrowScalarMul(MI, NarrowTy); 747 case TargetOpcode::G_EXTRACT: 748 return narrowScalarExtract(MI, TypeIdx, NarrowTy); 749 case TargetOpcode::G_INSERT: 750 return narrowScalarInsert(MI, TypeIdx, NarrowTy); 751 case TargetOpcode::G_LOAD: { 752 const auto &MMO = **MI.memoperands_begin(); 753 Register DstReg = MI.getOperand(0).getReg(); 754 LLT DstTy = MRI.getType(DstReg); 755 if (DstTy.isVector()) 756 return UnableToLegalize; 757 758 if (8 * MMO.getSize() != DstTy.getSizeInBits()) { 759 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 760 auto &MMO = **MI.memoperands_begin(); 761 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO); 762 MIRBuilder.buildAnyExt(DstReg, TmpReg); 763 MI.eraseFromParent(); 764 return Legalized; 765 } 766 767 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy); 768 } 769 case TargetOpcode::G_ZEXTLOAD: 770 case TargetOpcode::G_SEXTLOAD: { 771 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD; 772 Register DstReg = MI.getOperand(0).getReg(); 773 Register PtrReg = MI.getOperand(1).getReg(); 774 775 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 776 auto &MMO = **MI.memoperands_begin(); 777 if (MMO.getSizeInBits() == NarrowSize) { 778 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); 779 } else { 780 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD 781 : TargetOpcode::G_SEXTLOAD; 782 MIRBuilder.buildInstr(ExtLoad) 783 .addDef(TmpReg) 784 .addUse(PtrReg) 785 .addMemOperand(&MMO); 786 } 787 788 if (ZExt) 789 MIRBuilder.buildZExt(DstReg, TmpReg); 790 else 791 MIRBuilder.buildSExt(DstReg, TmpReg); 792 793 MI.eraseFromParent(); 794 return Legalized; 795 } 796 case TargetOpcode::G_STORE: { 797 const auto &MMO = **MI.memoperands_begin(); 798 799 Register SrcReg = MI.getOperand(0).getReg(); 800 LLT SrcTy = MRI.getType(SrcReg); 801 if (SrcTy.isVector()) 802 return UnableToLegalize; 803 804 int NumParts = SizeOp0 / NarrowSize; 805 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits(); 806 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize; 807 if (SrcTy.isVector() && LeftoverBits != 0) 808 return UnableToLegalize; 809 810 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) { 811 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 812 auto &MMO = **MI.memoperands_begin(); 813 MIRBuilder.buildTrunc(TmpReg, SrcReg); 814 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO); 815 MI.eraseFromParent(); 816 return Legalized; 817 } 818 819 return reduceLoadStoreWidth(MI, 0, NarrowTy); 820 } 821 case TargetOpcode::G_SELECT: 822 return narrowScalarSelect(MI, TypeIdx, NarrowTy); 823 case TargetOpcode::G_AND: 824 case TargetOpcode::G_OR: 825 case TargetOpcode::G_XOR: { 826 // Legalize bitwise operation: 827 // A = BinOp<Ty> B, C 828 // into: 829 // B1, ..., BN = G_UNMERGE_VALUES B 830 // C1, ..., CN = G_UNMERGE_VALUES C 831 // A1 = BinOp<Ty/N> B1, C2 832 // ... 833 // AN = BinOp<Ty/N> BN, CN 834 // A = G_MERGE_VALUES A1, ..., AN 835 return narrowScalarBasic(MI, TypeIdx, NarrowTy); 836 } 837 case TargetOpcode::G_SHL: 838 case TargetOpcode::G_LSHR: 839 case TargetOpcode::G_ASHR: 840 return narrowScalarShift(MI, TypeIdx, NarrowTy); 841 case TargetOpcode::G_CTLZ: 842 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 843 case TargetOpcode::G_CTTZ: 844 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 845 case TargetOpcode::G_CTPOP: 846 if (TypeIdx != 0) 847 return UnableToLegalize; // TODO 848 849 Observer.changingInstr(MI); 850 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT); 851 Observer.changedInstr(MI); 852 return Legalized; 853 case TargetOpcode::G_INTTOPTR: 854 if (TypeIdx != 1) 855 return UnableToLegalize; 856 857 Observer.changingInstr(MI); 858 narrowScalarSrc(MI, NarrowTy, 1); 859 Observer.changedInstr(MI); 860 return Legalized; 861 case TargetOpcode::G_PTRTOINT: 862 if (TypeIdx != 0) 863 return UnableToLegalize; 864 865 Observer.changingInstr(MI); 866 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT); 867 Observer.changedInstr(MI); 868 return Legalized; 869 case TargetOpcode::G_PHI: { 870 unsigned NumParts = SizeOp0 / NarrowSize; 871 SmallVector<Register, 2> DstRegs; 872 SmallVector<SmallVector<Register, 2>, 2> SrcRegs; 873 DstRegs.resize(NumParts); 874 SrcRegs.resize(MI.getNumOperands() / 2); 875 Observer.changingInstr(MI); 876 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) { 877 MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB(); 878 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 879 extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts, 880 SrcRegs[i / 2]); 881 } 882 MachineBasicBlock &MBB = *MI.getParent(); 883 MIRBuilder.setInsertPt(MBB, MI); 884 for (unsigned i = 0; i < NumParts; ++i) { 885 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy); 886 MachineInstrBuilder MIB = 887 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]); 888 for (unsigned j = 1; j < MI.getNumOperands(); j += 2) 889 MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1)); 890 } 891 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI()); 892 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 893 Observer.changedInstr(MI); 894 MI.eraseFromParent(); 895 return Legalized; 896 } 897 case TargetOpcode::G_EXTRACT_VECTOR_ELT: 898 case TargetOpcode::G_INSERT_VECTOR_ELT: { 899 if (TypeIdx != 2) 900 return UnableToLegalize; 901 902 int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3; 903 Observer.changingInstr(MI); 904 narrowScalarSrc(MI, NarrowTy, OpIdx); 905 Observer.changedInstr(MI); 906 return Legalized; 907 } 908 case TargetOpcode::G_ICMP: { 909 uint64_t SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 910 if (NarrowSize * 2 != SrcSize) 911 return UnableToLegalize; 912 913 Observer.changingInstr(MI); 914 Register LHSL = MRI.createGenericVirtualRegister(NarrowTy); 915 Register LHSH = MRI.createGenericVirtualRegister(NarrowTy); 916 MIRBuilder.buildUnmerge({LHSL, LHSH}, MI.getOperand(2).getReg()); 917 918 Register RHSL = MRI.createGenericVirtualRegister(NarrowTy); 919 Register RHSH = MRI.createGenericVirtualRegister(NarrowTy); 920 MIRBuilder.buildUnmerge({RHSL, RHSH}, MI.getOperand(3).getReg()); 921 922 CmpInst::Predicate Pred = 923 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()); 924 LLT ResTy = MRI.getType(MI.getOperand(0).getReg()); 925 926 if (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) { 927 MachineInstrBuilder XorL = MIRBuilder.buildXor(NarrowTy, LHSL, RHSL); 928 MachineInstrBuilder XorH = MIRBuilder.buildXor(NarrowTy, LHSH, RHSH); 929 MachineInstrBuilder Or = MIRBuilder.buildOr(NarrowTy, XorL, XorH); 930 MachineInstrBuilder Zero = MIRBuilder.buildConstant(NarrowTy, 0); 931 MIRBuilder.buildICmp(Pred, MI.getOperand(0).getReg(), Or, Zero); 932 } else { 933 MachineInstrBuilder CmpH = MIRBuilder.buildICmp(Pred, ResTy, LHSH, RHSH); 934 MachineInstrBuilder CmpHEQ = 935 MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy, LHSH, RHSH); 936 MachineInstrBuilder CmpLU = MIRBuilder.buildICmp( 937 ICmpInst::getUnsignedPredicate(Pred), ResTy, LHSL, RHSL); 938 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), CmpHEQ, CmpLU, CmpH); 939 } 940 Observer.changedInstr(MI); 941 MI.eraseFromParent(); 942 return Legalized; 943 } 944 case TargetOpcode::G_SEXT_INREG: { 945 if (TypeIdx != 0) 946 return UnableToLegalize; 947 948 if (!MI.getOperand(2).isImm()) 949 return UnableToLegalize; 950 int64_t SizeInBits = MI.getOperand(2).getImm(); 951 952 // So long as the new type has more bits than the bits we're extending we 953 // don't need to break it apart. 954 if (NarrowTy.getScalarSizeInBits() >= SizeInBits) { 955 Observer.changingInstr(MI); 956 // We don't lose any non-extension bits by truncating the src and 957 // sign-extending the dst. 958 MachineOperand &MO1 = MI.getOperand(1); 959 auto TruncMIB = MIRBuilder.buildTrunc(NarrowTy, MO1.getReg()); 960 MO1.setReg(TruncMIB->getOperand(0).getReg()); 961 962 MachineOperand &MO2 = MI.getOperand(0); 963 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy); 964 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 965 MIRBuilder.buildInstr(TargetOpcode::G_SEXT, {MO2.getReg()}, {DstExt}); 966 MO2.setReg(DstExt); 967 Observer.changedInstr(MI); 968 return Legalized; 969 } 970 971 // Break it apart. Components below the extension point are unmodified. The 972 // component containing the extension point becomes a narrower SEXT_INREG. 973 // Components above it are ashr'd from the component containing the 974 // extension point. 975 if (SizeOp0 % NarrowSize != 0) 976 return UnableToLegalize; 977 int NumParts = SizeOp0 / NarrowSize; 978 979 // List the registers where the destination will be scattered. 980 SmallVector<Register, 2> DstRegs; 981 // List the registers where the source will be split. 982 SmallVector<Register, 2> SrcRegs; 983 984 // Create all the temporary registers. 985 for (int i = 0; i < NumParts; ++i) { 986 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy); 987 988 SrcRegs.push_back(SrcReg); 989 } 990 991 // Explode the big arguments into smaller chunks. 992 MIRBuilder.buildUnmerge(SrcRegs, MI.getOperand(1).getReg()); 993 994 Register AshrCstReg = 995 MIRBuilder.buildConstant(NarrowTy, NarrowTy.getScalarSizeInBits() - 1) 996 ->getOperand(0) 997 .getReg(); 998 Register FullExtensionReg = 0; 999 Register PartialExtensionReg = 0; 1000 1001 // Do the operation on each small part. 1002 for (int i = 0; i < NumParts; ++i) { 1003 if ((i + 1) * NarrowTy.getScalarSizeInBits() < SizeInBits) 1004 DstRegs.push_back(SrcRegs[i]); 1005 else if (i * NarrowTy.getScalarSizeInBits() > SizeInBits) { 1006 assert(PartialExtensionReg && 1007 "Expected to visit partial extension before full"); 1008 if (FullExtensionReg) { 1009 DstRegs.push_back(FullExtensionReg); 1010 continue; 1011 } 1012 DstRegs.push_back(MIRBuilder 1013 .buildInstr(TargetOpcode::G_ASHR, {NarrowTy}, 1014 {PartialExtensionReg, AshrCstReg}) 1015 ->getOperand(0) 1016 .getReg()); 1017 FullExtensionReg = DstRegs.back(); 1018 } else { 1019 DstRegs.push_back( 1020 MIRBuilder 1021 .buildInstr( 1022 TargetOpcode::G_SEXT_INREG, {NarrowTy}, 1023 {SrcRegs[i], SizeInBits % NarrowTy.getScalarSizeInBits()}) 1024 ->getOperand(0) 1025 .getReg()); 1026 PartialExtensionReg = DstRegs.back(); 1027 } 1028 } 1029 1030 // Gather the destination registers into the final destination. 1031 Register DstReg = MI.getOperand(0).getReg(); 1032 MIRBuilder.buildMerge(DstReg, DstRegs); 1033 MI.eraseFromParent(); 1034 return Legalized; 1035 } 1036 } 1037 } 1038 1039 void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy, 1040 unsigned OpIdx, unsigned ExtOpcode) { 1041 MachineOperand &MO = MI.getOperand(OpIdx); 1042 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()}); 1043 MO.setReg(ExtB->getOperand(0).getReg()); 1044 } 1045 1046 void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, 1047 unsigned OpIdx) { 1048 MachineOperand &MO = MI.getOperand(OpIdx); 1049 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy}, 1050 {MO.getReg()}); 1051 MO.setReg(ExtB->getOperand(0).getReg()); 1052 } 1053 1054 void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy, 1055 unsigned OpIdx, unsigned TruncOpcode) { 1056 MachineOperand &MO = MI.getOperand(OpIdx); 1057 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 1058 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1059 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt}); 1060 MO.setReg(DstExt); 1061 } 1062 1063 void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy, 1064 unsigned OpIdx, unsigned ExtOpcode) { 1065 MachineOperand &MO = MI.getOperand(OpIdx); 1066 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy); 1067 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1068 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc}); 1069 MO.setReg(DstTrunc); 1070 } 1071 1072 void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy, 1073 unsigned OpIdx) { 1074 MachineOperand &MO = MI.getOperand(OpIdx); 1075 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 1076 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1077 MIRBuilder.buildExtract(MO.getReg(), DstExt, 0); 1078 MO.setReg(DstExt); 1079 } 1080 1081 void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, 1082 unsigned OpIdx) { 1083 MachineOperand &MO = MI.getOperand(OpIdx); 1084 1085 LLT OldTy = MRI.getType(MO.getReg()); 1086 unsigned OldElts = OldTy.getNumElements(); 1087 unsigned NewElts = MoreTy.getNumElements(); 1088 1089 unsigned NumParts = NewElts / OldElts; 1090 1091 // Use concat_vectors if the result is a multiple of the number of elements. 1092 if (NumParts * OldElts == NewElts) { 1093 SmallVector<Register, 8> Parts; 1094 Parts.push_back(MO.getReg()); 1095 1096 Register ImpDef = MIRBuilder.buildUndef(OldTy).getReg(0); 1097 for (unsigned I = 1; I != NumParts; ++I) 1098 Parts.push_back(ImpDef); 1099 1100 auto Concat = MIRBuilder.buildConcatVectors(MoreTy, Parts); 1101 MO.setReg(Concat.getReg(0)); 1102 return; 1103 } 1104 1105 Register MoreReg = MRI.createGenericVirtualRegister(MoreTy); 1106 Register ImpDef = MIRBuilder.buildUndef(MoreTy).getReg(0); 1107 MIRBuilder.buildInsert(MoreReg, ImpDef, MO.getReg(), 0); 1108 MO.setReg(MoreReg); 1109 } 1110 1111 LegalizerHelper::LegalizeResult 1112 LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, 1113 LLT WideTy) { 1114 if (TypeIdx != 1) 1115 return UnableToLegalize; 1116 1117 Register DstReg = MI.getOperand(0).getReg(); 1118 LLT DstTy = MRI.getType(DstReg); 1119 if (DstTy.isVector()) 1120 return UnableToLegalize; 1121 1122 Register Src1 = MI.getOperand(1).getReg(); 1123 LLT SrcTy = MRI.getType(Src1); 1124 const int DstSize = DstTy.getSizeInBits(); 1125 const int SrcSize = SrcTy.getSizeInBits(); 1126 const int WideSize = WideTy.getSizeInBits(); 1127 const int NumMerge = (DstSize + WideSize - 1) / WideSize; 1128 1129 unsigned NumOps = MI.getNumOperands(); 1130 unsigned NumSrc = MI.getNumOperands() - 1; 1131 unsigned PartSize = DstTy.getSizeInBits() / NumSrc; 1132 1133 if (WideSize >= DstSize) { 1134 // Directly pack the bits in the target type. 1135 Register ResultReg = MIRBuilder.buildZExt(WideTy, Src1).getReg(0); 1136 1137 for (unsigned I = 2; I != NumOps; ++I) { 1138 const unsigned Offset = (I - 1) * PartSize; 1139 1140 Register SrcReg = MI.getOperand(I).getReg(); 1141 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize)); 1142 1143 auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg); 1144 1145 Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg : 1146 MRI.createGenericVirtualRegister(WideTy); 1147 1148 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset); 1149 auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt); 1150 MIRBuilder.buildOr(NextResult, ResultReg, Shl); 1151 ResultReg = NextResult; 1152 } 1153 1154 if (WideSize > DstSize) 1155 MIRBuilder.buildTrunc(DstReg, ResultReg); 1156 else if (DstTy.isPointer()) 1157 MIRBuilder.buildIntToPtr(DstReg, ResultReg); 1158 1159 MI.eraseFromParent(); 1160 return Legalized; 1161 } 1162 1163 // Unmerge the original values to the GCD type, and recombine to the next 1164 // multiple greater than the original type. 1165 // 1166 // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6 1167 // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0 1168 // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1 1169 // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2 1170 // %10:_(s6) = G_MERGE_VALUES %4, %5, %6 1171 // %11:_(s6) = G_MERGE_VALUES %7, %8, %9 1172 // %12:_(s12) = G_MERGE_VALUES %10, %11 1173 // 1174 // Padding with undef if necessary: 1175 // 1176 // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6 1177 // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0 1178 // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1 1179 // %7:_(s2) = G_IMPLICIT_DEF 1180 // %8:_(s6) = G_MERGE_VALUES %3, %4, %5 1181 // %9:_(s6) = G_MERGE_VALUES %6, %7, %7 1182 // %10:_(s12) = G_MERGE_VALUES %8, %9 1183 1184 const int GCD = greatestCommonDivisor(SrcSize, WideSize); 1185 LLT GCDTy = LLT::scalar(GCD); 1186 1187 SmallVector<Register, 8> Parts; 1188 SmallVector<Register, 8> NewMergeRegs; 1189 SmallVector<Register, 8> Unmerges; 1190 LLT WideDstTy = LLT::scalar(NumMerge * WideSize); 1191 1192 // Decompose the original operands if they don't evenly divide. 1193 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) { 1194 Register SrcReg = MI.getOperand(I).getReg(); 1195 if (GCD == SrcSize) { 1196 Unmerges.push_back(SrcReg); 1197 } else { 1198 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg); 1199 for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J) 1200 Unmerges.push_back(Unmerge.getReg(J)); 1201 } 1202 } 1203 1204 // Pad with undef to the next size that is a multiple of the requested size. 1205 if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) { 1206 Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0); 1207 for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I) 1208 Unmerges.push_back(UndefReg); 1209 } 1210 1211 const int PartsPerGCD = WideSize / GCD; 1212 1213 // Build merges of each piece. 1214 ArrayRef<Register> Slicer(Unmerges); 1215 for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) { 1216 auto Merge = MIRBuilder.buildMerge(WideTy, Slicer.take_front(PartsPerGCD)); 1217 NewMergeRegs.push_back(Merge.getReg(0)); 1218 } 1219 1220 // A truncate may be necessary if the requested type doesn't evenly divide the 1221 // original result type. 1222 if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) { 1223 MIRBuilder.buildMerge(DstReg, NewMergeRegs); 1224 } else { 1225 auto FinalMerge = MIRBuilder.buildMerge(WideDstTy, NewMergeRegs); 1226 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0)); 1227 } 1228 1229 MI.eraseFromParent(); 1230 return Legalized; 1231 } 1232 1233 LegalizerHelper::LegalizeResult 1234 LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, 1235 LLT WideTy) { 1236 if (TypeIdx != 0) 1237 return UnableToLegalize; 1238 1239 unsigned NumDst = MI.getNumOperands() - 1; 1240 Register SrcReg = MI.getOperand(NumDst).getReg(); 1241 LLT SrcTy = MRI.getType(SrcReg); 1242 if (!SrcTy.isScalar()) 1243 return UnableToLegalize; 1244 1245 Register Dst0Reg = MI.getOperand(0).getReg(); 1246 LLT DstTy = MRI.getType(Dst0Reg); 1247 if (!DstTy.isScalar()) 1248 return UnableToLegalize; 1249 1250 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits(); 1251 LLT NewSrcTy = LLT::scalar(NewSrcSize); 1252 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits(); 1253 1254 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg); 1255 1256 for (unsigned I = 1; I != NumDst; ++I) { 1257 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I); 1258 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt); 1259 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl); 1260 } 1261 1262 Observer.changingInstr(MI); 1263 1264 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg()); 1265 for (unsigned I = 0; I != NumDst; ++I) 1266 widenScalarDst(MI, WideTy, I); 1267 1268 Observer.changedInstr(MI); 1269 1270 return Legalized; 1271 } 1272 1273 LegalizerHelper::LegalizeResult 1274 LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, 1275 LLT WideTy) { 1276 Register DstReg = MI.getOperand(0).getReg(); 1277 Register SrcReg = MI.getOperand(1).getReg(); 1278 LLT SrcTy = MRI.getType(SrcReg); 1279 1280 LLT DstTy = MRI.getType(DstReg); 1281 unsigned Offset = MI.getOperand(2).getImm(); 1282 1283 if (TypeIdx == 0) { 1284 if (SrcTy.isVector() || DstTy.isVector()) 1285 return UnableToLegalize; 1286 1287 SrcOp Src(SrcReg); 1288 if (SrcTy.isPointer()) { 1289 // Extracts from pointers can be handled only if they are really just 1290 // simple integers. 1291 const DataLayout &DL = MIRBuilder.getDataLayout(); 1292 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) 1293 return UnableToLegalize; 1294 1295 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits()); 1296 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src); 1297 SrcTy = SrcAsIntTy; 1298 } 1299 1300 if (DstTy.isPointer()) 1301 return UnableToLegalize; 1302 1303 if (Offset == 0) { 1304 // Avoid a shift in the degenerate case. 1305 MIRBuilder.buildTrunc(DstReg, 1306 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src)); 1307 MI.eraseFromParent(); 1308 return Legalized; 1309 } 1310 1311 // Do a shift in the source type. 1312 LLT ShiftTy = SrcTy; 1313 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) { 1314 Src = MIRBuilder.buildAnyExt(WideTy, Src); 1315 ShiftTy = WideTy; 1316 } else if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) 1317 return UnableToLegalize; 1318 1319 auto LShr = MIRBuilder.buildLShr( 1320 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset)); 1321 MIRBuilder.buildTrunc(DstReg, LShr); 1322 MI.eraseFromParent(); 1323 return Legalized; 1324 } 1325 1326 if (SrcTy.isScalar()) { 1327 Observer.changingInstr(MI); 1328 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1329 Observer.changedInstr(MI); 1330 return Legalized; 1331 } 1332 1333 if (!SrcTy.isVector()) 1334 return UnableToLegalize; 1335 1336 if (DstTy != SrcTy.getElementType()) 1337 return UnableToLegalize; 1338 1339 if (Offset % SrcTy.getScalarSizeInBits() != 0) 1340 return UnableToLegalize; 1341 1342 Observer.changingInstr(MI); 1343 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1344 1345 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) * 1346 Offset); 1347 widenScalarDst(MI, WideTy.getScalarType(), 0); 1348 Observer.changedInstr(MI); 1349 return Legalized; 1350 } 1351 1352 LegalizerHelper::LegalizeResult 1353 LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, 1354 LLT WideTy) { 1355 if (TypeIdx != 0) 1356 return UnableToLegalize; 1357 Observer.changingInstr(MI); 1358 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1359 widenScalarDst(MI, WideTy); 1360 Observer.changedInstr(MI); 1361 return Legalized; 1362 } 1363 1364 LegalizerHelper::LegalizeResult 1365 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 1366 MIRBuilder.setInstr(MI); 1367 1368 switch (MI.getOpcode()) { 1369 default: 1370 return UnableToLegalize; 1371 case TargetOpcode::G_EXTRACT: 1372 return widenScalarExtract(MI, TypeIdx, WideTy); 1373 case TargetOpcode::G_INSERT: 1374 return widenScalarInsert(MI, TypeIdx, WideTy); 1375 case TargetOpcode::G_MERGE_VALUES: 1376 return widenScalarMergeValues(MI, TypeIdx, WideTy); 1377 case TargetOpcode::G_UNMERGE_VALUES: 1378 return widenScalarUnmergeValues(MI, TypeIdx, WideTy); 1379 case TargetOpcode::G_UADDO: 1380 case TargetOpcode::G_USUBO: { 1381 if (TypeIdx == 1) 1382 return UnableToLegalize; // TODO 1383 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy}, 1384 {MI.getOperand(2).getReg()}); 1385 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy}, 1386 {MI.getOperand(3).getReg()}); 1387 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO 1388 ? TargetOpcode::G_ADD 1389 : TargetOpcode::G_SUB; 1390 // Do the arithmetic in the larger type. 1391 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext}); 1392 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg()); 1393 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits()); 1394 auto AndOp = MIRBuilder.buildInstr( 1395 TargetOpcode::G_AND, {WideTy}, 1396 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())}); 1397 // There is no overflow if the AndOp is the same as NewOp. 1398 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp, 1399 AndOp); 1400 // Now trunc the NewOp to the original result. 1401 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp); 1402 MI.eraseFromParent(); 1403 return Legalized; 1404 } 1405 case TargetOpcode::G_CTTZ: 1406 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 1407 case TargetOpcode::G_CTLZ: 1408 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 1409 case TargetOpcode::G_CTPOP: { 1410 if (TypeIdx == 0) { 1411 Observer.changingInstr(MI); 1412 widenScalarDst(MI, WideTy, 0); 1413 Observer.changedInstr(MI); 1414 return Legalized; 1415 } 1416 1417 Register SrcReg = MI.getOperand(1).getReg(); 1418 1419 // First ZEXT the input. 1420 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg); 1421 LLT CurTy = MRI.getType(SrcReg); 1422 if (MI.getOpcode() == TargetOpcode::G_CTTZ) { 1423 // The count is the same in the larger type except if the original 1424 // value was zero. This can be handled by setting the bit just off 1425 // the top of the original type. 1426 auto TopBit = 1427 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits()); 1428 MIBSrc = MIRBuilder.buildOr( 1429 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit)); 1430 } 1431 1432 // Perform the operation at the larger size. 1433 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc}); 1434 // This is already the correct result for CTPOP and CTTZs 1435 if (MI.getOpcode() == TargetOpcode::G_CTLZ || 1436 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) { 1437 // The correct result is NewOp - (Difference in widety and current ty). 1438 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits(); 1439 MIBNewOp = MIRBuilder.buildInstr( 1440 TargetOpcode::G_SUB, {WideTy}, 1441 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)}); 1442 } 1443 1444 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp); 1445 MI.eraseFromParent(); 1446 return Legalized; 1447 } 1448 case TargetOpcode::G_BSWAP: { 1449 Observer.changingInstr(MI); 1450 Register DstReg = MI.getOperand(0).getReg(); 1451 1452 Register ShrReg = MRI.createGenericVirtualRegister(WideTy); 1453 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 1454 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy); 1455 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1456 1457 MI.getOperand(0).setReg(DstExt); 1458 1459 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1460 1461 LLT Ty = MRI.getType(DstReg); 1462 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits(); 1463 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits); 1464 MIRBuilder.buildInstr(TargetOpcode::G_LSHR) 1465 .addDef(ShrReg) 1466 .addUse(DstExt) 1467 .addUse(ShiftAmtReg); 1468 1469 MIRBuilder.buildTrunc(DstReg, ShrReg); 1470 Observer.changedInstr(MI); 1471 return Legalized; 1472 } 1473 case TargetOpcode::G_BITREVERSE: { 1474 Observer.changingInstr(MI); 1475 1476 Register DstReg = MI.getOperand(0).getReg(); 1477 LLT Ty = MRI.getType(DstReg); 1478 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits(); 1479 1480 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 1481 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1482 MI.getOperand(0).setReg(DstExt); 1483 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1484 1485 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, DiffBits); 1486 auto Shift = MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt); 1487 MIRBuilder.buildTrunc(DstReg, Shift); 1488 Observer.changedInstr(MI); 1489 return Legalized; 1490 } 1491 case TargetOpcode::G_ADD: 1492 case TargetOpcode::G_AND: 1493 case TargetOpcode::G_MUL: 1494 case TargetOpcode::G_OR: 1495 case TargetOpcode::G_XOR: 1496 case TargetOpcode::G_SUB: 1497 // Perform operation at larger width (any extension is fines here, high bits 1498 // don't affect the result) and then truncate the result back to the 1499 // original type. 1500 Observer.changingInstr(MI); 1501 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1502 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 1503 widenScalarDst(MI, WideTy); 1504 Observer.changedInstr(MI); 1505 return Legalized; 1506 1507 case TargetOpcode::G_SHL: 1508 Observer.changingInstr(MI); 1509 1510 if (TypeIdx == 0) { 1511 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1512 widenScalarDst(MI, WideTy); 1513 } else { 1514 assert(TypeIdx == 1); 1515 // The "number of bits to shift" operand must preserve its value as an 1516 // unsigned integer: 1517 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 1518 } 1519 1520 Observer.changedInstr(MI); 1521 return Legalized; 1522 1523 case TargetOpcode::G_SDIV: 1524 case TargetOpcode::G_SREM: 1525 case TargetOpcode::G_SMIN: 1526 case TargetOpcode::G_SMAX: 1527 Observer.changingInstr(MI); 1528 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 1529 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 1530 widenScalarDst(MI, WideTy); 1531 Observer.changedInstr(MI); 1532 return Legalized; 1533 1534 case TargetOpcode::G_ASHR: 1535 case TargetOpcode::G_LSHR: 1536 Observer.changingInstr(MI); 1537 1538 if (TypeIdx == 0) { 1539 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ? 1540 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT; 1541 1542 widenScalarSrc(MI, WideTy, 1, CvtOp); 1543 widenScalarDst(MI, WideTy); 1544 } else { 1545 assert(TypeIdx == 1); 1546 // The "number of bits to shift" operand must preserve its value as an 1547 // unsigned integer: 1548 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 1549 } 1550 1551 Observer.changedInstr(MI); 1552 return Legalized; 1553 case TargetOpcode::G_UDIV: 1554 case TargetOpcode::G_UREM: 1555 case TargetOpcode::G_UMIN: 1556 case TargetOpcode::G_UMAX: 1557 Observer.changingInstr(MI); 1558 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 1559 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 1560 widenScalarDst(MI, WideTy); 1561 Observer.changedInstr(MI); 1562 return Legalized; 1563 1564 case TargetOpcode::G_SELECT: 1565 Observer.changingInstr(MI); 1566 if (TypeIdx == 0) { 1567 // Perform operation at larger width (any extension is fine here, high 1568 // bits don't affect the result) and then truncate the result back to the 1569 // original type. 1570 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 1571 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT); 1572 widenScalarDst(MI, WideTy); 1573 } else { 1574 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector(); 1575 // Explicit extension is required here since high bits affect the result. 1576 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false)); 1577 } 1578 Observer.changedInstr(MI); 1579 return Legalized; 1580 1581 case TargetOpcode::G_FPTOSI: 1582 case TargetOpcode::G_FPTOUI: 1583 if (TypeIdx != 0) 1584 return UnableToLegalize; 1585 Observer.changingInstr(MI); 1586 widenScalarDst(MI, WideTy); 1587 Observer.changedInstr(MI); 1588 return Legalized; 1589 1590 case TargetOpcode::G_SITOFP: 1591 if (TypeIdx != 1) 1592 return UnableToLegalize; 1593 Observer.changingInstr(MI); 1594 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 1595 Observer.changedInstr(MI); 1596 return Legalized; 1597 1598 case TargetOpcode::G_UITOFP: 1599 if (TypeIdx != 1) 1600 return UnableToLegalize; 1601 Observer.changingInstr(MI); 1602 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 1603 Observer.changedInstr(MI); 1604 return Legalized; 1605 1606 case TargetOpcode::G_LOAD: 1607 case TargetOpcode::G_SEXTLOAD: 1608 case TargetOpcode::G_ZEXTLOAD: 1609 Observer.changingInstr(MI); 1610 widenScalarDst(MI, WideTy); 1611 Observer.changedInstr(MI); 1612 return Legalized; 1613 1614 case TargetOpcode::G_STORE: { 1615 if (TypeIdx != 0) 1616 return UnableToLegalize; 1617 1618 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 1619 if (!isPowerOf2_32(Ty.getSizeInBits())) 1620 return UnableToLegalize; 1621 1622 Observer.changingInstr(MI); 1623 1624 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ? 1625 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT; 1626 widenScalarSrc(MI, WideTy, 0, ExtType); 1627 1628 Observer.changedInstr(MI); 1629 return Legalized; 1630 } 1631 case TargetOpcode::G_CONSTANT: { 1632 MachineOperand &SrcMO = MI.getOperand(1); 1633 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 1634 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits()); 1635 Observer.changingInstr(MI); 1636 SrcMO.setCImm(ConstantInt::get(Ctx, Val)); 1637 1638 widenScalarDst(MI, WideTy); 1639 Observer.changedInstr(MI); 1640 return Legalized; 1641 } 1642 case TargetOpcode::G_FCONSTANT: { 1643 MachineOperand &SrcMO = MI.getOperand(1); 1644 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 1645 APFloat Val = SrcMO.getFPImm()->getValueAPF(); 1646 bool LosesInfo; 1647 switch (WideTy.getSizeInBits()) { 1648 case 32: 1649 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, 1650 &LosesInfo); 1651 break; 1652 case 64: 1653 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, 1654 &LosesInfo); 1655 break; 1656 default: 1657 return UnableToLegalize; 1658 } 1659 1660 assert(!LosesInfo && "extend should always be lossless"); 1661 1662 Observer.changingInstr(MI); 1663 SrcMO.setFPImm(ConstantFP::get(Ctx, Val)); 1664 1665 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 1666 Observer.changedInstr(MI); 1667 return Legalized; 1668 } 1669 case TargetOpcode::G_IMPLICIT_DEF: { 1670 Observer.changingInstr(MI); 1671 widenScalarDst(MI, WideTy); 1672 Observer.changedInstr(MI); 1673 return Legalized; 1674 } 1675 case TargetOpcode::G_BRCOND: 1676 Observer.changingInstr(MI); 1677 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false)); 1678 Observer.changedInstr(MI); 1679 return Legalized; 1680 1681 case TargetOpcode::G_FCMP: 1682 Observer.changingInstr(MI); 1683 if (TypeIdx == 0) 1684 widenScalarDst(MI, WideTy); 1685 else { 1686 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT); 1687 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT); 1688 } 1689 Observer.changedInstr(MI); 1690 return Legalized; 1691 1692 case TargetOpcode::G_ICMP: 1693 Observer.changingInstr(MI); 1694 if (TypeIdx == 0) 1695 widenScalarDst(MI, WideTy); 1696 else { 1697 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>( 1698 MI.getOperand(1).getPredicate())) 1699 ? TargetOpcode::G_SEXT 1700 : TargetOpcode::G_ZEXT; 1701 widenScalarSrc(MI, WideTy, 2, ExtOpcode); 1702 widenScalarSrc(MI, WideTy, 3, ExtOpcode); 1703 } 1704 Observer.changedInstr(MI); 1705 return Legalized; 1706 1707 case TargetOpcode::G_GEP: 1708 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 1709 Observer.changingInstr(MI); 1710 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 1711 Observer.changedInstr(MI); 1712 return Legalized; 1713 1714 case TargetOpcode::G_PHI: { 1715 assert(TypeIdx == 0 && "Expecting only Idx 0"); 1716 1717 Observer.changingInstr(MI); 1718 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) { 1719 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB(); 1720 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 1721 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT); 1722 } 1723 1724 MachineBasicBlock &MBB = *MI.getParent(); 1725 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI()); 1726 widenScalarDst(MI, WideTy); 1727 Observer.changedInstr(MI); 1728 return Legalized; 1729 } 1730 case TargetOpcode::G_EXTRACT_VECTOR_ELT: { 1731 if (TypeIdx == 0) { 1732 Register VecReg = MI.getOperand(1).getReg(); 1733 LLT VecTy = MRI.getType(VecReg); 1734 Observer.changingInstr(MI); 1735 1736 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(), 1737 WideTy.getSizeInBits()), 1738 1, TargetOpcode::G_SEXT); 1739 1740 widenScalarDst(MI, WideTy, 0); 1741 Observer.changedInstr(MI); 1742 return Legalized; 1743 } 1744 1745 if (TypeIdx != 2) 1746 return UnableToLegalize; 1747 Observer.changingInstr(MI); 1748 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 1749 Observer.changedInstr(MI); 1750 return Legalized; 1751 } 1752 case TargetOpcode::G_FADD: 1753 case TargetOpcode::G_FMUL: 1754 case TargetOpcode::G_FSUB: 1755 case TargetOpcode::G_FMA: 1756 case TargetOpcode::G_FMAD: 1757 case TargetOpcode::G_FNEG: 1758 case TargetOpcode::G_FABS: 1759 case TargetOpcode::G_FCANONICALIZE: 1760 case TargetOpcode::G_FMINNUM: 1761 case TargetOpcode::G_FMAXNUM: 1762 case TargetOpcode::G_FMINNUM_IEEE: 1763 case TargetOpcode::G_FMAXNUM_IEEE: 1764 case TargetOpcode::G_FMINIMUM: 1765 case TargetOpcode::G_FMAXIMUM: 1766 case TargetOpcode::G_FDIV: 1767 case TargetOpcode::G_FREM: 1768 case TargetOpcode::G_FCEIL: 1769 case TargetOpcode::G_FFLOOR: 1770 case TargetOpcode::G_FCOS: 1771 case TargetOpcode::G_FSIN: 1772 case TargetOpcode::G_FLOG10: 1773 case TargetOpcode::G_FLOG: 1774 case TargetOpcode::G_FLOG2: 1775 case TargetOpcode::G_FRINT: 1776 case TargetOpcode::G_FNEARBYINT: 1777 case TargetOpcode::G_FSQRT: 1778 case TargetOpcode::G_FEXP: 1779 case TargetOpcode::G_FEXP2: 1780 case TargetOpcode::G_FPOW: 1781 case TargetOpcode::G_INTRINSIC_TRUNC: 1782 case TargetOpcode::G_INTRINSIC_ROUND: 1783 assert(TypeIdx == 0); 1784 Observer.changingInstr(MI); 1785 1786 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) 1787 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT); 1788 1789 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 1790 Observer.changedInstr(MI); 1791 return Legalized; 1792 case TargetOpcode::G_INTTOPTR: 1793 if (TypeIdx != 1) 1794 return UnableToLegalize; 1795 1796 Observer.changingInstr(MI); 1797 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 1798 Observer.changedInstr(MI); 1799 return Legalized; 1800 case TargetOpcode::G_PTRTOINT: 1801 if (TypeIdx != 0) 1802 return UnableToLegalize; 1803 1804 Observer.changingInstr(MI); 1805 widenScalarDst(MI, WideTy, 0); 1806 Observer.changedInstr(MI); 1807 return Legalized; 1808 case TargetOpcode::G_BUILD_VECTOR: { 1809 Observer.changingInstr(MI); 1810 1811 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType(); 1812 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) 1813 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT); 1814 1815 // Avoid changing the result vector type if the source element type was 1816 // requested. 1817 if (TypeIdx == 1) { 1818 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo(); 1819 MI.setDesc(TII.get(TargetOpcode::G_BUILD_VECTOR_TRUNC)); 1820 } else { 1821 widenScalarDst(MI, WideTy, 0); 1822 } 1823 1824 Observer.changedInstr(MI); 1825 return Legalized; 1826 } 1827 case TargetOpcode::G_SEXT_INREG: 1828 if (TypeIdx != 0) 1829 return UnableToLegalize; 1830 1831 Observer.changingInstr(MI); 1832 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1833 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_TRUNC); 1834 Observer.changedInstr(MI); 1835 return Legalized; 1836 } 1837 } 1838 1839 LegalizerHelper::LegalizeResult 1840 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 1841 using namespace TargetOpcode; 1842 MIRBuilder.setInstr(MI); 1843 1844 switch(MI.getOpcode()) { 1845 default: 1846 return UnableToLegalize; 1847 case TargetOpcode::G_SREM: 1848 case TargetOpcode::G_UREM: { 1849 Register QuotReg = MRI.createGenericVirtualRegister(Ty); 1850 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 1851 .addDef(QuotReg) 1852 .addUse(MI.getOperand(1).getReg()) 1853 .addUse(MI.getOperand(2).getReg()); 1854 1855 Register ProdReg = MRI.createGenericVirtualRegister(Ty); 1856 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 1857 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 1858 ProdReg); 1859 MI.eraseFromParent(); 1860 return Legalized; 1861 } 1862 case TargetOpcode::G_SMULO: 1863 case TargetOpcode::G_UMULO: { 1864 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 1865 // result. 1866 Register Res = MI.getOperand(0).getReg(); 1867 Register Overflow = MI.getOperand(1).getReg(); 1868 Register LHS = MI.getOperand(2).getReg(); 1869 Register RHS = MI.getOperand(3).getReg(); 1870 1871 MIRBuilder.buildMul(Res, LHS, RHS); 1872 1873 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 1874 ? TargetOpcode::G_SMULH 1875 : TargetOpcode::G_UMULH; 1876 1877 Register HiPart = MRI.createGenericVirtualRegister(Ty); 1878 MIRBuilder.buildInstr(Opcode) 1879 .addDef(HiPart) 1880 .addUse(LHS) 1881 .addUse(RHS); 1882 1883 Register Zero = MRI.createGenericVirtualRegister(Ty); 1884 MIRBuilder.buildConstant(Zero, 0); 1885 1886 // For *signed* multiply, overflow is detected by checking: 1887 // (hi != (lo >> bitwidth-1)) 1888 if (Opcode == TargetOpcode::G_SMULH) { 1889 Register Shifted = MRI.createGenericVirtualRegister(Ty); 1890 Register ShiftAmt = MRI.createGenericVirtualRegister(Ty); 1891 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1); 1892 MIRBuilder.buildInstr(TargetOpcode::G_ASHR) 1893 .addDef(Shifted) 1894 .addUse(Res) 1895 .addUse(ShiftAmt); 1896 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted); 1897 } else { 1898 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 1899 } 1900 MI.eraseFromParent(); 1901 return Legalized; 1902 } 1903 case TargetOpcode::G_FNEG: { 1904 // TODO: Handle vector types once we are able to 1905 // represent them. 1906 if (Ty.isVector()) 1907 return UnableToLegalize; 1908 Register Res = MI.getOperand(0).getReg(); 1909 Type *ZeroTy; 1910 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 1911 switch (Ty.getSizeInBits()) { 1912 case 16: 1913 ZeroTy = Type::getHalfTy(Ctx); 1914 break; 1915 case 32: 1916 ZeroTy = Type::getFloatTy(Ctx); 1917 break; 1918 case 64: 1919 ZeroTy = Type::getDoubleTy(Ctx); 1920 break; 1921 case 128: 1922 ZeroTy = Type::getFP128Ty(Ctx); 1923 break; 1924 default: 1925 llvm_unreachable("unexpected floating-point type"); 1926 } 1927 ConstantFP &ZeroForNegation = 1928 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); 1929 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation); 1930 Register SubByReg = MI.getOperand(1).getReg(); 1931 Register ZeroReg = Zero->getOperand(0).getReg(); 1932 MIRBuilder.buildInstr(TargetOpcode::G_FSUB, {Res}, {ZeroReg, SubByReg}, 1933 MI.getFlags()); 1934 MI.eraseFromParent(); 1935 return Legalized; 1936 } 1937 case TargetOpcode::G_FSUB: { 1938 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 1939 // First, check if G_FNEG is marked as Lower. If so, we may 1940 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 1941 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower) 1942 return UnableToLegalize; 1943 Register Res = MI.getOperand(0).getReg(); 1944 Register LHS = MI.getOperand(1).getReg(); 1945 Register RHS = MI.getOperand(2).getReg(); 1946 Register Neg = MRI.createGenericVirtualRegister(Ty); 1947 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); 1948 MIRBuilder.buildInstr(TargetOpcode::G_FADD, {Res}, {LHS, Neg}, MI.getFlags()); 1949 MI.eraseFromParent(); 1950 return Legalized; 1951 } 1952 case TargetOpcode::G_FMAD: 1953 return lowerFMad(MI); 1954 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { 1955 Register OldValRes = MI.getOperand(0).getReg(); 1956 Register SuccessRes = MI.getOperand(1).getReg(); 1957 Register Addr = MI.getOperand(2).getReg(); 1958 Register CmpVal = MI.getOperand(3).getReg(); 1959 Register NewVal = MI.getOperand(4).getReg(); 1960 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, 1961 **MI.memoperands_begin()); 1962 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); 1963 MI.eraseFromParent(); 1964 return Legalized; 1965 } 1966 case TargetOpcode::G_LOAD: 1967 case TargetOpcode::G_SEXTLOAD: 1968 case TargetOpcode::G_ZEXTLOAD: { 1969 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT 1970 Register DstReg = MI.getOperand(0).getReg(); 1971 Register PtrReg = MI.getOperand(1).getReg(); 1972 LLT DstTy = MRI.getType(DstReg); 1973 auto &MMO = **MI.memoperands_begin(); 1974 1975 if (DstTy.getSizeInBits() == MMO.getSizeInBits()) { 1976 if (MI.getOpcode() == TargetOpcode::G_LOAD) { 1977 // This load needs splitting into power of 2 sized loads. 1978 if (DstTy.isVector()) 1979 return UnableToLegalize; 1980 if (isPowerOf2_32(DstTy.getSizeInBits())) 1981 return UnableToLegalize; // Don't know what we're being asked to do. 1982 1983 // Our strategy here is to generate anyextending loads for the smaller 1984 // types up to next power-2 result type, and then combine the two larger 1985 // result values together, before truncating back down to the non-pow-2 1986 // type. 1987 // E.g. v1 = i24 load => 1988 // v2 = i32 load (2 byte) 1989 // v3 = i32 load (1 byte) 1990 // v4 = i32 shl v3, 16 1991 // v5 = i32 or v4, v2 1992 // v1 = i24 trunc v5 1993 // By doing this we generate the correct truncate which should get 1994 // combined away as an artifact with a matching extend. 1995 uint64_t LargeSplitSize = PowerOf2Floor(DstTy.getSizeInBits()); 1996 uint64_t SmallSplitSize = DstTy.getSizeInBits() - LargeSplitSize; 1997 1998 MachineFunction &MF = MIRBuilder.getMF(); 1999 MachineMemOperand *LargeMMO = 2000 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8); 2001 MachineMemOperand *SmallMMO = MF.getMachineMemOperand( 2002 &MMO, LargeSplitSize / 8, SmallSplitSize / 8); 2003 2004 LLT PtrTy = MRI.getType(PtrReg); 2005 unsigned AnyExtSize = NextPowerOf2(DstTy.getSizeInBits()); 2006 LLT AnyExtTy = LLT::scalar(AnyExtSize); 2007 Register LargeLdReg = MRI.createGenericVirtualRegister(AnyExtTy); 2008 Register SmallLdReg = MRI.createGenericVirtualRegister(AnyExtTy); 2009 auto LargeLoad = 2010 MIRBuilder.buildLoad(LargeLdReg, PtrReg, *LargeMMO); 2011 2012 auto OffsetCst = 2013 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8); 2014 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy); 2015 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0)); 2016 auto SmallLoad = MIRBuilder.buildLoad(SmallLdReg, SmallPtr.getReg(0), 2017 *SmallMMO); 2018 2019 auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize); 2020 auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt); 2021 auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad); 2022 MIRBuilder.buildTrunc(DstReg, {Or.getReg(0)}); 2023 MI.eraseFromParent(); 2024 return Legalized; 2025 } 2026 MIRBuilder.buildLoad(DstReg, PtrReg, MMO); 2027 MI.eraseFromParent(); 2028 return Legalized; 2029 } 2030 2031 if (DstTy.isScalar()) { 2032 Register TmpReg = 2033 MRI.createGenericVirtualRegister(LLT::scalar(MMO.getSizeInBits())); 2034 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); 2035 switch (MI.getOpcode()) { 2036 default: 2037 llvm_unreachable("Unexpected opcode"); 2038 case TargetOpcode::G_LOAD: 2039 MIRBuilder.buildAnyExt(DstReg, TmpReg); 2040 break; 2041 case TargetOpcode::G_SEXTLOAD: 2042 MIRBuilder.buildSExt(DstReg, TmpReg); 2043 break; 2044 case TargetOpcode::G_ZEXTLOAD: 2045 MIRBuilder.buildZExt(DstReg, TmpReg); 2046 break; 2047 } 2048 MI.eraseFromParent(); 2049 return Legalized; 2050 } 2051 2052 return UnableToLegalize; 2053 } 2054 case TargetOpcode::G_STORE: { 2055 // Lower a non-power of 2 store into multiple pow-2 stores. 2056 // E.g. split an i24 store into an i16 store + i8 store. 2057 // We do this by first extending the stored value to the next largest power 2058 // of 2 type, and then using truncating stores to store the components. 2059 // By doing this, likewise with G_LOAD, generate an extend that can be 2060 // artifact-combined away instead of leaving behind extracts. 2061 Register SrcReg = MI.getOperand(0).getReg(); 2062 Register PtrReg = MI.getOperand(1).getReg(); 2063 LLT SrcTy = MRI.getType(SrcReg); 2064 MachineMemOperand &MMO = **MI.memoperands_begin(); 2065 if (SrcTy.getSizeInBits() != MMO.getSizeInBits()) 2066 return UnableToLegalize; 2067 if (SrcTy.isVector()) 2068 return UnableToLegalize; 2069 if (isPowerOf2_32(SrcTy.getSizeInBits())) 2070 return UnableToLegalize; // Don't know what we're being asked to do. 2071 2072 // Extend to the next pow-2. 2073 const LLT ExtendTy = LLT::scalar(NextPowerOf2(SrcTy.getSizeInBits())); 2074 auto ExtVal = MIRBuilder.buildAnyExt(ExtendTy, SrcReg); 2075 2076 // Obtain the smaller value by shifting away the larger value. 2077 uint64_t LargeSplitSize = PowerOf2Floor(SrcTy.getSizeInBits()); 2078 uint64_t SmallSplitSize = SrcTy.getSizeInBits() - LargeSplitSize; 2079 auto ShiftAmt = MIRBuilder.buildConstant(ExtendTy, LargeSplitSize); 2080 auto SmallVal = MIRBuilder.buildLShr(ExtendTy, ExtVal, ShiftAmt); 2081 2082 // Generate the GEP and truncating stores. 2083 LLT PtrTy = MRI.getType(PtrReg); 2084 auto OffsetCst = 2085 MIRBuilder.buildConstant(LLT::scalar(64), LargeSplitSize / 8); 2086 Register GEPReg = MRI.createGenericVirtualRegister(PtrTy); 2087 auto SmallPtr = MIRBuilder.buildGEP(GEPReg, PtrReg, OffsetCst.getReg(0)); 2088 2089 MachineFunction &MF = MIRBuilder.getMF(); 2090 MachineMemOperand *LargeMMO = 2091 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8); 2092 MachineMemOperand *SmallMMO = 2093 MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8); 2094 MIRBuilder.buildStore(ExtVal.getReg(0), PtrReg, *LargeMMO); 2095 MIRBuilder.buildStore(SmallVal.getReg(0), SmallPtr.getReg(0), *SmallMMO); 2096 MI.eraseFromParent(); 2097 return Legalized; 2098 } 2099 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 2100 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 2101 case TargetOpcode::G_CTLZ: 2102 case TargetOpcode::G_CTTZ: 2103 case TargetOpcode::G_CTPOP: 2104 return lowerBitCount(MI, TypeIdx, Ty); 2105 case G_UADDO: { 2106 Register Res = MI.getOperand(0).getReg(); 2107 Register CarryOut = MI.getOperand(1).getReg(); 2108 Register LHS = MI.getOperand(2).getReg(); 2109 Register RHS = MI.getOperand(3).getReg(); 2110 2111 MIRBuilder.buildAdd(Res, LHS, RHS); 2112 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS); 2113 2114 MI.eraseFromParent(); 2115 return Legalized; 2116 } 2117 case G_UADDE: { 2118 Register Res = MI.getOperand(0).getReg(); 2119 Register CarryOut = MI.getOperand(1).getReg(); 2120 Register LHS = MI.getOperand(2).getReg(); 2121 Register RHS = MI.getOperand(3).getReg(); 2122 Register CarryIn = MI.getOperand(4).getReg(); 2123 2124 Register TmpRes = MRI.createGenericVirtualRegister(Ty); 2125 Register ZExtCarryIn = MRI.createGenericVirtualRegister(Ty); 2126 2127 MIRBuilder.buildAdd(TmpRes, LHS, RHS); 2128 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn); 2129 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn); 2130 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS); 2131 2132 MI.eraseFromParent(); 2133 return Legalized; 2134 } 2135 case G_USUBO: { 2136 Register Res = MI.getOperand(0).getReg(); 2137 Register BorrowOut = MI.getOperand(1).getReg(); 2138 Register LHS = MI.getOperand(2).getReg(); 2139 Register RHS = MI.getOperand(3).getReg(); 2140 2141 MIRBuilder.buildSub(Res, LHS, RHS); 2142 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS); 2143 2144 MI.eraseFromParent(); 2145 return Legalized; 2146 } 2147 case G_USUBE: { 2148 Register Res = MI.getOperand(0).getReg(); 2149 Register BorrowOut = MI.getOperand(1).getReg(); 2150 Register LHS = MI.getOperand(2).getReg(); 2151 Register RHS = MI.getOperand(3).getReg(); 2152 Register BorrowIn = MI.getOperand(4).getReg(); 2153 2154 Register TmpRes = MRI.createGenericVirtualRegister(Ty); 2155 Register ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty); 2156 Register LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1)); 2157 Register LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1)); 2158 2159 MIRBuilder.buildSub(TmpRes, LHS, RHS); 2160 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn); 2161 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn); 2162 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS); 2163 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS); 2164 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS); 2165 2166 MI.eraseFromParent(); 2167 return Legalized; 2168 } 2169 case G_UITOFP: 2170 return lowerUITOFP(MI, TypeIdx, Ty); 2171 case G_SITOFP: 2172 return lowerSITOFP(MI, TypeIdx, Ty); 2173 case G_FPTOUI: 2174 return lowerFPTOUI(MI, TypeIdx, Ty); 2175 case G_SMIN: 2176 case G_SMAX: 2177 case G_UMIN: 2178 case G_UMAX: 2179 return lowerMinMax(MI, TypeIdx, Ty); 2180 case G_FCOPYSIGN: 2181 return lowerFCopySign(MI, TypeIdx, Ty); 2182 case G_FMINNUM: 2183 case G_FMAXNUM: 2184 return lowerFMinNumMaxNum(MI); 2185 case G_UNMERGE_VALUES: 2186 return lowerUnmergeValues(MI); 2187 case TargetOpcode::G_SEXT_INREG: { 2188 assert(MI.getOperand(2).isImm() && "Expected immediate"); 2189 int64_t SizeInBits = MI.getOperand(2).getImm(); 2190 2191 Register DstReg = MI.getOperand(0).getReg(); 2192 Register SrcReg = MI.getOperand(1).getReg(); 2193 LLT DstTy = MRI.getType(DstReg); 2194 Register TmpRes = MRI.createGenericVirtualRegister(DstTy); 2195 2196 auto MIBSz = MIRBuilder.buildConstant(DstTy, DstTy.getScalarSizeInBits() - SizeInBits); 2197 MIRBuilder.buildInstr(TargetOpcode::G_SHL, {TmpRes}, {SrcReg, MIBSz->getOperand(0).getReg()}); 2198 MIRBuilder.buildInstr(TargetOpcode::G_ASHR, {DstReg}, {TmpRes, MIBSz->getOperand(0).getReg()}); 2199 MI.eraseFromParent(); 2200 return Legalized; 2201 } 2202 case G_SHUFFLE_VECTOR: 2203 return lowerShuffleVector(MI); 2204 case G_DYN_STACKALLOC: 2205 return lowerDynStackAlloc(MI); 2206 } 2207 } 2208 2209 LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef( 2210 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) { 2211 SmallVector<Register, 2> DstRegs; 2212 2213 unsigned NarrowSize = NarrowTy.getSizeInBits(); 2214 Register DstReg = MI.getOperand(0).getReg(); 2215 unsigned Size = MRI.getType(DstReg).getSizeInBits(); 2216 int NumParts = Size / NarrowSize; 2217 // FIXME: Don't know how to handle the situation where the small vectors 2218 // aren't all the same size yet. 2219 if (Size % NarrowSize != 0) 2220 return UnableToLegalize; 2221 2222 for (int i = 0; i < NumParts; ++i) { 2223 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 2224 MIRBuilder.buildUndef(TmpReg); 2225 DstRegs.push_back(TmpReg); 2226 } 2227 2228 if (NarrowTy.isVector()) 2229 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 2230 else 2231 MIRBuilder.buildBuildVector(DstReg, DstRegs); 2232 2233 MI.eraseFromParent(); 2234 return Legalized; 2235 } 2236 2237 LegalizerHelper::LegalizeResult 2238 LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx, 2239 LLT NarrowTy) { 2240 const unsigned Opc = MI.getOpcode(); 2241 const unsigned NumOps = MI.getNumOperands() - 1; 2242 const unsigned NarrowSize = NarrowTy.getSizeInBits(); 2243 const Register DstReg = MI.getOperand(0).getReg(); 2244 const unsigned Flags = MI.getFlags(); 2245 const LLT DstTy = MRI.getType(DstReg); 2246 const unsigned Size = DstTy.getSizeInBits(); 2247 const int NumParts = Size / NarrowSize; 2248 const LLT EltTy = DstTy.getElementType(); 2249 const unsigned EltSize = EltTy.getSizeInBits(); 2250 const unsigned BitsForNumParts = NarrowSize * NumParts; 2251 2252 // Check if we have any leftovers. If we do, then only handle the case where 2253 // the leftover is one element. 2254 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size) 2255 return UnableToLegalize; 2256 2257 if (BitsForNumParts != Size) { 2258 Register AccumDstReg = MRI.createGenericVirtualRegister(DstTy); 2259 MIRBuilder.buildUndef(AccumDstReg); 2260 2261 // Handle the pieces which evenly divide into the requested type with 2262 // extract/op/insert sequence. 2263 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) { 2264 SmallVector<SrcOp, 4> SrcOps; 2265 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) { 2266 Register PartOpReg = MRI.createGenericVirtualRegister(NarrowTy); 2267 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset); 2268 SrcOps.push_back(PartOpReg); 2269 } 2270 2271 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy); 2272 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags); 2273 2274 Register PartInsertReg = MRI.createGenericVirtualRegister(DstTy); 2275 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset); 2276 AccumDstReg = PartInsertReg; 2277 } 2278 2279 // Handle the remaining element sized leftover piece. 2280 SmallVector<SrcOp, 4> SrcOps; 2281 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) { 2282 Register PartOpReg = MRI.createGenericVirtualRegister(EltTy); 2283 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), 2284 BitsForNumParts); 2285 SrcOps.push_back(PartOpReg); 2286 } 2287 2288 Register PartDstReg = MRI.createGenericVirtualRegister(EltTy); 2289 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags); 2290 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts); 2291 MI.eraseFromParent(); 2292 2293 return Legalized; 2294 } 2295 2296 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs; 2297 2298 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs); 2299 2300 if (NumOps >= 2) 2301 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs); 2302 2303 if (NumOps >= 3) 2304 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs); 2305 2306 for (int i = 0; i < NumParts; ++i) { 2307 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); 2308 2309 if (NumOps == 1) 2310 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags); 2311 else if (NumOps == 2) { 2312 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags); 2313 } else if (NumOps == 3) { 2314 MIRBuilder.buildInstr(Opc, {DstReg}, 2315 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags); 2316 } 2317 2318 DstRegs.push_back(DstReg); 2319 } 2320 2321 if (NarrowTy.isVector()) 2322 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 2323 else 2324 MIRBuilder.buildBuildVector(DstReg, DstRegs); 2325 2326 MI.eraseFromParent(); 2327 return Legalized; 2328 } 2329 2330 // Handle splitting vector operations which need to have the same number of 2331 // elements in each type index, but each type index may have a different element 2332 // type. 2333 // 2334 // e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> -> 2335 // <2 x s64> = G_SHL <2 x s64>, <2 x s32> 2336 // <2 x s64> = G_SHL <2 x s64>, <2 x s32> 2337 // 2338 // Also handles some irregular breakdown cases, e.g. 2339 // e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> -> 2340 // <2 x s64> = G_SHL <2 x s64>, <2 x s32> 2341 // s64 = G_SHL s64, s32 2342 LegalizerHelper::LegalizeResult 2343 LegalizerHelper::fewerElementsVectorMultiEltType( 2344 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTyArg) { 2345 if (TypeIdx != 0) 2346 return UnableToLegalize; 2347 2348 const LLT NarrowTy0 = NarrowTyArg; 2349 const unsigned NewNumElts = 2350 NarrowTy0.isVector() ? NarrowTy0.getNumElements() : 1; 2351 2352 const Register DstReg = MI.getOperand(0).getReg(); 2353 LLT DstTy = MRI.getType(DstReg); 2354 LLT LeftoverTy0; 2355 2356 // All of the operands need to have the same number of elements, so if we can 2357 // determine a type breakdown for the result type, we can for all of the 2358 // source types. 2359 int NumParts = getNarrowTypeBreakDown(DstTy, NarrowTy0, LeftoverTy0).first; 2360 if (NumParts < 0) 2361 return UnableToLegalize; 2362 2363 SmallVector<MachineInstrBuilder, 4> NewInsts; 2364 2365 SmallVector<Register, 4> DstRegs, LeftoverDstRegs; 2366 SmallVector<Register, 4> PartRegs, LeftoverRegs; 2367 2368 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) { 2369 LLT LeftoverTy; 2370 Register SrcReg = MI.getOperand(I).getReg(); 2371 LLT SrcTyI = MRI.getType(SrcReg); 2372 LLT NarrowTyI = LLT::scalarOrVector(NewNumElts, SrcTyI.getScalarType()); 2373 LLT LeftoverTyI; 2374 2375 // Split this operand into the requested typed registers, and any leftover 2376 // required to reproduce the original type. 2377 if (!extractParts(SrcReg, SrcTyI, NarrowTyI, LeftoverTyI, PartRegs, 2378 LeftoverRegs)) 2379 return UnableToLegalize; 2380 2381 if (I == 1) { 2382 // For the first operand, create an instruction for each part and setup 2383 // the result. 2384 for (Register PartReg : PartRegs) { 2385 Register PartDstReg = MRI.createGenericVirtualRegister(NarrowTy0); 2386 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode()) 2387 .addDef(PartDstReg) 2388 .addUse(PartReg)); 2389 DstRegs.push_back(PartDstReg); 2390 } 2391 2392 for (Register LeftoverReg : LeftoverRegs) { 2393 Register PartDstReg = MRI.createGenericVirtualRegister(LeftoverTy0); 2394 NewInsts.push_back(MIRBuilder.buildInstrNoInsert(MI.getOpcode()) 2395 .addDef(PartDstReg) 2396 .addUse(LeftoverReg)); 2397 LeftoverDstRegs.push_back(PartDstReg); 2398 } 2399 } else { 2400 assert(NewInsts.size() == PartRegs.size() + LeftoverRegs.size()); 2401 2402 // Add the newly created operand splits to the existing instructions. The 2403 // odd-sized pieces are ordered after the requested NarrowTyArg sized 2404 // pieces. 2405 unsigned InstCount = 0; 2406 for (unsigned J = 0, JE = PartRegs.size(); J != JE; ++J) 2407 NewInsts[InstCount++].addUse(PartRegs[J]); 2408 for (unsigned J = 0, JE = LeftoverRegs.size(); J != JE; ++J) 2409 NewInsts[InstCount++].addUse(LeftoverRegs[J]); 2410 } 2411 2412 PartRegs.clear(); 2413 LeftoverRegs.clear(); 2414 } 2415 2416 // Insert the newly built operations and rebuild the result register. 2417 for (auto &MIB : NewInsts) 2418 MIRBuilder.insertInstr(MIB); 2419 2420 insertParts(DstReg, DstTy, NarrowTy0, DstRegs, LeftoverTy0, LeftoverDstRegs); 2421 2422 MI.eraseFromParent(); 2423 return Legalized; 2424 } 2425 2426 LegalizerHelper::LegalizeResult 2427 LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx, 2428 LLT NarrowTy) { 2429 if (TypeIdx != 0) 2430 return UnableToLegalize; 2431 2432 Register DstReg = MI.getOperand(0).getReg(); 2433 Register SrcReg = MI.getOperand(1).getReg(); 2434 LLT DstTy = MRI.getType(DstReg); 2435 LLT SrcTy = MRI.getType(SrcReg); 2436 2437 LLT NarrowTy0 = NarrowTy; 2438 LLT NarrowTy1; 2439 unsigned NumParts; 2440 2441 if (NarrowTy.isVector()) { 2442 // Uneven breakdown not handled. 2443 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements(); 2444 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements()) 2445 return UnableToLegalize; 2446 2447 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits()); 2448 } else { 2449 NumParts = DstTy.getNumElements(); 2450 NarrowTy1 = SrcTy.getElementType(); 2451 } 2452 2453 SmallVector<Register, 4> SrcRegs, DstRegs; 2454 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs); 2455 2456 for (unsigned I = 0; I < NumParts; ++I) { 2457 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0); 2458 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode()) 2459 .addDef(DstReg) 2460 .addUse(SrcRegs[I]); 2461 2462 NewInst->setFlags(MI.getFlags()); 2463 DstRegs.push_back(DstReg); 2464 } 2465 2466 if (NarrowTy.isVector()) 2467 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 2468 else 2469 MIRBuilder.buildBuildVector(DstReg, DstRegs); 2470 2471 MI.eraseFromParent(); 2472 return Legalized; 2473 } 2474 2475 LegalizerHelper::LegalizeResult 2476 LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, 2477 LLT NarrowTy) { 2478 Register DstReg = MI.getOperand(0).getReg(); 2479 Register Src0Reg = MI.getOperand(2).getReg(); 2480 LLT DstTy = MRI.getType(DstReg); 2481 LLT SrcTy = MRI.getType(Src0Reg); 2482 2483 unsigned NumParts; 2484 LLT NarrowTy0, NarrowTy1; 2485 2486 if (TypeIdx == 0) { 2487 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1; 2488 unsigned OldElts = DstTy.getNumElements(); 2489 2490 NarrowTy0 = NarrowTy; 2491 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements(); 2492 NarrowTy1 = NarrowTy.isVector() ? 2493 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) : 2494 SrcTy.getElementType(); 2495 2496 } else { 2497 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1; 2498 unsigned OldElts = SrcTy.getNumElements(); 2499 2500 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : 2501 NarrowTy.getNumElements(); 2502 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(), 2503 DstTy.getScalarSizeInBits()); 2504 NarrowTy1 = NarrowTy; 2505 } 2506 2507 // FIXME: Don't know how to handle the situation where the small vectors 2508 // aren't all the same size yet. 2509 if (NarrowTy1.isVector() && 2510 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements()) 2511 return UnableToLegalize; 2512 2513 CmpInst::Predicate Pred 2514 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()); 2515 2516 SmallVector<Register, 2> Src1Regs, Src2Regs, DstRegs; 2517 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs); 2518 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs); 2519 2520 for (unsigned I = 0; I < NumParts; ++I) { 2521 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0); 2522 DstRegs.push_back(DstReg); 2523 2524 if (MI.getOpcode() == TargetOpcode::G_ICMP) 2525 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]); 2526 else { 2527 MachineInstr *NewCmp 2528 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]); 2529 NewCmp->setFlags(MI.getFlags()); 2530 } 2531 } 2532 2533 if (NarrowTy1.isVector()) 2534 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 2535 else 2536 MIRBuilder.buildBuildVector(DstReg, DstRegs); 2537 2538 MI.eraseFromParent(); 2539 return Legalized; 2540 } 2541 2542 LegalizerHelper::LegalizeResult 2543 LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, 2544 LLT NarrowTy) { 2545 Register DstReg = MI.getOperand(0).getReg(); 2546 Register CondReg = MI.getOperand(1).getReg(); 2547 2548 unsigned NumParts = 0; 2549 LLT NarrowTy0, NarrowTy1; 2550 2551 LLT DstTy = MRI.getType(DstReg); 2552 LLT CondTy = MRI.getType(CondReg); 2553 unsigned Size = DstTy.getSizeInBits(); 2554 2555 assert(TypeIdx == 0 || CondTy.isVector()); 2556 2557 if (TypeIdx == 0) { 2558 NarrowTy0 = NarrowTy; 2559 NarrowTy1 = CondTy; 2560 2561 unsigned NarrowSize = NarrowTy0.getSizeInBits(); 2562 // FIXME: Don't know how to handle the situation where the small vectors 2563 // aren't all the same size yet. 2564 if (Size % NarrowSize != 0) 2565 return UnableToLegalize; 2566 2567 NumParts = Size / NarrowSize; 2568 2569 // Need to break down the condition type 2570 if (CondTy.isVector()) { 2571 if (CondTy.getNumElements() == NumParts) 2572 NarrowTy1 = CondTy.getElementType(); 2573 else 2574 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts, 2575 CondTy.getScalarSizeInBits()); 2576 } 2577 } else { 2578 NumParts = CondTy.getNumElements(); 2579 if (NarrowTy.isVector()) { 2580 // TODO: Handle uneven breakdown. 2581 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements()) 2582 return UnableToLegalize; 2583 2584 return UnableToLegalize; 2585 } else { 2586 NarrowTy0 = DstTy.getElementType(); 2587 NarrowTy1 = NarrowTy; 2588 } 2589 } 2590 2591 SmallVector<Register, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs; 2592 if (CondTy.isVector()) 2593 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs); 2594 2595 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs); 2596 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs); 2597 2598 for (unsigned i = 0; i < NumParts; ++i) { 2599 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy0); 2600 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg, 2601 Src1Regs[i], Src2Regs[i]); 2602 DstRegs.push_back(DstReg); 2603 } 2604 2605 if (NarrowTy0.isVector()) 2606 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 2607 else 2608 MIRBuilder.buildBuildVector(DstReg, DstRegs); 2609 2610 MI.eraseFromParent(); 2611 return Legalized; 2612 } 2613 2614 LegalizerHelper::LegalizeResult 2615 LegalizerHelper::fewerElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, 2616 LLT NarrowTy) { 2617 const Register DstReg = MI.getOperand(0).getReg(); 2618 LLT PhiTy = MRI.getType(DstReg); 2619 LLT LeftoverTy; 2620 2621 // All of the operands need to have the same number of elements, so if we can 2622 // determine a type breakdown for the result type, we can for all of the 2623 // source types. 2624 int NumParts, NumLeftover; 2625 std::tie(NumParts, NumLeftover) 2626 = getNarrowTypeBreakDown(PhiTy, NarrowTy, LeftoverTy); 2627 if (NumParts < 0) 2628 return UnableToLegalize; 2629 2630 SmallVector<Register, 4> DstRegs, LeftoverDstRegs; 2631 SmallVector<MachineInstrBuilder, 4> NewInsts; 2632 2633 const int TotalNumParts = NumParts + NumLeftover; 2634 2635 // Insert the new phis in the result block first. 2636 for (int I = 0; I != TotalNumParts; ++I) { 2637 LLT Ty = I < NumParts ? NarrowTy : LeftoverTy; 2638 Register PartDstReg = MRI.createGenericVirtualRegister(Ty); 2639 NewInsts.push_back(MIRBuilder.buildInstr(TargetOpcode::G_PHI) 2640 .addDef(PartDstReg)); 2641 if (I < NumParts) 2642 DstRegs.push_back(PartDstReg); 2643 else 2644 LeftoverDstRegs.push_back(PartDstReg); 2645 } 2646 2647 MachineBasicBlock *MBB = MI.getParent(); 2648 MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI()); 2649 insertParts(DstReg, PhiTy, NarrowTy, DstRegs, LeftoverTy, LeftoverDstRegs); 2650 2651 SmallVector<Register, 4> PartRegs, LeftoverRegs; 2652 2653 // Insert code to extract the incoming values in each predecessor block. 2654 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) { 2655 PartRegs.clear(); 2656 LeftoverRegs.clear(); 2657 2658 Register SrcReg = MI.getOperand(I).getReg(); 2659 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB(); 2660 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 2661 2662 LLT Unused; 2663 if (!extractParts(SrcReg, PhiTy, NarrowTy, Unused, PartRegs, 2664 LeftoverRegs)) 2665 return UnableToLegalize; 2666 2667 // Add the newly created operand splits to the existing instructions. The 2668 // odd-sized pieces are ordered after the requested NarrowTyArg sized 2669 // pieces. 2670 for (int J = 0; J != TotalNumParts; ++J) { 2671 MachineInstrBuilder MIB = NewInsts[J]; 2672 MIB.addUse(J < NumParts ? PartRegs[J] : LeftoverRegs[J - NumParts]); 2673 MIB.addMBB(&OpMBB); 2674 } 2675 } 2676 2677 MI.eraseFromParent(); 2678 return Legalized; 2679 } 2680 2681 LegalizerHelper::LegalizeResult 2682 LegalizerHelper::fewerElementsVectorUnmergeValues(MachineInstr &MI, 2683 unsigned TypeIdx, 2684 LLT NarrowTy) { 2685 if (TypeIdx != 1) 2686 return UnableToLegalize; 2687 2688 const int NumDst = MI.getNumOperands() - 1; 2689 const Register SrcReg = MI.getOperand(NumDst).getReg(); 2690 LLT SrcTy = MRI.getType(SrcReg); 2691 2692 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 2693 2694 // TODO: Create sequence of extracts. 2695 if (DstTy == NarrowTy) 2696 return UnableToLegalize; 2697 2698 LLT GCDTy = getGCDType(SrcTy, NarrowTy); 2699 if (DstTy == GCDTy) { 2700 // This would just be a copy of the same unmerge. 2701 // TODO: Create extracts, pad with undef and create intermediate merges. 2702 return UnableToLegalize; 2703 } 2704 2705 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg); 2706 const int NumUnmerge = Unmerge->getNumOperands() - 1; 2707 const int PartsPerUnmerge = NumDst / NumUnmerge; 2708 2709 for (int I = 0; I != NumUnmerge; ++I) { 2710 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES); 2711 2712 for (int J = 0; J != PartsPerUnmerge; ++J) 2713 MIB.addDef(MI.getOperand(I * PartsPerUnmerge + J).getReg()); 2714 MIB.addUse(Unmerge.getReg(I)); 2715 } 2716 2717 MI.eraseFromParent(); 2718 return Legalized; 2719 } 2720 2721 LegalizerHelper::LegalizeResult 2722 LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, 2723 LLT NarrowTy) { 2724 // FIXME: Don't know how to handle secondary types yet. 2725 if (TypeIdx != 0) 2726 return UnableToLegalize; 2727 2728 MachineMemOperand *MMO = *MI.memoperands_begin(); 2729 2730 // This implementation doesn't work for atomics. Give up instead of doing 2731 // something invalid. 2732 if (MMO->getOrdering() != AtomicOrdering::NotAtomic || 2733 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic) 2734 return UnableToLegalize; 2735 2736 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD; 2737 Register ValReg = MI.getOperand(0).getReg(); 2738 Register AddrReg = MI.getOperand(1).getReg(); 2739 LLT ValTy = MRI.getType(ValReg); 2740 2741 int NumParts = -1; 2742 int NumLeftover = -1; 2743 LLT LeftoverTy; 2744 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs; 2745 if (IsLoad) { 2746 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy); 2747 } else { 2748 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs, 2749 NarrowLeftoverRegs)) { 2750 NumParts = NarrowRegs.size(); 2751 NumLeftover = NarrowLeftoverRegs.size(); 2752 } 2753 } 2754 2755 if (NumParts == -1) 2756 return UnableToLegalize; 2757 2758 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits()); 2759 2760 unsigned TotalSize = ValTy.getSizeInBits(); 2761 2762 // Split the load/store into PartTy sized pieces starting at Offset. If this 2763 // is a load, return the new registers in ValRegs. For a store, each elements 2764 // of ValRegs should be PartTy. Returns the next offset that needs to be 2765 // handled. 2766 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs, 2767 unsigned Offset) -> unsigned { 2768 MachineFunction &MF = MIRBuilder.getMF(); 2769 unsigned PartSize = PartTy.getSizeInBits(); 2770 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize; 2771 Offset += PartSize, ++Idx) { 2772 unsigned ByteSize = PartSize / 8; 2773 unsigned ByteOffset = Offset / 8; 2774 Register NewAddrReg; 2775 2776 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset); 2777 2778 MachineMemOperand *NewMMO = 2779 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize); 2780 2781 if (IsLoad) { 2782 Register Dst = MRI.createGenericVirtualRegister(PartTy); 2783 ValRegs.push_back(Dst); 2784 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO); 2785 } else { 2786 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO); 2787 } 2788 } 2789 2790 return Offset; 2791 }; 2792 2793 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0); 2794 2795 // Handle the rest of the register if this isn't an even type breakdown. 2796 if (LeftoverTy.isValid()) 2797 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset); 2798 2799 if (IsLoad) { 2800 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs, 2801 LeftoverTy, NarrowLeftoverRegs); 2802 } 2803 2804 MI.eraseFromParent(); 2805 return Legalized; 2806 } 2807 2808 LegalizerHelper::LegalizeResult 2809 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 2810 LLT NarrowTy) { 2811 using namespace TargetOpcode; 2812 2813 MIRBuilder.setInstr(MI); 2814 switch (MI.getOpcode()) { 2815 case G_IMPLICIT_DEF: 2816 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy); 2817 case G_AND: 2818 case G_OR: 2819 case G_XOR: 2820 case G_ADD: 2821 case G_SUB: 2822 case G_MUL: 2823 case G_SMULH: 2824 case G_UMULH: 2825 case G_FADD: 2826 case G_FMUL: 2827 case G_FSUB: 2828 case G_FNEG: 2829 case G_FABS: 2830 case G_FCANONICALIZE: 2831 case G_FDIV: 2832 case G_FREM: 2833 case G_FMA: 2834 case G_FMAD: 2835 case G_FPOW: 2836 case G_FEXP: 2837 case G_FEXP2: 2838 case G_FLOG: 2839 case G_FLOG2: 2840 case G_FLOG10: 2841 case G_FNEARBYINT: 2842 case G_FCEIL: 2843 case G_FFLOOR: 2844 case G_FRINT: 2845 case G_INTRINSIC_ROUND: 2846 case G_INTRINSIC_TRUNC: 2847 case G_FCOS: 2848 case G_FSIN: 2849 case G_FSQRT: 2850 case G_BSWAP: 2851 case G_BITREVERSE: 2852 case G_SDIV: 2853 case G_SMIN: 2854 case G_SMAX: 2855 case G_UMIN: 2856 case G_UMAX: 2857 case G_FMINNUM: 2858 case G_FMAXNUM: 2859 case G_FMINNUM_IEEE: 2860 case G_FMAXNUM_IEEE: 2861 case G_FMINIMUM: 2862 case G_FMAXIMUM: 2863 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy); 2864 case G_SHL: 2865 case G_LSHR: 2866 case G_ASHR: 2867 case G_CTLZ: 2868 case G_CTLZ_ZERO_UNDEF: 2869 case G_CTTZ: 2870 case G_CTTZ_ZERO_UNDEF: 2871 case G_CTPOP: 2872 case G_FCOPYSIGN: 2873 return fewerElementsVectorMultiEltType(MI, TypeIdx, NarrowTy); 2874 case G_ZEXT: 2875 case G_SEXT: 2876 case G_ANYEXT: 2877 case G_FPEXT: 2878 case G_FPTRUNC: 2879 case G_SITOFP: 2880 case G_UITOFP: 2881 case G_FPTOSI: 2882 case G_FPTOUI: 2883 case G_INTTOPTR: 2884 case G_PTRTOINT: 2885 case G_ADDRSPACE_CAST: 2886 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy); 2887 case G_ICMP: 2888 case G_FCMP: 2889 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy); 2890 case G_SELECT: 2891 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy); 2892 case G_PHI: 2893 return fewerElementsVectorPhi(MI, TypeIdx, NarrowTy); 2894 case G_UNMERGE_VALUES: 2895 return fewerElementsVectorUnmergeValues(MI, TypeIdx, NarrowTy); 2896 case G_LOAD: 2897 case G_STORE: 2898 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy); 2899 default: 2900 return UnableToLegalize; 2901 } 2902 } 2903 2904 LegalizerHelper::LegalizeResult 2905 LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, 2906 const LLT HalfTy, const LLT AmtTy) { 2907 2908 Register InL = MRI.createGenericVirtualRegister(HalfTy); 2909 Register InH = MRI.createGenericVirtualRegister(HalfTy); 2910 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg()); 2911 2912 if (Amt.isNullValue()) { 2913 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {InL, InH}); 2914 MI.eraseFromParent(); 2915 return Legalized; 2916 } 2917 2918 LLT NVT = HalfTy; 2919 unsigned NVTBits = HalfTy.getSizeInBits(); 2920 unsigned VTBits = 2 * NVTBits; 2921 2922 SrcOp Lo(Register(0)), Hi(Register(0)); 2923 if (MI.getOpcode() == TargetOpcode::G_SHL) { 2924 if (Amt.ugt(VTBits)) { 2925 Lo = Hi = MIRBuilder.buildConstant(NVT, 0); 2926 } else if (Amt.ugt(NVTBits)) { 2927 Lo = MIRBuilder.buildConstant(NVT, 0); 2928 Hi = MIRBuilder.buildShl(NVT, InL, 2929 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits)); 2930 } else if (Amt == NVTBits) { 2931 Lo = MIRBuilder.buildConstant(NVT, 0); 2932 Hi = InL; 2933 } else { 2934 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt)); 2935 auto OrLHS = 2936 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt)); 2937 auto OrRHS = MIRBuilder.buildLShr( 2938 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits)); 2939 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS); 2940 } 2941 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) { 2942 if (Amt.ugt(VTBits)) { 2943 Lo = Hi = MIRBuilder.buildConstant(NVT, 0); 2944 } else if (Amt.ugt(NVTBits)) { 2945 Lo = MIRBuilder.buildLShr(NVT, InH, 2946 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits)); 2947 Hi = MIRBuilder.buildConstant(NVT, 0); 2948 } else if (Amt == NVTBits) { 2949 Lo = InH; 2950 Hi = MIRBuilder.buildConstant(NVT, 0); 2951 } else { 2952 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt); 2953 2954 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst); 2955 auto OrRHS = MIRBuilder.buildShl( 2956 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits)); 2957 2958 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS); 2959 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst); 2960 } 2961 } else { 2962 if (Amt.ugt(VTBits)) { 2963 Hi = Lo = MIRBuilder.buildAShr( 2964 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1)); 2965 } else if (Amt.ugt(NVTBits)) { 2966 Lo = MIRBuilder.buildAShr(NVT, InH, 2967 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits)); 2968 Hi = MIRBuilder.buildAShr(NVT, InH, 2969 MIRBuilder.buildConstant(AmtTy, NVTBits - 1)); 2970 } else if (Amt == NVTBits) { 2971 Lo = InH; 2972 Hi = MIRBuilder.buildAShr(NVT, InH, 2973 MIRBuilder.buildConstant(AmtTy, NVTBits - 1)); 2974 } else { 2975 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt); 2976 2977 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst); 2978 auto OrRHS = MIRBuilder.buildShl( 2979 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits)); 2980 2981 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS); 2982 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst); 2983 } 2984 } 2985 2986 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {Lo.getReg(), Hi.getReg()}); 2987 MI.eraseFromParent(); 2988 2989 return Legalized; 2990 } 2991 2992 // TODO: Optimize if constant shift amount. 2993 LegalizerHelper::LegalizeResult 2994 LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, 2995 LLT RequestedTy) { 2996 if (TypeIdx == 1) { 2997 Observer.changingInstr(MI); 2998 narrowScalarSrc(MI, RequestedTy, 2); 2999 Observer.changedInstr(MI); 3000 return Legalized; 3001 } 3002 3003 Register DstReg = MI.getOperand(0).getReg(); 3004 LLT DstTy = MRI.getType(DstReg); 3005 if (DstTy.isVector()) 3006 return UnableToLegalize; 3007 3008 Register Amt = MI.getOperand(2).getReg(); 3009 LLT ShiftAmtTy = MRI.getType(Amt); 3010 const unsigned DstEltSize = DstTy.getScalarSizeInBits(); 3011 if (DstEltSize % 2 != 0) 3012 return UnableToLegalize; 3013 3014 // Ignore the input type. We can only go to exactly half the size of the 3015 // input. If that isn't small enough, the resulting pieces will be further 3016 // legalized. 3017 const unsigned NewBitSize = DstEltSize / 2; 3018 const LLT HalfTy = LLT::scalar(NewBitSize); 3019 const LLT CondTy = LLT::scalar(1); 3020 3021 if (const MachineInstr *KShiftAmt = 3022 getOpcodeDef(TargetOpcode::G_CONSTANT, Amt, MRI)) { 3023 return narrowScalarShiftByConstant( 3024 MI, KShiftAmt->getOperand(1).getCImm()->getValue(), HalfTy, ShiftAmtTy); 3025 } 3026 3027 // TODO: Expand with known bits. 3028 3029 // Handle the fully general expansion by an unknown amount. 3030 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize); 3031 3032 Register InL = MRI.createGenericVirtualRegister(HalfTy); 3033 Register InH = MRI.createGenericVirtualRegister(HalfTy); 3034 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1).getReg()); 3035 3036 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits); 3037 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt); 3038 3039 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0); 3040 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits); 3041 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero); 3042 3043 Register ResultRegs[2]; 3044 switch (MI.getOpcode()) { 3045 case TargetOpcode::G_SHL: { 3046 // Short: ShAmt < NewBitSize 3047 auto LoS = MIRBuilder.buildShl(HalfTy, InL, Amt); 3048 3049 auto LoOr = MIRBuilder.buildLShr(HalfTy, InL, AmtLack); 3050 auto HiOr = MIRBuilder.buildShl(HalfTy, InH, Amt); 3051 auto HiS = MIRBuilder.buildOr(HalfTy, LoOr, HiOr); 3052 3053 // Long: ShAmt >= NewBitSize 3054 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero. 3055 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part. 3056 3057 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL); 3058 auto Hi = MIRBuilder.buildSelect( 3059 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL)); 3060 3061 ResultRegs[0] = Lo.getReg(0); 3062 ResultRegs[1] = Hi.getReg(0); 3063 break; 3064 } 3065 case TargetOpcode::G_LSHR: 3066 case TargetOpcode::G_ASHR: { 3067 // Short: ShAmt < NewBitSize 3068 auto HiS = MIRBuilder.buildInstr(MI.getOpcode(), {HalfTy}, {InH, Amt}); 3069 3070 auto LoOr = MIRBuilder.buildLShr(HalfTy, InL, Amt); 3071 auto HiOr = MIRBuilder.buildShl(HalfTy, InH, AmtLack); 3072 auto LoS = MIRBuilder.buildOr(HalfTy, LoOr, HiOr); 3073 3074 // Long: ShAmt >= NewBitSize 3075 MachineInstrBuilder HiL; 3076 if (MI.getOpcode() == TargetOpcode::G_LSHR) { 3077 HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero. 3078 } else { 3079 auto ShiftAmt = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1); 3080 HiL = MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt); // Sign of Hi part. 3081 } 3082 auto LoL = MIRBuilder.buildInstr(MI.getOpcode(), {HalfTy}, 3083 {InH, AmtExcess}); // Lo from Hi part. 3084 3085 auto Lo = MIRBuilder.buildSelect( 3086 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL)); 3087 3088 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL); 3089 3090 ResultRegs[0] = Lo.getReg(0); 3091 ResultRegs[1] = Hi.getReg(0); 3092 break; 3093 } 3094 default: 3095 llvm_unreachable("not a shift"); 3096 } 3097 3098 MIRBuilder.buildMerge(DstReg, ResultRegs); 3099 MI.eraseFromParent(); 3100 return Legalized; 3101 } 3102 3103 LegalizerHelper::LegalizeResult 3104 LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, 3105 LLT MoreTy) { 3106 assert(TypeIdx == 0 && "Expecting only Idx 0"); 3107 3108 Observer.changingInstr(MI); 3109 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) { 3110 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB(); 3111 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 3112 moreElementsVectorSrc(MI, MoreTy, I); 3113 } 3114 3115 MachineBasicBlock &MBB = *MI.getParent(); 3116 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI()); 3117 moreElementsVectorDst(MI, MoreTy, 0); 3118 Observer.changedInstr(MI); 3119 return Legalized; 3120 } 3121 3122 LegalizerHelper::LegalizeResult 3123 LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, 3124 LLT MoreTy) { 3125 MIRBuilder.setInstr(MI); 3126 unsigned Opc = MI.getOpcode(); 3127 switch (Opc) { 3128 case TargetOpcode::G_IMPLICIT_DEF: 3129 case TargetOpcode::G_LOAD: { 3130 if (TypeIdx != 0) 3131 return UnableToLegalize; 3132 Observer.changingInstr(MI); 3133 moreElementsVectorDst(MI, MoreTy, 0); 3134 Observer.changedInstr(MI); 3135 return Legalized; 3136 } 3137 case TargetOpcode::G_STORE: 3138 if (TypeIdx != 0) 3139 return UnableToLegalize; 3140 Observer.changingInstr(MI); 3141 moreElementsVectorSrc(MI, MoreTy, 0); 3142 Observer.changedInstr(MI); 3143 return Legalized; 3144 case TargetOpcode::G_AND: 3145 case TargetOpcode::G_OR: 3146 case TargetOpcode::G_XOR: 3147 case TargetOpcode::G_SMIN: 3148 case TargetOpcode::G_SMAX: 3149 case TargetOpcode::G_UMIN: 3150 case TargetOpcode::G_UMAX: { 3151 Observer.changingInstr(MI); 3152 moreElementsVectorSrc(MI, MoreTy, 1); 3153 moreElementsVectorSrc(MI, MoreTy, 2); 3154 moreElementsVectorDst(MI, MoreTy, 0); 3155 Observer.changedInstr(MI); 3156 return Legalized; 3157 } 3158 case TargetOpcode::G_EXTRACT: 3159 if (TypeIdx != 1) 3160 return UnableToLegalize; 3161 Observer.changingInstr(MI); 3162 moreElementsVectorSrc(MI, MoreTy, 1); 3163 Observer.changedInstr(MI); 3164 return Legalized; 3165 case TargetOpcode::G_INSERT: 3166 if (TypeIdx != 0) 3167 return UnableToLegalize; 3168 Observer.changingInstr(MI); 3169 moreElementsVectorSrc(MI, MoreTy, 1); 3170 moreElementsVectorDst(MI, MoreTy, 0); 3171 Observer.changedInstr(MI); 3172 return Legalized; 3173 case TargetOpcode::G_SELECT: 3174 if (TypeIdx != 0) 3175 return UnableToLegalize; 3176 if (MRI.getType(MI.getOperand(1).getReg()).isVector()) 3177 return UnableToLegalize; 3178 3179 Observer.changingInstr(MI); 3180 moreElementsVectorSrc(MI, MoreTy, 2); 3181 moreElementsVectorSrc(MI, MoreTy, 3); 3182 moreElementsVectorDst(MI, MoreTy, 0); 3183 Observer.changedInstr(MI); 3184 return Legalized; 3185 case TargetOpcode::G_UNMERGE_VALUES: { 3186 if (TypeIdx != 1) 3187 return UnableToLegalize; 3188 3189 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 3190 int NumDst = MI.getNumOperands() - 1; 3191 moreElementsVectorSrc(MI, MoreTy, NumDst); 3192 3193 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES); 3194 for (int I = 0; I != NumDst; ++I) 3195 MIB.addDef(MI.getOperand(I).getReg()); 3196 3197 int NewNumDst = MoreTy.getSizeInBits() / DstTy.getSizeInBits(); 3198 for (int I = NumDst; I != NewNumDst; ++I) 3199 MIB.addDef(MRI.createGenericVirtualRegister(DstTy)); 3200 3201 MIB.addUse(MI.getOperand(NumDst).getReg()); 3202 MI.eraseFromParent(); 3203 return Legalized; 3204 } 3205 case TargetOpcode::G_PHI: 3206 return moreElementsVectorPhi(MI, TypeIdx, MoreTy); 3207 default: 3208 return UnableToLegalize; 3209 } 3210 } 3211 3212 void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs, 3213 ArrayRef<Register> Src1Regs, 3214 ArrayRef<Register> Src2Regs, 3215 LLT NarrowTy) { 3216 MachineIRBuilder &B = MIRBuilder; 3217 unsigned SrcParts = Src1Regs.size(); 3218 unsigned DstParts = DstRegs.size(); 3219 3220 unsigned DstIdx = 0; // Low bits of the result. 3221 Register FactorSum = 3222 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0); 3223 DstRegs[DstIdx] = FactorSum; 3224 3225 unsigned CarrySumPrevDstIdx; 3226 SmallVector<Register, 4> Factors; 3227 3228 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) { 3229 // Collect low parts of muls for DstIdx. 3230 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1; 3231 i <= std::min(DstIdx, SrcParts - 1); ++i) { 3232 MachineInstrBuilder Mul = 3233 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]); 3234 Factors.push_back(Mul.getReg(0)); 3235 } 3236 // Collect high parts of muls from previous DstIdx. 3237 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts; 3238 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) { 3239 MachineInstrBuilder Umulh = 3240 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]); 3241 Factors.push_back(Umulh.getReg(0)); 3242 } 3243 // Add CarrySum from additons calculated for previous DstIdx. 3244 if (DstIdx != 1) { 3245 Factors.push_back(CarrySumPrevDstIdx); 3246 } 3247 3248 Register CarrySum; 3249 // Add all factors and accumulate all carries into CarrySum. 3250 if (DstIdx != DstParts - 1) { 3251 MachineInstrBuilder Uaddo = 3252 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]); 3253 FactorSum = Uaddo.getReg(0); 3254 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0); 3255 for (unsigned i = 2; i < Factors.size(); ++i) { 3256 MachineInstrBuilder Uaddo = 3257 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]); 3258 FactorSum = Uaddo.getReg(0); 3259 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1)); 3260 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0); 3261 } 3262 } else { 3263 // Since value for the next index is not calculated, neither is CarrySum. 3264 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0); 3265 for (unsigned i = 2; i < Factors.size(); ++i) 3266 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0); 3267 } 3268 3269 CarrySumPrevDstIdx = CarrySum; 3270 DstRegs[DstIdx] = FactorSum; 3271 Factors.clear(); 3272 } 3273 } 3274 3275 LegalizerHelper::LegalizeResult 3276 LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) { 3277 Register DstReg = MI.getOperand(0).getReg(); 3278 Register Src1 = MI.getOperand(1).getReg(); 3279 Register Src2 = MI.getOperand(2).getReg(); 3280 3281 LLT Ty = MRI.getType(DstReg); 3282 if (Ty.isVector()) 3283 return UnableToLegalize; 3284 3285 unsigned SrcSize = MRI.getType(Src1).getSizeInBits(); 3286 unsigned DstSize = Ty.getSizeInBits(); 3287 unsigned NarrowSize = NarrowTy.getSizeInBits(); 3288 if (DstSize % NarrowSize != 0 || SrcSize % NarrowSize != 0) 3289 return UnableToLegalize; 3290 3291 unsigned NumDstParts = DstSize / NarrowSize; 3292 unsigned NumSrcParts = SrcSize / NarrowSize; 3293 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH; 3294 unsigned DstTmpParts = NumDstParts * (IsMulHigh ? 2 : 1); 3295 3296 SmallVector<Register, 2> Src1Parts, Src2Parts, DstTmpRegs; 3297 extractParts(Src1, NarrowTy, NumSrcParts, Src1Parts); 3298 extractParts(Src2, NarrowTy, NumSrcParts, Src2Parts); 3299 DstTmpRegs.resize(DstTmpParts); 3300 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy); 3301 3302 // Take only high half of registers if this is high mul. 3303 ArrayRef<Register> DstRegs( 3304 IsMulHigh ? &DstTmpRegs[DstTmpParts / 2] : &DstTmpRegs[0], NumDstParts); 3305 MIRBuilder.buildMerge(DstReg, DstRegs); 3306 MI.eraseFromParent(); 3307 return Legalized; 3308 } 3309 3310 LegalizerHelper::LegalizeResult 3311 LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, 3312 LLT NarrowTy) { 3313 if (TypeIdx != 1) 3314 return UnableToLegalize; 3315 3316 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 3317 3318 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 3319 // FIXME: add support for when SizeOp1 isn't an exact multiple of 3320 // NarrowSize. 3321 if (SizeOp1 % NarrowSize != 0) 3322 return UnableToLegalize; 3323 int NumParts = SizeOp1 / NarrowSize; 3324 3325 SmallVector<Register, 2> SrcRegs, DstRegs; 3326 SmallVector<uint64_t, 2> Indexes; 3327 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 3328 3329 Register OpReg = MI.getOperand(0).getReg(); 3330 uint64_t OpStart = MI.getOperand(2).getImm(); 3331 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 3332 for (int i = 0; i < NumParts; ++i) { 3333 unsigned SrcStart = i * NarrowSize; 3334 3335 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) { 3336 // No part of the extract uses this subregister, ignore it. 3337 continue; 3338 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 3339 // The entire subregister is extracted, forward the value. 3340 DstRegs.push_back(SrcRegs[i]); 3341 continue; 3342 } 3343 3344 // OpSegStart is where this destination segment would start in OpReg if it 3345 // extended infinitely in both directions. 3346 int64_t ExtractOffset; 3347 uint64_t SegSize; 3348 if (OpStart < SrcStart) { 3349 ExtractOffset = 0; 3350 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart); 3351 } else { 3352 ExtractOffset = OpStart - SrcStart; 3353 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize); 3354 } 3355 3356 Register SegReg = SrcRegs[i]; 3357 if (ExtractOffset != 0 || SegSize != NarrowSize) { 3358 // A genuine extract is needed. 3359 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 3360 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset); 3361 } 3362 3363 DstRegs.push_back(SegReg); 3364 } 3365 3366 Register DstReg = MI.getOperand(0).getReg(); 3367 if(MRI.getType(DstReg).isVector()) 3368 MIRBuilder.buildBuildVector(DstReg, DstRegs); 3369 else 3370 MIRBuilder.buildMerge(DstReg, DstRegs); 3371 MI.eraseFromParent(); 3372 return Legalized; 3373 } 3374 3375 LegalizerHelper::LegalizeResult 3376 LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, 3377 LLT NarrowTy) { 3378 // FIXME: Don't know how to handle secondary types yet. 3379 if (TypeIdx != 0) 3380 return UnableToLegalize; 3381 3382 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 3383 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 3384 3385 // FIXME: add support for when SizeOp0 isn't an exact multiple of 3386 // NarrowSize. 3387 if (SizeOp0 % NarrowSize != 0) 3388 return UnableToLegalize; 3389 3390 int NumParts = SizeOp0 / NarrowSize; 3391 3392 SmallVector<Register, 2> SrcRegs, DstRegs; 3393 SmallVector<uint64_t, 2> Indexes; 3394 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 3395 3396 Register OpReg = MI.getOperand(2).getReg(); 3397 uint64_t OpStart = MI.getOperand(3).getImm(); 3398 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 3399 for (int i = 0; i < NumParts; ++i) { 3400 unsigned DstStart = i * NarrowSize; 3401 3402 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { 3403 // No part of the insert affects this subregister, forward the original. 3404 DstRegs.push_back(SrcRegs[i]); 3405 continue; 3406 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 3407 // The entire subregister is defined by this insert, forward the new 3408 // value. 3409 DstRegs.push_back(OpReg); 3410 continue; 3411 } 3412 3413 // OpSegStart is where this destination segment would start in OpReg if it 3414 // extended infinitely in both directions. 3415 int64_t ExtractOffset, InsertOffset; 3416 uint64_t SegSize; 3417 if (OpStart < DstStart) { 3418 InsertOffset = 0; 3419 ExtractOffset = DstStart - OpStart; 3420 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); 3421 } else { 3422 InsertOffset = OpStart - DstStart; 3423 ExtractOffset = 0; 3424 SegSize = 3425 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); 3426 } 3427 3428 Register SegReg = OpReg; 3429 if (ExtractOffset != 0 || SegSize != OpSize) { 3430 // A genuine extract is needed. 3431 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 3432 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); 3433 } 3434 3435 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); 3436 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); 3437 DstRegs.push_back(DstReg); 3438 } 3439 3440 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); 3441 Register DstReg = MI.getOperand(0).getReg(); 3442 if(MRI.getType(DstReg).isVector()) 3443 MIRBuilder.buildBuildVector(DstReg, DstRegs); 3444 else 3445 MIRBuilder.buildMerge(DstReg, DstRegs); 3446 MI.eraseFromParent(); 3447 return Legalized; 3448 } 3449 3450 LegalizerHelper::LegalizeResult 3451 LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, 3452 LLT NarrowTy) { 3453 Register DstReg = MI.getOperand(0).getReg(); 3454 LLT DstTy = MRI.getType(DstReg); 3455 3456 assert(MI.getNumOperands() == 3 && TypeIdx == 0); 3457 3458 SmallVector<Register, 4> DstRegs, DstLeftoverRegs; 3459 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs; 3460 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs; 3461 LLT LeftoverTy; 3462 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy, 3463 Src0Regs, Src0LeftoverRegs)) 3464 return UnableToLegalize; 3465 3466 LLT Unused; 3467 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused, 3468 Src1Regs, Src1LeftoverRegs)) 3469 llvm_unreachable("inconsistent extractParts result"); 3470 3471 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) { 3472 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy}, 3473 {Src0Regs[I], Src1Regs[I]}); 3474 DstRegs.push_back(Inst->getOperand(0).getReg()); 3475 } 3476 3477 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) { 3478 auto Inst = MIRBuilder.buildInstr( 3479 MI.getOpcode(), 3480 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]}); 3481 DstLeftoverRegs.push_back(Inst->getOperand(0).getReg()); 3482 } 3483 3484 insertParts(DstReg, DstTy, NarrowTy, DstRegs, 3485 LeftoverTy, DstLeftoverRegs); 3486 3487 MI.eraseFromParent(); 3488 return Legalized; 3489 } 3490 3491 LegalizerHelper::LegalizeResult 3492 LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, 3493 LLT NarrowTy) { 3494 if (TypeIdx != 0) 3495 return UnableToLegalize; 3496 3497 Register CondReg = MI.getOperand(1).getReg(); 3498 LLT CondTy = MRI.getType(CondReg); 3499 if (CondTy.isVector()) // TODO: Handle vselect 3500 return UnableToLegalize; 3501 3502 Register DstReg = MI.getOperand(0).getReg(); 3503 LLT DstTy = MRI.getType(DstReg); 3504 3505 SmallVector<Register, 4> DstRegs, DstLeftoverRegs; 3506 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs; 3507 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs; 3508 LLT LeftoverTy; 3509 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy, 3510 Src1Regs, Src1LeftoverRegs)) 3511 return UnableToLegalize; 3512 3513 LLT Unused; 3514 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused, 3515 Src2Regs, Src2LeftoverRegs)) 3516 llvm_unreachable("inconsistent extractParts result"); 3517 3518 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) { 3519 auto Select = MIRBuilder.buildSelect(NarrowTy, 3520 CondReg, Src1Regs[I], Src2Regs[I]); 3521 DstRegs.push_back(Select->getOperand(0).getReg()); 3522 } 3523 3524 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) { 3525 auto Select = MIRBuilder.buildSelect( 3526 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]); 3527 DstLeftoverRegs.push_back(Select->getOperand(0).getReg()); 3528 } 3529 3530 insertParts(DstReg, DstTy, NarrowTy, DstRegs, 3531 LeftoverTy, DstLeftoverRegs); 3532 3533 MI.eraseFromParent(); 3534 return Legalized; 3535 } 3536 3537 LegalizerHelper::LegalizeResult 3538 LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 3539 unsigned Opc = MI.getOpcode(); 3540 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo(); 3541 auto isSupported = [this](const LegalityQuery &Q) { 3542 auto QAction = LI.getAction(Q).Action; 3543 return QAction == Legal || QAction == Libcall || QAction == Custom; 3544 }; 3545 switch (Opc) { 3546 default: 3547 return UnableToLegalize; 3548 case TargetOpcode::G_CTLZ_ZERO_UNDEF: { 3549 // This trivially expands to CTLZ. 3550 Observer.changingInstr(MI); 3551 MI.setDesc(TII.get(TargetOpcode::G_CTLZ)); 3552 Observer.changedInstr(MI); 3553 return Legalized; 3554 } 3555 case TargetOpcode::G_CTLZ: { 3556 Register SrcReg = MI.getOperand(1).getReg(); 3557 unsigned Len = Ty.getSizeInBits(); 3558 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) { 3559 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero. 3560 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, 3561 {Ty}, {SrcReg}); 3562 auto MIBZero = MIRBuilder.buildConstant(Ty, 0); 3563 auto MIBLen = MIRBuilder.buildConstant(Ty, Len); 3564 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), 3565 SrcReg, MIBZero); 3566 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen, 3567 MIBCtlzZU); 3568 MI.eraseFromParent(); 3569 return Legalized; 3570 } 3571 // for now, we do this: 3572 // NewLen = NextPowerOf2(Len); 3573 // x = x | (x >> 1); 3574 // x = x | (x >> 2); 3575 // ... 3576 // x = x | (x >>16); 3577 // x = x | (x >>32); // for 64-bit input 3578 // Upto NewLen/2 3579 // return Len - popcount(x); 3580 // 3581 // Ref: "Hacker's Delight" by Henry Warren 3582 Register Op = SrcReg; 3583 unsigned NewLen = PowerOf2Ceil(Len); 3584 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) { 3585 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i); 3586 auto MIBOp = MIRBuilder.buildInstr( 3587 TargetOpcode::G_OR, {Ty}, 3588 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty}, 3589 {Op, MIBShiftAmt})}); 3590 Op = MIBOp->getOperand(0).getReg(); 3591 } 3592 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op}); 3593 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()}, 3594 {MIRBuilder.buildConstant(Ty, Len), MIBPop}); 3595 MI.eraseFromParent(); 3596 return Legalized; 3597 } 3598 case TargetOpcode::G_CTTZ_ZERO_UNDEF: { 3599 // This trivially expands to CTTZ. 3600 Observer.changingInstr(MI); 3601 MI.setDesc(TII.get(TargetOpcode::G_CTTZ)); 3602 Observer.changedInstr(MI); 3603 return Legalized; 3604 } 3605 case TargetOpcode::G_CTTZ: { 3606 Register SrcReg = MI.getOperand(1).getReg(); 3607 unsigned Len = Ty.getSizeInBits(); 3608 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) { 3609 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with 3610 // zero. 3611 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, 3612 {Ty}, {SrcReg}); 3613 auto MIBZero = MIRBuilder.buildConstant(Ty, 0); 3614 auto MIBLen = MIRBuilder.buildConstant(Ty, Len); 3615 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), 3616 SrcReg, MIBZero); 3617 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen, 3618 MIBCttzZU); 3619 MI.eraseFromParent(); 3620 return Legalized; 3621 } 3622 // for now, we use: { return popcount(~x & (x - 1)); } 3623 // unless the target has ctlz but not ctpop, in which case we use: 3624 // { return 32 - nlz(~x & (x-1)); } 3625 // Ref: "Hacker's Delight" by Henry Warren 3626 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1); 3627 auto MIBNot = 3628 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1}); 3629 auto MIBTmp = MIRBuilder.buildInstr( 3630 TargetOpcode::G_AND, {Ty}, 3631 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty}, 3632 {SrcReg, MIBCstNeg1})}); 3633 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) && 3634 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) { 3635 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len); 3636 MIRBuilder.buildInstr( 3637 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()}, 3638 {MIBCstLen, 3639 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})}); 3640 MI.eraseFromParent(); 3641 return Legalized; 3642 } 3643 MI.setDesc(TII.get(TargetOpcode::G_CTPOP)); 3644 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg()); 3645 return Legalized; 3646 } 3647 } 3648 } 3649 3650 // Expand s32 = G_UITOFP s64 using bit operations to an IEEE float 3651 // representation. 3652 LegalizerHelper::LegalizeResult 3653 LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) { 3654 Register Dst = MI.getOperand(0).getReg(); 3655 Register Src = MI.getOperand(1).getReg(); 3656 const LLT S64 = LLT::scalar(64); 3657 const LLT S32 = LLT::scalar(32); 3658 const LLT S1 = LLT::scalar(1); 3659 3660 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32); 3661 3662 // unsigned cul2f(ulong u) { 3663 // uint lz = clz(u); 3664 // uint e = (u != 0) ? 127U + 63U - lz : 0; 3665 // u = (u << lz) & 0x7fffffffffffffffUL; 3666 // ulong t = u & 0xffffffffffUL; 3667 // uint v = (e << 23) | (uint)(u >> 40); 3668 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U); 3669 // return as_float(v + r); 3670 // } 3671 3672 auto Zero32 = MIRBuilder.buildConstant(S32, 0); 3673 auto Zero64 = MIRBuilder.buildConstant(S64, 0); 3674 3675 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src); 3676 3677 auto K = MIRBuilder.buildConstant(S32, 127U + 63U); 3678 auto Sub = MIRBuilder.buildSub(S32, K, LZ); 3679 3680 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64); 3681 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32); 3682 3683 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1); 3684 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ); 3685 3686 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0); 3687 3688 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL); 3689 auto T = MIRBuilder.buildAnd(S64, U, Mask1); 3690 3691 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40)); 3692 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23)); 3693 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl)); 3694 3695 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL); 3696 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C); 3697 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C); 3698 auto One = MIRBuilder.buildConstant(S32, 1); 3699 3700 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One); 3701 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32); 3702 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0); 3703 MIRBuilder.buildAdd(Dst, V, R); 3704 3705 return Legalized; 3706 } 3707 3708 LegalizerHelper::LegalizeResult 3709 LegalizerHelper::lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 3710 Register Dst = MI.getOperand(0).getReg(); 3711 Register Src = MI.getOperand(1).getReg(); 3712 LLT DstTy = MRI.getType(Dst); 3713 LLT SrcTy = MRI.getType(Src); 3714 3715 if (SrcTy != LLT::scalar(64)) 3716 return UnableToLegalize; 3717 3718 if (DstTy == LLT::scalar(32)) { 3719 // TODO: SelectionDAG has several alternative expansions to port which may 3720 // be more reasonble depending on the available instructions. If a target 3721 // has sitofp, does not have CTLZ, or can efficiently use f64 as an 3722 // intermediate type, this is probably worse. 3723 return lowerU64ToF32BitOps(MI); 3724 } 3725 3726 return UnableToLegalize; 3727 } 3728 3729 LegalizerHelper::LegalizeResult 3730 LegalizerHelper::lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 3731 Register Dst = MI.getOperand(0).getReg(); 3732 Register Src = MI.getOperand(1).getReg(); 3733 LLT DstTy = MRI.getType(Dst); 3734 LLT SrcTy = MRI.getType(Src); 3735 3736 const LLT S64 = LLT::scalar(64); 3737 const LLT S32 = LLT::scalar(32); 3738 const LLT S1 = LLT::scalar(1); 3739 3740 if (SrcTy != S64) 3741 return UnableToLegalize; 3742 3743 if (DstTy == S32) { 3744 // signed cl2f(long l) { 3745 // long s = l >> 63; 3746 // float r = cul2f((l + s) ^ s); 3747 // return s ? -r : r; 3748 // } 3749 Register L = Src; 3750 auto SignBit = MIRBuilder.buildConstant(S64, 63); 3751 auto S = MIRBuilder.buildAShr(S64, L, SignBit); 3752 3753 auto LPlusS = MIRBuilder.buildAdd(S64, L, S); 3754 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S); 3755 auto R = MIRBuilder.buildUITOFP(S32, Xor); 3756 3757 auto RNeg = MIRBuilder.buildFNeg(S32, R); 3758 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S, 3759 MIRBuilder.buildConstant(S64, 0)); 3760 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R); 3761 return Legalized; 3762 } 3763 3764 return UnableToLegalize; 3765 } 3766 3767 LegalizerHelper::LegalizeResult 3768 LegalizerHelper::lowerFPTOUI(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 3769 Register Dst = MI.getOperand(0).getReg(); 3770 Register Src = MI.getOperand(1).getReg(); 3771 LLT DstTy = MRI.getType(Dst); 3772 LLT SrcTy = MRI.getType(Src); 3773 const LLT S64 = LLT::scalar(64); 3774 const LLT S32 = LLT::scalar(32); 3775 3776 if (SrcTy != S64 && SrcTy != S32) 3777 return UnableToLegalize; 3778 if (DstTy != S32 && DstTy != S64) 3779 return UnableToLegalize; 3780 3781 // FPTOSI gives same result as FPTOUI for positive signed integers. 3782 // FPTOUI needs to deal with fp values that convert to unsigned integers 3783 // greater or equal to 2^31 for float or 2^63 for double. For brevity 2^Exp. 3784 3785 APInt TwoPExpInt = APInt::getSignMask(DstTy.getSizeInBits()); 3786 APFloat TwoPExpFP(SrcTy.getSizeInBits() == 32 ? APFloat::IEEEsingle() 3787 : APFloat::IEEEdouble(), 3788 APInt::getNullValue(SrcTy.getSizeInBits())); 3789 TwoPExpFP.convertFromAPInt(TwoPExpInt, false, APFloat::rmNearestTiesToEven); 3790 3791 MachineInstrBuilder FPTOSI = MIRBuilder.buildFPTOSI(DstTy, Src); 3792 3793 MachineInstrBuilder Threshold = MIRBuilder.buildFConstant(SrcTy, TwoPExpFP); 3794 // For fp Value greater or equal to Threshold(2^Exp), we use FPTOSI on 3795 // (Value - 2^Exp) and add 2^Exp by setting highest bit in result to 1. 3796 MachineInstrBuilder FSub = MIRBuilder.buildFSub(SrcTy, Src, Threshold); 3797 MachineInstrBuilder ResLowBits = MIRBuilder.buildFPTOSI(DstTy, FSub); 3798 MachineInstrBuilder ResHighBit = MIRBuilder.buildConstant(DstTy, TwoPExpInt); 3799 MachineInstrBuilder Res = MIRBuilder.buildXor(DstTy, ResLowBits, ResHighBit); 3800 3801 MachineInstrBuilder FCMP = 3802 MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, DstTy, Src, Threshold); 3803 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res); 3804 3805 MI.eraseFromParent(); 3806 return Legalized; 3807 } 3808 3809 static CmpInst::Predicate minMaxToCompare(unsigned Opc) { 3810 switch (Opc) { 3811 case TargetOpcode::G_SMIN: 3812 return CmpInst::ICMP_SLT; 3813 case TargetOpcode::G_SMAX: 3814 return CmpInst::ICMP_SGT; 3815 case TargetOpcode::G_UMIN: 3816 return CmpInst::ICMP_ULT; 3817 case TargetOpcode::G_UMAX: 3818 return CmpInst::ICMP_UGT; 3819 default: 3820 llvm_unreachable("not in integer min/max"); 3821 } 3822 } 3823 3824 LegalizerHelper::LegalizeResult 3825 LegalizerHelper::lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 3826 Register Dst = MI.getOperand(0).getReg(); 3827 Register Src0 = MI.getOperand(1).getReg(); 3828 Register Src1 = MI.getOperand(2).getReg(); 3829 3830 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode()); 3831 LLT CmpType = MRI.getType(Dst).changeElementSize(1); 3832 3833 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1); 3834 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1); 3835 3836 MI.eraseFromParent(); 3837 return Legalized; 3838 } 3839 3840 LegalizerHelper::LegalizeResult 3841 LegalizerHelper::lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 3842 Register Dst = MI.getOperand(0).getReg(); 3843 Register Src0 = MI.getOperand(1).getReg(); 3844 Register Src1 = MI.getOperand(2).getReg(); 3845 3846 const LLT Src0Ty = MRI.getType(Src0); 3847 const LLT Src1Ty = MRI.getType(Src1); 3848 3849 const int Src0Size = Src0Ty.getScalarSizeInBits(); 3850 const int Src1Size = Src1Ty.getScalarSizeInBits(); 3851 3852 auto SignBitMask = MIRBuilder.buildConstant( 3853 Src0Ty, APInt::getSignMask(Src0Size)); 3854 3855 auto NotSignBitMask = MIRBuilder.buildConstant( 3856 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1)); 3857 3858 auto And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask); 3859 MachineInstr *Or; 3860 3861 if (Src0Ty == Src1Ty) { 3862 auto And1 = MIRBuilder.buildAnd(Src1Ty, Src0, SignBitMask); 3863 Or = MIRBuilder.buildOr(Dst, And0, And1); 3864 } else if (Src0Size > Src1Size) { 3865 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size); 3866 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1); 3867 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt); 3868 auto And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask); 3869 Or = MIRBuilder.buildOr(Dst, And0, And1); 3870 } else { 3871 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size); 3872 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt); 3873 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift); 3874 auto And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask); 3875 Or = MIRBuilder.buildOr(Dst, And0, And1); 3876 } 3877 3878 // Be careful about setting nsz/nnan/ninf on every instruction, since the 3879 // constants are a nan and -0.0, but the final result should preserve 3880 // everything. 3881 if (unsigned Flags = MI.getFlags()) 3882 Or->setFlags(Flags); 3883 3884 MI.eraseFromParent(); 3885 return Legalized; 3886 } 3887 3888 LegalizerHelper::LegalizeResult 3889 LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) { 3890 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ? 3891 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE; 3892 3893 Register Dst = MI.getOperand(0).getReg(); 3894 Register Src0 = MI.getOperand(1).getReg(); 3895 Register Src1 = MI.getOperand(2).getReg(); 3896 LLT Ty = MRI.getType(Dst); 3897 3898 if (!MI.getFlag(MachineInstr::FmNoNans)) { 3899 // Insert canonicalizes if it's possible we need to quiet to get correct 3900 // sNaN behavior. 3901 3902 // Note this must be done here, and not as an optimization combine in the 3903 // absence of a dedicate quiet-snan instruction as we're using an 3904 // omni-purpose G_FCANONICALIZE. 3905 if (!isKnownNeverSNaN(Src0, MRI)) 3906 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0); 3907 3908 if (!isKnownNeverSNaN(Src1, MRI)) 3909 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0); 3910 } 3911 3912 // If there are no nans, it's safe to simply replace this with the non-IEEE 3913 // version. 3914 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags()); 3915 MI.eraseFromParent(); 3916 return Legalized; 3917 } 3918 3919 LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMad(MachineInstr &MI) { 3920 // Expand G_FMAD a, b, c -> G_FADD (G_FMUL a, b), c 3921 Register DstReg = MI.getOperand(0).getReg(); 3922 LLT Ty = MRI.getType(DstReg); 3923 unsigned Flags = MI.getFlags(); 3924 3925 auto Mul = MIRBuilder.buildFMul(Ty, MI.getOperand(1), MI.getOperand(2), 3926 Flags); 3927 MIRBuilder.buildFAdd(DstReg, Mul, MI.getOperand(3), Flags); 3928 MI.eraseFromParent(); 3929 return Legalized; 3930 } 3931 3932 LegalizerHelper::LegalizeResult 3933 LegalizerHelper::lowerUnmergeValues(MachineInstr &MI) { 3934 const unsigned NumDst = MI.getNumOperands() - 1; 3935 const Register SrcReg = MI.getOperand(NumDst).getReg(); 3936 LLT SrcTy = MRI.getType(SrcReg); 3937 3938 Register Dst0Reg = MI.getOperand(0).getReg(); 3939 LLT DstTy = MRI.getType(Dst0Reg); 3940 3941 3942 // Expand scalarizing unmerge as bitcast to integer and shift. 3943 if (!DstTy.isVector() && SrcTy.isVector() && 3944 SrcTy.getElementType() == DstTy) { 3945 LLT IntTy = LLT::scalar(SrcTy.getSizeInBits()); 3946 Register Cast = MIRBuilder.buildBitcast(IntTy, SrcReg).getReg(0); 3947 3948 MIRBuilder.buildTrunc(Dst0Reg, Cast); 3949 3950 const unsigned DstSize = DstTy.getSizeInBits(); 3951 unsigned Offset = DstSize; 3952 for (unsigned I = 1; I != NumDst; ++I, Offset += DstSize) { 3953 auto ShiftAmt = MIRBuilder.buildConstant(IntTy, Offset); 3954 auto Shift = MIRBuilder.buildLShr(IntTy, Cast, ShiftAmt); 3955 MIRBuilder.buildTrunc(MI.getOperand(I), Shift); 3956 } 3957 3958 MI.eraseFromParent(); 3959 return Legalized; 3960 } 3961 3962 return UnableToLegalize; 3963 } 3964 3965 LegalizerHelper::LegalizeResult 3966 LegalizerHelper::lowerShuffleVector(MachineInstr &MI) { 3967 Register DstReg = MI.getOperand(0).getReg(); 3968 Register Src0Reg = MI.getOperand(1).getReg(); 3969 Register Src1Reg = MI.getOperand(2).getReg(); 3970 LLT Src0Ty = MRI.getType(Src0Reg); 3971 LLT DstTy = MRI.getType(DstReg); 3972 LLT IdxTy = LLT::scalar(32); 3973 3974 const Constant *ShufMask = MI.getOperand(3).getShuffleMask(); 3975 3976 SmallVector<int, 32> Mask; 3977 ShuffleVectorInst::getShuffleMask(ShufMask, Mask); 3978 3979 if (DstTy.isScalar()) { 3980 if (Src0Ty.isVector()) 3981 return UnableToLegalize; 3982 3983 // This is just a SELECT. 3984 assert(Mask.size() == 1 && "Expected a single mask element"); 3985 Register Val; 3986 if (Mask[0] < 0 || Mask[0] > 1) 3987 Val = MIRBuilder.buildUndef(DstTy).getReg(0); 3988 else 3989 Val = Mask[0] == 0 ? Src0Reg : Src1Reg; 3990 MIRBuilder.buildCopy(DstReg, Val); 3991 MI.eraseFromParent(); 3992 return Legalized; 3993 } 3994 3995 Register Undef; 3996 SmallVector<Register, 32> BuildVec; 3997 LLT EltTy = DstTy.getElementType(); 3998 3999 for (int Idx : Mask) { 4000 if (Idx < 0) { 4001 if (!Undef.isValid()) 4002 Undef = MIRBuilder.buildUndef(EltTy).getReg(0); 4003 BuildVec.push_back(Undef); 4004 continue; 4005 } 4006 4007 if (Src0Ty.isScalar()) { 4008 BuildVec.push_back(Idx == 0 ? Src0Reg : Src1Reg); 4009 } else { 4010 int NumElts = Src0Ty.getNumElements(); 4011 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg; 4012 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts; 4013 auto IdxK = MIRBuilder.buildConstant(IdxTy, ExtractIdx); 4014 auto Extract = MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK); 4015 BuildVec.push_back(Extract.getReg(0)); 4016 } 4017 } 4018 4019 MIRBuilder.buildBuildVector(DstReg, BuildVec); 4020 MI.eraseFromParent(); 4021 return Legalized; 4022 } 4023 4024 LegalizerHelper::LegalizeResult 4025 LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) { 4026 Register Dst = MI.getOperand(0).getReg(); 4027 Register AllocSize = MI.getOperand(1).getReg(); 4028 unsigned Align = MI.getOperand(2).getImm(); 4029 4030 const auto &MF = *MI.getMF(); 4031 const auto &TLI = *MF.getSubtarget().getTargetLowering(); 4032 4033 LLT PtrTy = MRI.getType(Dst); 4034 LLT IntPtrTy = LLT::scalar(PtrTy.getSizeInBits()); 4035 4036 Register SPReg = TLI.getStackPointerRegisterToSaveRestore(); 4037 auto SPTmp = MIRBuilder.buildCopy(PtrTy, SPReg); 4038 SPTmp = MIRBuilder.buildCast(IntPtrTy, SPTmp); 4039 4040 // Subtract the final alloc from the SP. We use G_PTRTOINT here so we don't 4041 // have to generate an extra instruction to negate the alloc and then use 4042 // G_GEP to add the negative offset. 4043 auto Alloc = MIRBuilder.buildSub(IntPtrTy, SPTmp, AllocSize); 4044 if (Align) { 4045 APInt AlignMask(IntPtrTy.getSizeInBits(), Align, true); 4046 AlignMask.negate(); 4047 auto AlignCst = MIRBuilder.buildConstant(IntPtrTy, AlignMask); 4048 Alloc = MIRBuilder.buildAnd(IntPtrTy, Alloc, AlignCst); 4049 } 4050 4051 SPTmp = MIRBuilder.buildCast(PtrTy, Alloc); 4052 MIRBuilder.buildCopy(SPReg, SPTmp); 4053 MIRBuilder.buildCopy(Dst, SPTmp); 4054 4055 MI.eraseFromParent(); 4056 return Legalized; 4057 } 4058