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/TargetInstrInfo.h" 21 #include "llvm/CodeGen/TargetLowering.h" 22 #include "llvm/CodeGen/TargetSubtargetInfo.h" 23 #include "llvm/Support/Debug.h" 24 #include "llvm/Support/MathExtras.h" 25 #include "llvm/Support/raw_ostream.h" 26 27 #define DEBUG_TYPE "legalizer" 28 29 using namespace llvm; 30 using namespace LegalizeActions; 31 32 LegalizerHelper::LegalizerHelper(MachineFunction &MF, 33 GISelChangeObserver &Observer, 34 MachineIRBuilder &Builder) 35 : MIRBuilder(Builder), MRI(MF.getRegInfo()), 36 LI(*MF.getSubtarget().getLegalizerInfo()), Observer(Observer) { 37 MIRBuilder.setMF(MF); 38 MIRBuilder.setChangeObserver(Observer); 39 } 40 41 LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, 42 GISelChangeObserver &Observer, 43 MachineIRBuilder &B) 44 : MIRBuilder(B), MRI(MF.getRegInfo()), LI(LI), Observer(Observer) { 45 MIRBuilder.setMF(MF); 46 MIRBuilder.setChangeObserver(Observer); 47 } 48 LegalizerHelper::LegalizeResult 49 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) { 50 LLVM_DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs())); 51 52 auto Step = LI.getAction(MI, MRI); 53 switch (Step.Action) { 54 case Legal: 55 LLVM_DEBUG(dbgs() << ".. Already legal\n"); 56 return AlreadyLegal; 57 case Libcall: 58 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n"); 59 return libcall(MI); 60 case NarrowScalar: 61 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n"); 62 return narrowScalar(MI, Step.TypeIdx, Step.NewType); 63 case WidenScalar: 64 LLVM_DEBUG(dbgs() << ".. Widen scalar\n"); 65 return widenScalar(MI, Step.TypeIdx, Step.NewType); 66 case Lower: 67 LLVM_DEBUG(dbgs() << ".. Lower\n"); 68 return lower(MI, Step.TypeIdx, Step.NewType); 69 case FewerElements: 70 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n"); 71 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType); 72 case Custom: 73 LLVM_DEBUG(dbgs() << ".. Custom legalization\n"); 74 return LI.legalizeCustom(MI, MRI, MIRBuilder, Observer) ? Legalized 75 : UnableToLegalize; 76 default: 77 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n"); 78 return UnableToLegalize; 79 } 80 } 81 82 void LegalizerHelper::extractParts(unsigned Reg, LLT Ty, int NumParts, 83 SmallVectorImpl<unsigned> &VRegs) { 84 for (int i = 0; i < NumParts; ++i) 85 VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); 86 MIRBuilder.buildUnmerge(VRegs, Reg); 87 } 88 89 bool LegalizerHelper::extractParts(unsigned Reg, LLT RegTy, 90 LLT MainTy, LLT &LeftoverTy, 91 SmallVectorImpl<unsigned> &VRegs, 92 SmallVectorImpl<unsigned> &LeftoverRegs) { 93 assert(!LeftoverTy.isValid() && "this is an out argument"); 94 95 unsigned RegSize = RegTy.getSizeInBits(); 96 unsigned MainSize = MainTy.getSizeInBits(); 97 unsigned NumParts = RegSize / MainSize; 98 unsigned LeftoverSize = RegSize - NumParts * MainSize; 99 100 // Use an unmerge when possible. 101 if (LeftoverSize == 0) { 102 for (unsigned I = 0; I < NumParts; ++I) 103 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy)); 104 MIRBuilder.buildUnmerge(VRegs, Reg); 105 return true; 106 } 107 108 if (MainTy.isVector()) { 109 unsigned EltSize = MainTy.getScalarSizeInBits(); 110 if (LeftoverSize % EltSize != 0) 111 return false; 112 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize); 113 } else { 114 LeftoverTy = LLT::scalar(LeftoverSize); 115 } 116 117 // For irregular sizes, extract the individual parts. 118 for (unsigned I = 0; I != NumParts; ++I) { 119 unsigned NewReg = MRI.createGenericVirtualRegister(MainTy); 120 VRegs.push_back(NewReg); 121 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I); 122 } 123 124 for (unsigned Offset = MainSize * NumParts; Offset < RegSize; 125 Offset += LeftoverSize) { 126 unsigned NewReg = MRI.createGenericVirtualRegister(LeftoverTy); 127 LeftoverRegs.push_back(NewReg); 128 MIRBuilder.buildExtract(NewReg, Reg, Offset); 129 } 130 131 return true; 132 } 133 134 void LegalizerHelper::insertParts(unsigned DstReg, 135 LLT ResultTy, LLT PartTy, 136 ArrayRef<unsigned> PartRegs, 137 LLT LeftoverTy, 138 ArrayRef<unsigned> LeftoverRegs) { 139 if (!LeftoverTy.isValid()) { 140 assert(LeftoverRegs.empty()); 141 142 if (!ResultTy.isVector()) { 143 MIRBuilder.buildMerge(DstReg, PartRegs); 144 return; 145 } 146 147 if (PartTy.isVector()) 148 MIRBuilder.buildConcatVectors(DstReg, PartRegs); 149 else 150 MIRBuilder.buildBuildVector(DstReg, PartRegs); 151 return; 152 } 153 154 unsigned PartSize = PartTy.getSizeInBits(); 155 unsigned LeftoverPartSize = LeftoverTy.getSizeInBits(); 156 157 unsigned CurResultReg = MRI.createGenericVirtualRegister(ResultTy); 158 MIRBuilder.buildUndef(CurResultReg); 159 160 unsigned Offset = 0; 161 for (unsigned PartReg : PartRegs) { 162 unsigned NewResultReg = MRI.createGenericVirtualRegister(ResultTy); 163 MIRBuilder.buildInsert(NewResultReg, CurResultReg, PartReg, Offset); 164 CurResultReg = NewResultReg; 165 Offset += PartSize; 166 } 167 168 for (unsigned I = 0, E = LeftoverRegs.size(); I != E; ++I) { 169 // Use the original output register for the final insert to avoid a copy. 170 unsigned NewResultReg = (I + 1 == E) ? 171 DstReg : MRI.createGenericVirtualRegister(ResultTy); 172 173 MIRBuilder.buildInsert(NewResultReg, CurResultReg, LeftoverRegs[I], Offset); 174 CurResultReg = NewResultReg; 175 Offset += LeftoverPartSize; 176 } 177 } 178 179 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { 180 switch (Opcode) { 181 case TargetOpcode::G_SDIV: 182 assert((Size == 32 || Size == 64) && "Unsupported size"); 183 return Size == 64 ? RTLIB::SDIV_I64 : RTLIB::SDIV_I32; 184 case TargetOpcode::G_UDIV: 185 assert((Size == 32 || Size == 64) && "Unsupported size"); 186 return Size == 64 ? RTLIB::UDIV_I64 : RTLIB::UDIV_I32; 187 case TargetOpcode::G_SREM: 188 assert((Size == 32 || Size == 64) && "Unsupported size"); 189 return Size == 64 ? RTLIB::SREM_I64 : RTLIB::SREM_I32; 190 case TargetOpcode::G_UREM: 191 assert((Size == 32 || Size == 64) && "Unsupported size"); 192 return Size == 64 ? RTLIB::UREM_I64 : RTLIB::UREM_I32; 193 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 194 assert(Size == 32 && "Unsupported size"); 195 return RTLIB::CTLZ_I32; 196 case TargetOpcode::G_FADD: 197 assert((Size == 32 || Size == 64) && "Unsupported size"); 198 return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; 199 case TargetOpcode::G_FSUB: 200 assert((Size == 32 || Size == 64) && "Unsupported size"); 201 return Size == 64 ? RTLIB::SUB_F64 : RTLIB::SUB_F32; 202 case TargetOpcode::G_FMUL: 203 assert((Size == 32 || Size == 64) && "Unsupported size"); 204 return Size == 64 ? RTLIB::MUL_F64 : RTLIB::MUL_F32; 205 case TargetOpcode::G_FDIV: 206 assert((Size == 32 || Size == 64) && "Unsupported size"); 207 return Size == 64 ? RTLIB::DIV_F64 : RTLIB::DIV_F32; 208 case TargetOpcode::G_FEXP: 209 assert((Size == 32 || Size == 64) && "Unsupported size"); 210 return Size == 64 ? RTLIB::EXP_F64 : RTLIB::EXP_F32; 211 case TargetOpcode::G_FREM: 212 return Size == 64 ? RTLIB::REM_F64 : RTLIB::REM_F32; 213 case TargetOpcode::G_FPOW: 214 return Size == 64 ? RTLIB::POW_F64 : RTLIB::POW_F32; 215 case TargetOpcode::G_FMA: 216 assert((Size == 32 || Size == 64) && "Unsupported size"); 217 return Size == 64 ? RTLIB::FMA_F64 : RTLIB::FMA_F32; 218 case TargetOpcode::G_FSIN: 219 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 220 return Size == 128 ? RTLIB::SIN_F128 221 : Size == 64 ? RTLIB::SIN_F64 : RTLIB::SIN_F32; 222 case TargetOpcode::G_FCOS: 223 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 224 return Size == 128 ? RTLIB::COS_F128 225 : Size == 64 ? RTLIB::COS_F64 : RTLIB::COS_F32; 226 case TargetOpcode::G_FLOG10: 227 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 228 return Size == 128 ? RTLIB::LOG10_F128 229 : Size == 64 ? RTLIB::LOG10_F64 : RTLIB::LOG10_F32; 230 case TargetOpcode::G_FLOG: 231 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 232 return Size == 128 ? RTLIB::LOG_F128 233 : Size == 64 ? RTLIB::LOG_F64 : RTLIB::LOG_F32; 234 case TargetOpcode::G_FLOG2: 235 assert((Size == 32 || Size == 64 || Size == 128) && "Unsupported size"); 236 return Size == 128 ? RTLIB::LOG2_F128 237 : Size == 64 ? RTLIB::LOG2_F64 : RTLIB::LOG2_F32; 238 } 239 llvm_unreachable("Unknown libcall function"); 240 } 241 242 LegalizerHelper::LegalizeResult 243 llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, 244 const CallLowering::ArgInfo &Result, 245 ArrayRef<CallLowering::ArgInfo> Args) { 246 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 247 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 248 const char *Name = TLI.getLibcallName(Libcall); 249 250 MIRBuilder.getMF().getFrameInfo().setHasCalls(true); 251 if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall), 252 MachineOperand::CreateES(Name), Result, Args)) 253 return LegalizerHelper::UnableToLegalize; 254 255 return LegalizerHelper::Legalized; 256 } 257 258 // Useful for libcalls where all operands have the same type. 259 static LegalizerHelper::LegalizeResult 260 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, 261 Type *OpType) { 262 auto Libcall = getRTLibDesc(MI.getOpcode(), Size); 263 264 SmallVector<CallLowering::ArgInfo, 3> Args; 265 for (unsigned i = 1; i < MI.getNumOperands(); i++) 266 Args.push_back({MI.getOperand(i).getReg(), OpType}); 267 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), OpType}, 268 Args); 269 } 270 271 static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, 272 Type *FromType) { 273 auto ToMVT = MVT::getVT(ToType); 274 auto FromMVT = MVT::getVT(FromType); 275 276 switch (Opcode) { 277 case TargetOpcode::G_FPEXT: 278 return RTLIB::getFPEXT(FromMVT, ToMVT); 279 case TargetOpcode::G_FPTRUNC: 280 return RTLIB::getFPROUND(FromMVT, ToMVT); 281 case TargetOpcode::G_FPTOSI: 282 return RTLIB::getFPTOSINT(FromMVT, ToMVT); 283 case TargetOpcode::G_FPTOUI: 284 return RTLIB::getFPTOUINT(FromMVT, ToMVT); 285 case TargetOpcode::G_SITOFP: 286 return RTLIB::getSINTTOFP(FromMVT, ToMVT); 287 case TargetOpcode::G_UITOFP: 288 return RTLIB::getUINTTOFP(FromMVT, ToMVT); 289 } 290 llvm_unreachable("Unsupported libcall function"); 291 } 292 293 static LegalizerHelper::LegalizeResult 294 conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, 295 Type *FromType) { 296 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType); 297 return createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ToType}, 298 {{MI.getOperand(1).getReg(), FromType}}); 299 } 300 301 LegalizerHelper::LegalizeResult 302 LegalizerHelper::libcall(MachineInstr &MI) { 303 LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); 304 unsigned Size = LLTy.getSizeInBits(); 305 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 306 307 MIRBuilder.setInstr(MI); 308 309 switch (MI.getOpcode()) { 310 default: 311 return UnableToLegalize; 312 case TargetOpcode::G_SDIV: 313 case TargetOpcode::G_UDIV: 314 case TargetOpcode::G_SREM: 315 case TargetOpcode::G_UREM: 316 case TargetOpcode::G_CTLZ_ZERO_UNDEF: { 317 Type *HLTy = IntegerType::get(Ctx, Size); 318 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 319 if (Status != Legalized) 320 return Status; 321 break; 322 } 323 case TargetOpcode::G_FADD: 324 case TargetOpcode::G_FSUB: 325 case TargetOpcode::G_FMUL: 326 case TargetOpcode::G_FDIV: 327 case TargetOpcode::G_FMA: 328 case TargetOpcode::G_FPOW: 329 case TargetOpcode::G_FREM: 330 case TargetOpcode::G_FCOS: 331 case TargetOpcode::G_FSIN: 332 case TargetOpcode::G_FLOG10: 333 case TargetOpcode::G_FLOG: 334 case TargetOpcode::G_FLOG2: 335 case TargetOpcode::G_FEXP: { 336 if (Size > 64) { 337 LLVM_DEBUG(dbgs() << "Size " << Size << " too large to legalize.\n"); 338 return UnableToLegalize; 339 } 340 Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); 341 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 342 if (Status != Legalized) 343 return Status; 344 break; 345 } 346 case TargetOpcode::G_FPEXT: { 347 // FIXME: Support other floating point types (half, fp128 etc) 348 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 349 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 350 if (ToSize != 64 || FromSize != 32) 351 return UnableToLegalize; 352 LegalizeResult Status = conversionLibcall( 353 MI, MIRBuilder, Type::getDoubleTy(Ctx), Type::getFloatTy(Ctx)); 354 if (Status != Legalized) 355 return Status; 356 break; 357 } 358 case TargetOpcode::G_FPTRUNC: { 359 // FIXME: Support other floating point types (half, fp128 etc) 360 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 361 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 362 if (ToSize != 32 || FromSize != 64) 363 return UnableToLegalize; 364 LegalizeResult Status = conversionLibcall( 365 MI, MIRBuilder, Type::getFloatTy(Ctx), Type::getDoubleTy(Ctx)); 366 if (Status != Legalized) 367 return Status; 368 break; 369 } 370 case TargetOpcode::G_FPTOSI: 371 case TargetOpcode::G_FPTOUI: { 372 // FIXME: Support other types 373 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 374 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 375 if (ToSize != 32 || (FromSize != 32 && FromSize != 64)) 376 return UnableToLegalize; 377 LegalizeResult Status = conversionLibcall( 378 MI, MIRBuilder, Type::getInt32Ty(Ctx), 379 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx)); 380 if (Status != Legalized) 381 return Status; 382 break; 383 } 384 case TargetOpcode::G_SITOFP: 385 case TargetOpcode::G_UITOFP: { 386 // FIXME: Support other types 387 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 388 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 389 if (FromSize != 32 || (ToSize != 32 && ToSize != 64)) 390 return UnableToLegalize; 391 LegalizeResult Status = conversionLibcall( 392 MI, MIRBuilder, 393 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx), 394 Type::getInt32Ty(Ctx)); 395 if (Status != Legalized) 396 return Status; 397 break; 398 } 399 } 400 401 MI.eraseFromParent(); 402 return Legalized; 403 } 404 405 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 406 unsigned TypeIdx, 407 LLT NarrowTy) { 408 MIRBuilder.setInstr(MI); 409 410 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 411 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 412 413 switch (MI.getOpcode()) { 414 default: 415 return UnableToLegalize; 416 case TargetOpcode::G_IMPLICIT_DEF: { 417 // FIXME: add support for when SizeOp0 isn't an exact multiple of 418 // NarrowSize. 419 if (SizeOp0 % NarrowSize != 0) 420 return UnableToLegalize; 421 int NumParts = SizeOp0 / NarrowSize; 422 423 SmallVector<unsigned, 2> DstRegs; 424 for (int i = 0; i < NumParts; ++i) 425 DstRegs.push_back( 426 MIRBuilder.buildUndef(NarrowTy)->getOperand(0).getReg()); 427 428 unsigned DstReg = MI.getOperand(0).getReg(); 429 if(MRI.getType(DstReg).isVector()) 430 MIRBuilder.buildBuildVector(DstReg, DstRegs); 431 else 432 MIRBuilder.buildMerge(DstReg, DstRegs); 433 MI.eraseFromParent(); 434 return Legalized; 435 } 436 case TargetOpcode::G_ADD: { 437 // FIXME: add support for when SizeOp0 isn't an exact multiple of 438 // NarrowSize. 439 if (SizeOp0 % NarrowSize != 0) 440 return UnableToLegalize; 441 // Expand in terms of carry-setting/consuming G_ADDE instructions. 442 int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); 443 444 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 445 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 446 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 447 448 unsigned CarryIn = MRI.createGenericVirtualRegister(LLT::scalar(1)); 449 MIRBuilder.buildConstant(CarryIn, 0); 450 451 for (int i = 0; i < NumParts; ++i) { 452 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 453 unsigned CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 454 455 MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], 456 Src2Regs[i], CarryIn); 457 458 DstRegs.push_back(DstReg); 459 CarryIn = CarryOut; 460 } 461 unsigned DstReg = MI.getOperand(0).getReg(); 462 if(MRI.getType(DstReg).isVector()) 463 MIRBuilder.buildBuildVector(DstReg, DstRegs); 464 else 465 MIRBuilder.buildMerge(DstReg, DstRegs); 466 MI.eraseFromParent(); 467 return Legalized; 468 } 469 case TargetOpcode::G_SUB: { 470 // FIXME: add support for when SizeOp0 isn't an exact multiple of 471 // NarrowSize. 472 if (SizeOp0 % NarrowSize != 0) 473 return UnableToLegalize; 474 475 int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); 476 477 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 478 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); 479 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); 480 481 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 482 unsigned BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 483 MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut}, 484 {Src1Regs[0], Src2Regs[0]}); 485 DstRegs.push_back(DstReg); 486 unsigned BorrowIn = BorrowOut; 487 for (int i = 1; i < NumParts; ++i) { 488 DstReg = MRI.createGenericVirtualRegister(NarrowTy); 489 BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 490 491 MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut}, 492 {Src1Regs[i], Src2Regs[i], BorrowIn}); 493 494 DstRegs.push_back(DstReg); 495 BorrowIn = BorrowOut; 496 } 497 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), DstRegs); 498 MI.eraseFromParent(); 499 return Legalized; 500 } 501 case TargetOpcode::G_MUL: 502 return narrowScalarMul(MI, TypeIdx, NarrowTy); 503 case TargetOpcode::G_EXTRACT: { 504 if (TypeIdx != 1) 505 return UnableToLegalize; 506 507 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 508 // FIXME: add support for when SizeOp1 isn't an exact multiple of 509 // NarrowSize. 510 if (SizeOp1 % NarrowSize != 0) 511 return UnableToLegalize; 512 int NumParts = SizeOp1 / NarrowSize; 513 514 SmallVector<unsigned, 2> SrcRegs, DstRegs; 515 SmallVector<uint64_t, 2> Indexes; 516 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 517 518 unsigned OpReg = MI.getOperand(0).getReg(); 519 uint64_t OpStart = MI.getOperand(2).getImm(); 520 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 521 for (int i = 0; i < NumParts; ++i) { 522 unsigned SrcStart = i * NarrowSize; 523 524 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) { 525 // No part of the extract uses this subregister, ignore it. 526 continue; 527 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 528 // The entire subregister is extracted, forward the value. 529 DstRegs.push_back(SrcRegs[i]); 530 continue; 531 } 532 533 // OpSegStart is where this destination segment would start in OpReg if it 534 // extended infinitely in both directions. 535 int64_t ExtractOffset; 536 uint64_t SegSize; 537 if (OpStart < SrcStart) { 538 ExtractOffset = 0; 539 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart); 540 } else { 541 ExtractOffset = OpStart - SrcStart; 542 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize); 543 } 544 545 unsigned SegReg = SrcRegs[i]; 546 if (ExtractOffset != 0 || SegSize != NarrowSize) { 547 // A genuine extract is needed. 548 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 549 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset); 550 } 551 552 DstRegs.push_back(SegReg); 553 } 554 555 unsigned DstReg = MI.getOperand(0).getReg(); 556 if(MRI.getType(DstReg).isVector()) 557 MIRBuilder.buildBuildVector(DstReg, DstRegs); 558 else 559 MIRBuilder.buildMerge(DstReg, DstRegs); 560 MI.eraseFromParent(); 561 return Legalized; 562 } 563 case TargetOpcode::G_INSERT: { 564 // FIXME: Don't know how to handle secondary types yet. 565 if (TypeIdx != 0) 566 return UnableToLegalize; 567 568 // FIXME: add support for when SizeOp0 isn't an exact multiple of 569 // NarrowSize. 570 if (SizeOp0 % NarrowSize != 0) 571 return UnableToLegalize; 572 573 int NumParts = SizeOp0 / NarrowSize; 574 575 SmallVector<unsigned, 2> SrcRegs, DstRegs; 576 SmallVector<uint64_t, 2> Indexes; 577 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 578 579 unsigned OpReg = MI.getOperand(2).getReg(); 580 uint64_t OpStart = MI.getOperand(3).getImm(); 581 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 582 for (int i = 0; i < NumParts; ++i) { 583 unsigned DstStart = i * NarrowSize; 584 585 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { 586 // No part of the insert affects this subregister, forward the original. 587 DstRegs.push_back(SrcRegs[i]); 588 continue; 589 } else if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 590 // The entire subregister is defined by this insert, forward the new 591 // value. 592 DstRegs.push_back(OpReg); 593 continue; 594 } 595 596 // OpSegStart is where this destination segment would start in OpReg if it 597 // extended infinitely in both directions. 598 int64_t ExtractOffset, InsertOffset; 599 uint64_t SegSize; 600 if (OpStart < DstStart) { 601 InsertOffset = 0; 602 ExtractOffset = DstStart - OpStart; 603 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); 604 } else { 605 InsertOffset = OpStart - DstStart; 606 ExtractOffset = 0; 607 SegSize = 608 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); 609 } 610 611 unsigned SegReg = OpReg; 612 if (ExtractOffset != 0 || SegSize != OpSize) { 613 // A genuine extract is needed. 614 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 615 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); 616 } 617 618 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 619 MIRBuilder.buildInsert(DstReg, SrcRegs[i], SegReg, InsertOffset); 620 DstRegs.push_back(DstReg); 621 } 622 623 assert(DstRegs.size() == (unsigned)NumParts && "not all parts covered"); 624 unsigned DstReg = MI.getOperand(0).getReg(); 625 if(MRI.getType(DstReg).isVector()) 626 MIRBuilder.buildBuildVector(DstReg, DstRegs); 627 else 628 MIRBuilder.buildMerge(DstReg, DstRegs); 629 MI.eraseFromParent(); 630 return Legalized; 631 } 632 case TargetOpcode::G_LOAD: { 633 const auto &MMO = **MI.memoperands_begin(); 634 unsigned DstReg = MI.getOperand(0).getReg(); 635 LLT DstTy = MRI.getType(DstReg); 636 if (DstTy.isVector()) 637 return UnableToLegalize; 638 639 if (8 * MMO.getSize() != DstTy.getSizeInBits()) { 640 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 641 auto &MMO = **MI.memoperands_begin(); 642 MIRBuilder.buildLoad(TmpReg, MI.getOperand(1).getReg(), MMO); 643 MIRBuilder.buildAnyExt(DstReg, TmpReg); 644 MI.eraseFromParent(); 645 return Legalized; 646 } 647 648 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy); 649 } 650 case TargetOpcode::G_ZEXTLOAD: 651 case TargetOpcode::G_SEXTLOAD: { 652 bool ZExt = MI.getOpcode() == TargetOpcode::G_ZEXTLOAD; 653 unsigned DstReg = MI.getOperand(0).getReg(); 654 unsigned PtrReg = MI.getOperand(1).getReg(); 655 656 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 657 auto &MMO = **MI.memoperands_begin(); 658 if (MMO.getSize() * 8 == NarrowSize) { 659 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); 660 } else { 661 unsigned ExtLoad = ZExt ? TargetOpcode::G_ZEXTLOAD 662 : TargetOpcode::G_SEXTLOAD; 663 MIRBuilder.buildInstr(ExtLoad) 664 .addDef(TmpReg) 665 .addUse(PtrReg) 666 .addMemOperand(&MMO); 667 } 668 669 if (ZExt) 670 MIRBuilder.buildZExt(DstReg, TmpReg); 671 else 672 MIRBuilder.buildSExt(DstReg, TmpReg); 673 674 MI.eraseFromParent(); 675 return Legalized; 676 } 677 case TargetOpcode::G_STORE: { 678 const auto &MMO = **MI.memoperands_begin(); 679 680 unsigned SrcReg = MI.getOperand(0).getReg(); 681 LLT SrcTy = MRI.getType(SrcReg); 682 if (SrcTy.isVector()) 683 return UnableToLegalize; 684 685 int NumParts = SizeOp0 / NarrowSize; 686 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits(); 687 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize; 688 if (SrcTy.isVector() && LeftoverBits != 0) 689 return UnableToLegalize; 690 691 if (8 * MMO.getSize() != SrcTy.getSizeInBits()) { 692 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 693 auto &MMO = **MI.memoperands_begin(); 694 MIRBuilder.buildTrunc(TmpReg, SrcReg); 695 MIRBuilder.buildStore(TmpReg, MI.getOperand(1).getReg(), MMO); 696 MI.eraseFromParent(); 697 return Legalized; 698 } 699 700 return reduceLoadStoreWidth(MI, 0, NarrowTy); 701 } 702 case TargetOpcode::G_CONSTANT: { 703 // FIXME: add support for when SizeOp0 isn't an exact multiple of 704 // NarrowSize. 705 if (SizeOp0 % NarrowSize != 0) 706 return UnableToLegalize; 707 int NumParts = SizeOp0 / NarrowSize; 708 const APInt &Cst = MI.getOperand(1).getCImm()->getValue(); 709 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 710 711 SmallVector<unsigned, 2> DstRegs; 712 for (int i = 0; i < NumParts; ++i) { 713 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 714 ConstantInt *CI = 715 ConstantInt::get(Ctx, Cst.lshr(NarrowSize * i).trunc(NarrowSize)); 716 MIRBuilder.buildConstant(DstReg, *CI); 717 DstRegs.push_back(DstReg); 718 } 719 unsigned DstReg = MI.getOperand(0).getReg(); 720 if(MRI.getType(DstReg).isVector()) 721 MIRBuilder.buildBuildVector(DstReg, DstRegs); 722 else 723 MIRBuilder.buildMerge(DstReg, DstRegs); 724 MI.eraseFromParent(); 725 return Legalized; 726 } 727 case TargetOpcode::G_SELECT: 728 return narrowScalarSelect(MI, TypeIdx, NarrowTy); 729 case TargetOpcode::G_AND: 730 case TargetOpcode::G_OR: 731 case TargetOpcode::G_XOR: { 732 // Legalize bitwise operation: 733 // A = BinOp<Ty> B, C 734 // into: 735 // B1, ..., BN = G_UNMERGE_VALUES B 736 // C1, ..., CN = G_UNMERGE_VALUES C 737 // A1 = BinOp<Ty/N> B1, C2 738 // ... 739 // AN = BinOp<Ty/N> BN, CN 740 // A = G_MERGE_VALUES A1, ..., AN 741 742 // FIXME: add support for when SizeOp0 isn't an exact multiple of 743 // NarrowSize. 744 if (SizeOp0 % NarrowSize != 0) 745 return UnableToLegalize; 746 int NumParts = SizeOp0 / NarrowSize; 747 748 // List the registers where the destination will be scattered. 749 SmallVector<unsigned, 2> DstRegs; 750 // List the registers where the first argument will be split. 751 SmallVector<unsigned, 2> SrcsReg1; 752 // List the registers where the second argument will be split. 753 SmallVector<unsigned, 2> SrcsReg2; 754 // Create all the temporary registers. 755 for (int i = 0; i < NumParts; ++i) { 756 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 757 unsigned SrcReg1 = MRI.createGenericVirtualRegister(NarrowTy); 758 unsigned SrcReg2 = MRI.createGenericVirtualRegister(NarrowTy); 759 760 DstRegs.push_back(DstReg); 761 SrcsReg1.push_back(SrcReg1); 762 SrcsReg2.push_back(SrcReg2); 763 } 764 // Explode the big arguments into smaller chunks. 765 MIRBuilder.buildUnmerge(SrcsReg1, MI.getOperand(1).getReg()); 766 MIRBuilder.buildUnmerge(SrcsReg2, MI.getOperand(2).getReg()); 767 768 // Do the operation on each small part. 769 for (int i = 0; i < NumParts; ++i) 770 MIRBuilder.buildInstr(MI.getOpcode(), {DstRegs[i]}, 771 {SrcsReg1[i], SrcsReg2[i]}); 772 773 // Gather the destination registers into the final destination. 774 unsigned DstReg = MI.getOperand(0).getReg(); 775 if(MRI.getType(DstReg).isVector()) 776 MIRBuilder.buildBuildVector(DstReg, DstRegs); 777 else 778 MIRBuilder.buildMerge(DstReg, DstRegs); 779 MI.eraseFromParent(); 780 return Legalized; 781 } 782 case TargetOpcode::G_SHL: 783 case TargetOpcode::G_LSHR: 784 case TargetOpcode::G_ASHR: { 785 if (TypeIdx != 1) 786 return UnableToLegalize; // TODO 787 Observer.changingInstr(MI); 788 narrowScalarSrc(MI, NarrowTy, 2); 789 Observer.changedInstr(MI); 790 return Legalized; 791 } 792 case TargetOpcode::G_CTLZ: 793 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 794 case TargetOpcode::G_CTTZ: 795 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 796 case TargetOpcode::G_CTPOP: 797 if (TypeIdx != 0) 798 return UnableToLegalize; // TODO 799 800 Observer.changingInstr(MI); 801 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT); 802 Observer.changedInstr(MI); 803 return Legalized; 804 case TargetOpcode::G_INTTOPTR: 805 if (TypeIdx != 1) 806 return UnableToLegalize; 807 808 Observer.changingInstr(MI); 809 narrowScalarSrc(MI, NarrowTy, 1); 810 Observer.changedInstr(MI); 811 return Legalized; 812 case TargetOpcode::G_PTRTOINT: 813 if (TypeIdx != 0) 814 return UnableToLegalize; 815 816 Observer.changingInstr(MI); 817 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT); 818 Observer.changedInstr(MI); 819 return Legalized; 820 } 821 } 822 823 void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy, 824 unsigned OpIdx, unsigned ExtOpcode) { 825 MachineOperand &MO = MI.getOperand(OpIdx); 826 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO.getReg()}); 827 MO.setReg(ExtB->getOperand(0).getReg()); 828 } 829 830 void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, 831 unsigned OpIdx) { 832 MachineOperand &MO = MI.getOperand(OpIdx); 833 auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_TRUNC, {NarrowTy}, 834 {MO.getReg()}); 835 MO.setReg(ExtB->getOperand(0).getReg()); 836 } 837 838 void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy, 839 unsigned OpIdx, unsigned TruncOpcode) { 840 MachineOperand &MO = MI.getOperand(OpIdx); 841 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 842 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 843 MIRBuilder.buildInstr(TruncOpcode, {MO.getReg()}, {DstExt}); 844 MO.setReg(DstExt); 845 } 846 847 void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy, 848 unsigned OpIdx, unsigned ExtOpcode) { 849 MachineOperand &MO = MI.getOperand(OpIdx); 850 unsigned DstTrunc = MRI.createGenericVirtualRegister(NarrowTy); 851 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 852 MIRBuilder.buildInstr(ExtOpcode, {MO.getReg()}, {DstTrunc}); 853 MO.setReg(DstTrunc); 854 } 855 856 LegalizerHelper::LegalizeResult 857 LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, 858 LLT WideTy) { 859 if (TypeIdx != 1) 860 return UnableToLegalize; 861 862 unsigned DstReg = MI.getOperand(0).getReg(); 863 LLT DstTy = MRI.getType(DstReg); 864 if (!DstTy.isScalar()) 865 return UnableToLegalize; 866 867 unsigned NumOps = MI.getNumOperands(); 868 unsigned NumSrc = MI.getNumOperands() - 1; 869 unsigned PartSize = DstTy.getSizeInBits() / NumSrc; 870 871 unsigned Src1 = MI.getOperand(1).getReg(); 872 unsigned ResultReg = MIRBuilder.buildZExt(DstTy, Src1)->getOperand(0).getReg(); 873 874 for (unsigned I = 2; I != NumOps; ++I) { 875 const unsigned Offset = (I - 1) * PartSize; 876 877 unsigned SrcReg = MI.getOperand(I).getReg(); 878 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize)); 879 880 auto ZextInput = MIRBuilder.buildZExt(DstTy, SrcReg); 881 882 unsigned NextResult = I + 1 == NumOps ? DstReg : 883 MRI.createGenericVirtualRegister(DstTy); 884 885 auto ShiftAmt = MIRBuilder.buildConstant(DstTy, Offset); 886 auto Shl = MIRBuilder.buildShl(DstTy, ZextInput, ShiftAmt); 887 MIRBuilder.buildOr(NextResult, ResultReg, Shl); 888 ResultReg = NextResult; 889 } 890 891 MI.eraseFromParent(); 892 return Legalized; 893 } 894 895 LegalizerHelper::LegalizeResult 896 LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, 897 LLT WideTy) { 898 if (TypeIdx != 0) 899 return UnableToLegalize; 900 901 unsigned NumDst = MI.getNumOperands() - 1; 902 unsigned SrcReg = MI.getOperand(NumDst).getReg(); 903 LLT SrcTy = MRI.getType(SrcReg); 904 if (!SrcTy.isScalar()) 905 return UnableToLegalize; 906 907 unsigned Dst0Reg = MI.getOperand(0).getReg(); 908 LLT DstTy = MRI.getType(Dst0Reg); 909 if (!DstTy.isScalar()) 910 return UnableToLegalize; 911 912 unsigned NewSrcSize = NumDst * WideTy.getSizeInBits(); 913 LLT NewSrcTy = LLT::scalar(NewSrcSize); 914 unsigned SizeDiff = WideTy.getSizeInBits() - DstTy.getSizeInBits(); 915 916 auto WideSrc = MIRBuilder.buildZExt(NewSrcTy, SrcReg); 917 918 for (unsigned I = 1; I != NumDst; ++I) { 919 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, SizeDiff * I); 920 auto Shl = MIRBuilder.buildShl(NewSrcTy, WideSrc, ShiftAmt); 921 WideSrc = MIRBuilder.buildOr(NewSrcTy, WideSrc, Shl); 922 } 923 924 Observer.changingInstr(MI); 925 926 MI.getOperand(NumDst).setReg(WideSrc->getOperand(0).getReg()); 927 for (unsigned I = 0; I != NumDst; ++I) 928 widenScalarDst(MI, WideTy, I); 929 930 Observer.changedInstr(MI); 931 932 return Legalized; 933 } 934 935 LegalizerHelper::LegalizeResult 936 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 937 MIRBuilder.setInstr(MI); 938 939 switch (MI.getOpcode()) { 940 default: 941 return UnableToLegalize; 942 case TargetOpcode::G_EXTRACT: { 943 if (TypeIdx != 1) 944 return UnableToLegalize; 945 946 unsigned SrcReg = MI.getOperand(1).getReg(); 947 LLT SrcTy = MRI.getType(SrcReg); 948 if (!SrcTy.isVector()) 949 return UnableToLegalize; 950 951 unsigned DstReg = MI.getOperand(0).getReg(); 952 LLT DstTy = MRI.getType(DstReg); 953 if (DstTy != SrcTy.getElementType()) 954 return UnableToLegalize; 955 956 unsigned Offset = MI.getOperand(2).getImm(); 957 if (Offset % SrcTy.getScalarSizeInBits() != 0) 958 return UnableToLegalize; 959 960 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 961 962 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) * 963 Offset); 964 widenScalarDst(MI, WideTy.getScalarType(), 0); 965 966 return Legalized; 967 } 968 case TargetOpcode::G_MERGE_VALUES: 969 return widenScalarMergeValues(MI, TypeIdx, WideTy); 970 case TargetOpcode::G_UNMERGE_VALUES: 971 return widenScalarUnmergeValues(MI, TypeIdx, WideTy); 972 case TargetOpcode::G_UADDO: 973 case TargetOpcode::G_USUBO: { 974 if (TypeIdx == 1) 975 return UnableToLegalize; // TODO 976 auto LHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy}, 977 {MI.getOperand(2).getReg()}); 978 auto RHSZext = MIRBuilder.buildInstr(TargetOpcode::G_ZEXT, {WideTy}, 979 {MI.getOperand(3).getReg()}); 980 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_UADDO 981 ? TargetOpcode::G_ADD 982 : TargetOpcode::G_SUB; 983 // Do the arithmetic in the larger type. 984 auto NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSZext, RHSZext}); 985 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg()); 986 APInt Mask = APInt::getAllOnesValue(OrigTy.getSizeInBits()); 987 auto AndOp = MIRBuilder.buildInstr( 988 TargetOpcode::G_AND, {WideTy}, 989 {NewOp, MIRBuilder.buildConstant(WideTy, Mask.getZExtValue())}); 990 // There is no overflow if the AndOp is the same as NewOp. 991 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1).getReg(), NewOp, 992 AndOp); 993 // Now trunc the NewOp to the original result. 994 MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), NewOp); 995 MI.eraseFromParent(); 996 return Legalized; 997 } 998 case TargetOpcode::G_CTTZ: 999 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 1000 case TargetOpcode::G_CTLZ: 1001 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 1002 case TargetOpcode::G_CTPOP: { 1003 if (TypeIdx == 0) { 1004 Observer.changingInstr(MI); 1005 widenScalarDst(MI, WideTy, 0); 1006 Observer.changedInstr(MI); 1007 return Legalized; 1008 } 1009 1010 unsigned SrcReg = MI.getOperand(1).getReg(); 1011 1012 // First ZEXT the input. 1013 auto MIBSrc = MIRBuilder.buildZExt(WideTy, SrcReg); 1014 LLT CurTy = MRI.getType(SrcReg); 1015 if (MI.getOpcode() == TargetOpcode::G_CTTZ) { 1016 // The count is the same in the larger type except if the original 1017 // value was zero. This can be handled by setting the bit just off 1018 // the top of the original type. 1019 auto TopBit = 1020 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits()); 1021 MIBSrc = MIRBuilder.buildOr( 1022 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit)); 1023 } 1024 1025 // Perform the operation at the larger size. 1026 auto MIBNewOp = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, {MIBSrc}); 1027 // This is already the correct result for CTPOP and CTTZs 1028 if (MI.getOpcode() == TargetOpcode::G_CTLZ || 1029 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) { 1030 // The correct result is NewOp - (Difference in widety and current ty). 1031 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits(); 1032 MIBNewOp = MIRBuilder.buildInstr( 1033 TargetOpcode::G_SUB, {WideTy}, 1034 {MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)}); 1035 } 1036 1037 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp); 1038 MI.eraseFromParent(); 1039 return Legalized; 1040 } 1041 case TargetOpcode::G_BSWAP: { 1042 Observer.changingInstr(MI); 1043 unsigned DstReg = MI.getOperand(0).getReg(); 1044 1045 unsigned ShrReg = MRI.createGenericVirtualRegister(WideTy); 1046 unsigned DstExt = MRI.createGenericVirtualRegister(WideTy); 1047 unsigned ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy); 1048 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1049 1050 MI.getOperand(0).setReg(DstExt); 1051 1052 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1053 1054 LLT Ty = MRI.getType(DstReg); 1055 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits(); 1056 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits); 1057 MIRBuilder.buildInstr(TargetOpcode::G_LSHR) 1058 .addDef(ShrReg) 1059 .addUse(DstExt) 1060 .addUse(ShiftAmtReg); 1061 1062 MIRBuilder.buildTrunc(DstReg, ShrReg); 1063 Observer.changedInstr(MI); 1064 return Legalized; 1065 } 1066 case TargetOpcode::G_ADD: 1067 case TargetOpcode::G_AND: 1068 case TargetOpcode::G_MUL: 1069 case TargetOpcode::G_OR: 1070 case TargetOpcode::G_XOR: 1071 case TargetOpcode::G_SUB: 1072 // Perform operation at larger width (any extension is fine here, high bits 1073 // don't affect the result) and then truncate the result back to the 1074 // original type. 1075 Observer.changingInstr(MI); 1076 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1077 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 1078 widenScalarDst(MI, WideTy); 1079 Observer.changedInstr(MI); 1080 return Legalized; 1081 1082 case TargetOpcode::G_SHL: 1083 Observer.changingInstr(MI); 1084 1085 if (TypeIdx == 0) { 1086 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1087 widenScalarDst(MI, WideTy); 1088 } else { 1089 assert(TypeIdx == 1); 1090 // The "number of bits to shift" operand must preserve its value as an 1091 // unsigned integer: 1092 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 1093 } 1094 1095 Observer.changedInstr(MI); 1096 return Legalized; 1097 1098 case TargetOpcode::G_SDIV: 1099 case TargetOpcode::G_SREM: 1100 Observer.changingInstr(MI); 1101 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 1102 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 1103 widenScalarDst(MI, WideTy); 1104 Observer.changedInstr(MI); 1105 return Legalized; 1106 1107 case TargetOpcode::G_ASHR: 1108 case TargetOpcode::G_LSHR: 1109 Observer.changingInstr(MI); 1110 1111 if (TypeIdx == 0) { 1112 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ? 1113 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT; 1114 1115 widenScalarSrc(MI, WideTy, 1, CvtOp); 1116 widenScalarDst(MI, WideTy); 1117 } else { 1118 assert(TypeIdx == 1); 1119 // The "number of bits to shift" operand must preserve its value as an 1120 // unsigned integer: 1121 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 1122 } 1123 1124 Observer.changedInstr(MI); 1125 return Legalized; 1126 case TargetOpcode::G_UDIV: 1127 case TargetOpcode::G_UREM: 1128 Observer.changingInstr(MI); 1129 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 1130 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 1131 widenScalarDst(MI, WideTy); 1132 Observer.changedInstr(MI); 1133 return Legalized; 1134 1135 case TargetOpcode::G_SELECT: 1136 Observer.changingInstr(MI); 1137 if (TypeIdx == 0) { 1138 // Perform operation at larger width (any extension is fine here, high 1139 // bits don't affect the result) and then truncate the result back to the 1140 // original type. 1141 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 1142 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT); 1143 widenScalarDst(MI, WideTy); 1144 } else { 1145 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector(); 1146 // Explicit extension is required here since high bits affect the result. 1147 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false)); 1148 } 1149 Observer.changedInstr(MI); 1150 return Legalized; 1151 1152 case TargetOpcode::G_FPTOSI: 1153 case TargetOpcode::G_FPTOUI: 1154 if (TypeIdx != 0) 1155 return UnableToLegalize; 1156 Observer.changingInstr(MI); 1157 widenScalarDst(MI, WideTy); 1158 Observer.changedInstr(MI); 1159 return Legalized; 1160 1161 case TargetOpcode::G_SITOFP: 1162 if (TypeIdx != 1) 1163 return UnableToLegalize; 1164 Observer.changingInstr(MI); 1165 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 1166 Observer.changedInstr(MI); 1167 return Legalized; 1168 1169 case TargetOpcode::G_UITOFP: 1170 if (TypeIdx != 1) 1171 return UnableToLegalize; 1172 Observer.changingInstr(MI); 1173 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 1174 Observer.changedInstr(MI); 1175 return Legalized; 1176 1177 case TargetOpcode::G_INSERT: 1178 if (TypeIdx != 0) 1179 return UnableToLegalize; 1180 Observer.changingInstr(MI); 1181 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1182 widenScalarDst(MI, WideTy); 1183 Observer.changedInstr(MI); 1184 return Legalized; 1185 1186 case TargetOpcode::G_LOAD: 1187 // For some types like i24, we might try to widen to i32. To properly handle 1188 // this we should be using a dedicated extending load, until then avoid 1189 // trying to legalize. 1190 if (alignTo(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(), 8) != 1191 WideTy.getSizeInBits()) 1192 return UnableToLegalize; 1193 LLVM_FALLTHROUGH; 1194 case TargetOpcode::G_SEXTLOAD: 1195 case TargetOpcode::G_ZEXTLOAD: 1196 Observer.changingInstr(MI); 1197 widenScalarDst(MI, WideTy); 1198 Observer.changedInstr(MI); 1199 return Legalized; 1200 1201 case TargetOpcode::G_STORE: { 1202 if (TypeIdx != 0) 1203 return UnableToLegalize; 1204 1205 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 1206 if (!isPowerOf2_32(Ty.getSizeInBits())) 1207 return UnableToLegalize; 1208 1209 Observer.changingInstr(MI); 1210 1211 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ? 1212 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT; 1213 widenScalarSrc(MI, WideTy, 0, ExtType); 1214 1215 Observer.changedInstr(MI); 1216 return Legalized; 1217 } 1218 case TargetOpcode::G_CONSTANT: { 1219 MachineOperand &SrcMO = MI.getOperand(1); 1220 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 1221 const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits()); 1222 Observer.changingInstr(MI); 1223 SrcMO.setCImm(ConstantInt::get(Ctx, Val)); 1224 1225 widenScalarDst(MI, WideTy); 1226 Observer.changedInstr(MI); 1227 return Legalized; 1228 } 1229 case TargetOpcode::G_FCONSTANT: { 1230 MachineOperand &SrcMO = MI.getOperand(1); 1231 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 1232 APFloat Val = SrcMO.getFPImm()->getValueAPF(); 1233 bool LosesInfo; 1234 switch (WideTy.getSizeInBits()) { 1235 case 32: 1236 Val.convert(APFloat::IEEEsingle(), APFloat::rmTowardZero, &LosesInfo); 1237 break; 1238 case 64: 1239 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo); 1240 break; 1241 default: 1242 llvm_unreachable("Unhandled fp widen type"); 1243 } 1244 Observer.changingInstr(MI); 1245 SrcMO.setFPImm(ConstantFP::get(Ctx, Val)); 1246 1247 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 1248 Observer.changedInstr(MI); 1249 return Legalized; 1250 } 1251 case TargetOpcode::G_IMPLICIT_DEF: { 1252 Observer.changingInstr(MI); 1253 widenScalarDst(MI, WideTy); 1254 Observer.changedInstr(MI); 1255 return Legalized; 1256 } 1257 case TargetOpcode::G_BRCOND: 1258 Observer.changingInstr(MI); 1259 widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT); 1260 Observer.changedInstr(MI); 1261 return Legalized; 1262 1263 case TargetOpcode::G_FCMP: 1264 Observer.changingInstr(MI); 1265 if (TypeIdx == 0) 1266 widenScalarDst(MI, WideTy); 1267 else { 1268 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT); 1269 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT); 1270 } 1271 Observer.changedInstr(MI); 1272 return Legalized; 1273 1274 case TargetOpcode::G_ICMP: 1275 Observer.changingInstr(MI); 1276 if (TypeIdx == 0) 1277 widenScalarDst(MI, WideTy); 1278 else { 1279 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>( 1280 MI.getOperand(1).getPredicate())) 1281 ? TargetOpcode::G_SEXT 1282 : TargetOpcode::G_ZEXT; 1283 widenScalarSrc(MI, WideTy, 2, ExtOpcode); 1284 widenScalarSrc(MI, WideTy, 3, ExtOpcode); 1285 } 1286 Observer.changedInstr(MI); 1287 return Legalized; 1288 1289 case TargetOpcode::G_GEP: 1290 assert(TypeIdx == 1 && "unable to legalize pointer of GEP"); 1291 Observer.changingInstr(MI); 1292 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 1293 Observer.changedInstr(MI); 1294 return Legalized; 1295 1296 case TargetOpcode::G_PHI: { 1297 assert(TypeIdx == 0 && "Expecting only Idx 0"); 1298 1299 Observer.changingInstr(MI); 1300 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) { 1301 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB(); 1302 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 1303 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT); 1304 } 1305 1306 MachineBasicBlock &MBB = *MI.getParent(); 1307 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI()); 1308 widenScalarDst(MI, WideTy); 1309 Observer.changedInstr(MI); 1310 return Legalized; 1311 } 1312 case TargetOpcode::G_EXTRACT_VECTOR_ELT: { 1313 if (TypeIdx == 0) { 1314 unsigned VecReg = MI.getOperand(1).getReg(); 1315 LLT VecTy = MRI.getType(VecReg); 1316 Observer.changingInstr(MI); 1317 1318 widenScalarSrc(MI, LLT::vector(VecTy.getNumElements(), 1319 WideTy.getSizeInBits()), 1320 1, TargetOpcode::G_SEXT); 1321 1322 widenScalarDst(MI, WideTy, 0); 1323 Observer.changedInstr(MI); 1324 return Legalized; 1325 } 1326 1327 if (TypeIdx != 2) 1328 return UnableToLegalize; 1329 Observer.changingInstr(MI); 1330 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 1331 Observer.changedInstr(MI); 1332 return Legalized; 1333 } 1334 case TargetOpcode::G_FADD: 1335 case TargetOpcode::G_FMUL: 1336 case TargetOpcode::G_FSUB: 1337 case TargetOpcode::G_FMA: 1338 case TargetOpcode::G_FNEG: 1339 case TargetOpcode::G_FABS: 1340 case TargetOpcode::G_FDIV: 1341 case TargetOpcode::G_FREM: 1342 case TargetOpcode::G_FCEIL: 1343 case TargetOpcode::G_FCOS: 1344 case TargetOpcode::G_FSIN: 1345 case TargetOpcode::G_FLOG10: 1346 case TargetOpcode::G_FLOG: 1347 case TargetOpcode::G_FLOG2: 1348 case TargetOpcode::G_FSQRT: 1349 case TargetOpcode::G_FEXP: 1350 assert(TypeIdx == 0); 1351 Observer.changingInstr(MI); 1352 1353 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) 1354 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT); 1355 1356 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 1357 Observer.changedInstr(MI); 1358 return Legalized; 1359 case TargetOpcode::G_INTTOPTR: 1360 if (TypeIdx != 1) 1361 return UnableToLegalize; 1362 1363 Observer.changingInstr(MI); 1364 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 1365 Observer.changedInstr(MI); 1366 return Legalized; 1367 case TargetOpcode::G_PTRTOINT: 1368 if (TypeIdx != 0) 1369 return UnableToLegalize; 1370 1371 Observer.changingInstr(MI); 1372 widenScalarDst(MI, WideTy, 0); 1373 Observer.changedInstr(MI); 1374 return Legalized; 1375 } 1376 } 1377 1378 LegalizerHelper::LegalizeResult 1379 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 1380 using namespace TargetOpcode; 1381 MIRBuilder.setInstr(MI); 1382 1383 switch(MI.getOpcode()) { 1384 default: 1385 return UnableToLegalize; 1386 case TargetOpcode::G_SREM: 1387 case TargetOpcode::G_UREM: { 1388 unsigned QuotReg = MRI.createGenericVirtualRegister(Ty); 1389 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV) 1390 .addDef(QuotReg) 1391 .addUse(MI.getOperand(1).getReg()) 1392 .addUse(MI.getOperand(2).getReg()); 1393 1394 unsigned ProdReg = MRI.createGenericVirtualRegister(Ty); 1395 MIRBuilder.buildMul(ProdReg, QuotReg, MI.getOperand(2).getReg()); 1396 MIRBuilder.buildSub(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), 1397 ProdReg); 1398 MI.eraseFromParent(); 1399 return Legalized; 1400 } 1401 case TargetOpcode::G_SMULO: 1402 case TargetOpcode::G_UMULO: { 1403 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 1404 // result. 1405 unsigned Res = MI.getOperand(0).getReg(); 1406 unsigned Overflow = MI.getOperand(1).getReg(); 1407 unsigned LHS = MI.getOperand(2).getReg(); 1408 unsigned RHS = MI.getOperand(3).getReg(); 1409 1410 MIRBuilder.buildMul(Res, LHS, RHS); 1411 1412 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 1413 ? TargetOpcode::G_SMULH 1414 : TargetOpcode::G_UMULH; 1415 1416 unsigned HiPart = MRI.createGenericVirtualRegister(Ty); 1417 MIRBuilder.buildInstr(Opcode) 1418 .addDef(HiPart) 1419 .addUse(LHS) 1420 .addUse(RHS); 1421 1422 unsigned Zero = MRI.createGenericVirtualRegister(Ty); 1423 MIRBuilder.buildConstant(Zero, 0); 1424 1425 // For *signed* multiply, overflow is detected by checking: 1426 // (hi != (lo >> bitwidth-1)) 1427 if (Opcode == TargetOpcode::G_SMULH) { 1428 unsigned Shifted = MRI.createGenericVirtualRegister(Ty); 1429 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty); 1430 MIRBuilder.buildConstant(ShiftAmt, Ty.getSizeInBits() - 1); 1431 MIRBuilder.buildInstr(TargetOpcode::G_ASHR) 1432 .addDef(Shifted) 1433 .addUse(Res) 1434 .addUse(ShiftAmt); 1435 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted); 1436 } else { 1437 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 1438 } 1439 MI.eraseFromParent(); 1440 return Legalized; 1441 } 1442 case TargetOpcode::G_FNEG: { 1443 // TODO: Handle vector types once we are able to 1444 // represent them. 1445 if (Ty.isVector()) 1446 return UnableToLegalize; 1447 unsigned Res = MI.getOperand(0).getReg(); 1448 Type *ZeroTy; 1449 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 1450 switch (Ty.getSizeInBits()) { 1451 case 16: 1452 ZeroTy = Type::getHalfTy(Ctx); 1453 break; 1454 case 32: 1455 ZeroTy = Type::getFloatTy(Ctx); 1456 break; 1457 case 64: 1458 ZeroTy = Type::getDoubleTy(Ctx); 1459 break; 1460 case 128: 1461 ZeroTy = Type::getFP128Ty(Ctx); 1462 break; 1463 default: 1464 llvm_unreachable("unexpected floating-point type"); 1465 } 1466 ConstantFP &ZeroForNegation = 1467 *cast<ConstantFP>(ConstantFP::getZeroValueForNegation(ZeroTy)); 1468 auto Zero = MIRBuilder.buildFConstant(Ty, ZeroForNegation); 1469 MIRBuilder.buildInstr(TargetOpcode::G_FSUB) 1470 .addDef(Res) 1471 .addUse(Zero->getOperand(0).getReg()) 1472 .addUse(MI.getOperand(1).getReg()); 1473 MI.eraseFromParent(); 1474 return Legalized; 1475 } 1476 case TargetOpcode::G_FSUB: { 1477 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 1478 // First, check if G_FNEG is marked as Lower. If so, we may 1479 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 1480 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower) 1481 return UnableToLegalize; 1482 unsigned Res = MI.getOperand(0).getReg(); 1483 unsigned LHS = MI.getOperand(1).getReg(); 1484 unsigned RHS = MI.getOperand(2).getReg(); 1485 unsigned Neg = MRI.createGenericVirtualRegister(Ty); 1486 MIRBuilder.buildInstr(TargetOpcode::G_FNEG).addDef(Neg).addUse(RHS); 1487 MIRBuilder.buildInstr(TargetOpcode::G_FADD) 1488 .addDef(Res) 1489 .addUse(LHS) 1490 .addUse(Neg); 1491 MI.eraseFromParent(); 1492 return Legalized; 1493 } 1494 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { 1495 unsigned OldValRes = MI.getOperand(0).getReg(); 1496 unsigned SuccessRes = MI.getOperand(1).getReg(); 1497 unsigned Addr = MI.getOperand(2).getReg(); 1498 unsigned CmpVal = MI.getOperand(3).getReg(); 1499 unsigned NewVal = MI.getOperand(4).getReg(); 1500 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, 1501 **MI.memoperands_begin()); 1502 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); 1503 MI.eraseFromParent(); 1504 return Legalized; 1505 } 1506 case TargetOpcode::G_LOAD: 1507 case TargetOpcode::G_SEXTLOAD: 1508 case TargetOpcode::G_ZEXTLOAD: { 1509 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT 1510 unsigned DstReg = MI.getOperand(0).getReg(); 1511 unsigned PtrReg = MI.getOperand(1).getReg(); 1512 LLT DstTy = MRI.getType(DstReg); 1513 auto &MMO = **MI.memoperands_begin(); 1514 1515 if (DstTy.getSizeInBits() == MMO.getSize() /* in bytes */ * 8) { 1516 // In the case of G_LOAD, this was a non-extending load already and we're 1517 // about to lower to the same instruction. 1518 if (MI.getOpcode() == TargetOpcode::G_LOAD) 1519 return UnableToLegalize; 1520 MIRBuilder.buildLoad(DstReg, PtrReg, MMO); 1521 MI.eraseFromParent(); 1522 return Legalized; 1523 } 1524 1525 if (DstTy.isScalar()) { 1526 unsigned TmpReg = MRI.createGenericVirtualRegister( 1527 LLT::scalar(MMO.getSize() /* in bytes */ * 8)); 1528 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); 1529 switch (MI.getOpcode()) { 1530 default: 1531 llvm_unreachable("Unexpected opcode"); 1532 case TargetOpcode::G_LOAD: 1533 MIRBuilder.buildAnyExt(DstReg, TmpReg); 1534 break; 1535 case TargetOpcode::G_SEXTLOAD: 1536 MIRBuilder.buildSExt(DstReg, TmpReg); 1537 break; 1538 case TargetOpcode::G_ZEXTLOAD: 1539 MIRBuilder.buildZExt(DstReg, TmpReg); 1540 break; 1541 } 1542 MI.eraseFromParent(); 1543 return Legalized; 1544 } 1545 1546 return UnableToLegalize; 1547 } 1548 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 1549 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 1550 case TargetOpcode::G_CTLZ: 1551 case TargetOpcode::G_CTTZ: 1552 case TargetOpcode::G_CTPOP: 1553 return lowerBitCount(MI, TypeIdx, Ty); 1554 case G_UADDE: { 1555 unsigned Res = MI.getOperand(0).getReg(); 1556 unsigned CarryOut = MI.getOperand(1).getReg(); 1557 unsigned LHS = MI.getOperand(2).getReg(); 1558 unsigned RHS = MI.getOperand(3).getReg(); 1559 unsigned CarryIn = MI.getOperand(4).getReg(); 1560 1561 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty); 1562 unsigned ZExtCarryIn = MRI.createGenericVirtualRegister(Ty); 1563 1564 MIRBuilder.buildAdd(TmpRes, LHS, RHS); 1565 MIRBuilder.buildZExt(ZExtCarryIn, CarryIn); 1566 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn); 1567 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS); 1568 1569 MI.eraseFromParent(); 1570 return Legalized; 1571 } 1572 case G_USUBO: { 1573 unsigned Res = MI.getOperand(0).getReg(); 1574 unsigned BorrowOut = MI.getOperand(1).getReg(); 1575 unsigned LHS = MI.getOperand(2).getReg(); 1576 unsigned RHS = MI.getOperand(3).getReg(); 1577 1578 MIRBuilder.buildSub(Res, LHS, RHS); 1579 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS); 1580 1581 MI.eraseFromParent(); 1582 return Legalized; 1583 } 1584 case G_USUBE: { 1585 unsigned Res = MI.getOperand(0).getReg(); 1586 unsigned BorrowOut = MI.getOperand(1).getReg(); 1587 unsigned LHS = MI.getOperand(2).getReg(); 1588 unsigned RHS = MI.getOperand(3).getReg(); 1589 unsigned BorrowIn = MI.getOperand(4).getReg(); 1590 1591 unsigned TmpRes = MRI.createGenericVirtualRegister(Ty); 1592 unsigned ZExtBorrowIn = MRI.createGenericVirtualRegister(Ty); 1593 unsigned LHS_EQ_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1)); 1594 unsigned LHS_ULT_RHS = MRI.createGenericVirtualRegister(LLT::scalar(1)); 1595 1596 MIRBuilder.buildSub(TmpRes, LHS, RHS); 1597 MIRBuilder.buildZExt(ZExtBorrowIn, BorrowIn); 1598 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn); 1599 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LHS_EQ_RHS, LHS, RHS); 1600 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, LHS_ULT_RHS, LHS, RHS); 1601 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS); 1602 1603 MI.eraseFromParent(); 1604 return Legalized; 1605 } 1606 } 1607 } 1608 1609 LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorImplicitDef( 1610 MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy) { 1611 SmallVector<unsigned, 2> DstRegs; 1612 1613 unsigned NarrowSize = NarrowTy.getSizeInBits(); 1614 unsigned DstReg = MI.getOperand(0).getReg(); 1615 unsigned Size = MRI.getType(DstReg).getSizeInBits(); 1616 int NumParts = Size / NarrowSize; 1617 // FIXME: Don't know how to handle the situation where the small vectors 1618 // aren't all the same size yet. 1619 if (Size % NarrowSize != 0) 1620 return UnableToLegalize; 1621 1622 for (int i = 0; i < NumParts; ++i) { 1623 unsigned TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 1624 MIRBuilder.buildUndef(TmpReg); 1625 DstRegs.push_back(TmpReg); 1626 } 1627 1628 if (NarrowTy.isVector()) 1629 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 1630 else 1631 MIRBuilder.buildBuildVector(DstReg, DstRegs); 1632 1633 MI.eraseFromParent(); 1634 return Legalized; 1635 } 1636 1637 LegalizerHelper::LegalizeResult 1638 LegalizerHelper::fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx, 1639 LLT NarrowTy) { 1640 const unsigned Opc = MI.getOpcode(); 1641 const unsigned NumOps = MI.getNumOperands() - 1; 1642 const unsigned NarrowSize = NarrowTy.getSizeInBits(); 1643 const unsigned DstReg = MI.getOperand(0).getReg(); 1644 const unsigned Flags = MI.getFlags(); 1645 const LLT DstTy = MRI.getType(DstReg); 1646 const unsigned Size = DstTy.getSizeInBits(); 1647 const int NumParts = Size / NarrowSize; 1648 const LLT EltTy = DstTy.getElementType(); 1649 const unsigned EltSize = EltTy.getSizeInBits(); 1650 const unsigned BitsForNumParts = NarrowSize * NumParts; 1651 1652 // Check if we have any leftovers. If we do, then only handle the case where 1653 // the leftover is one element. 1654 if (BitsForNumParts != Size && BitsForNumParts + EltSize != Size) 1655 return UnableToLegalize; 1656 1657 if (BitsForNumParts != Size) { 1658 unsigned AccumDstReg = MRI.createGenericVirtualRegister(DstTy); 1659 MIRBuilder.buildUndef(AccumDstReg); 1660 1661 // Handle the pieces which evenly divide into the requested type with 1662 // extract/op/insert sequence. 1663 for (unsigned Offset = 0; Offset < BitsForNumParts; Offset += NarrowSize) { 1664 SmallVector<SrcOp, 4> SrcOps; 1665 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) { 1666 unsigned PartOpReg = MRI.createGenericVirtualRegister(NarrowTy); 1667 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), Offset); 1668 SrcOps.push_back(PartOpReg); 1669 } 1670 1671 unsigned PartDstReg = MRI.createGenericVirtualRegister(NarrowTy); 1672 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags); 1673 1674 unsigned PartInsertReg = MRI.createGenericVirtualRegister(DstTy); 1675 MIRBuilder.buildInsert(PartInsertReg, AccumDstReg, PartDstReg, Offset); 1676 AccumDstReg = PartInsertReg; 1677 Offset += NarrowSize; 1678 } 1679 1680 // Handle the remaining element sized leftover piece. 1681 SmallVector<SrcOp, 4> SrcOps; 1682 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) { 1683 unsigned PartOpReg = MRI.createGenericVirtualRegister(EltTy); 1684 MIRBuilder.buildExtract(PartOpReg, MI.getOperand(I).getReg(), 1685 BitsForNumParts); 1686 SrcOps.push_back(PartOpReg); 1687 } 1688 1689 unsigned PartDstReg = MRI.createGenericVirtualRegister(EltTy); 1690 MIRBuilder.buildInstr(Opc, {PartDstReg}, SrcOps, Flags); 1691 MIRBuilder.buildInsert(DstReg, AccumDstReg, PartDstReg, BitsForNumParts); 1692 MI.eraseFromParent(); 1693 1694 return Legalized; 1695 } 1696 1697 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs; 1698 1699 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src0Regs); 1700 1701 if (NumOps >= 2) 1702 extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src1Regs); 1703 1704 if (NumOps >= 3) 1705 extractParts(MI.getOperand(3).getReg(), NarrowTy, NumParts, Src2Regs); 1706 1707 for (int i = 0; i < NumParts; ++i) { 1708 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); 1709 1710 if (NumOps == 1) 1711 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i]}, Flags); 1712 else if (NumOps == 2) { 1713 MIRBuilder.buildInstr(Opc, {DstReg}, {Src0Regs[i], Src1Regs[i]}, Flags); 1714 } else if (NumOps == 3) { 1715 MIRBuilder.buildInstr(Opc, {DstReg}, 1716 {Src0Regs[i], Src1Regs[i], Src2Regs[i]}, Flags); 1717 } 1718 1719 DstRegs.push_back(DstReg); 1720 } 1721 1722 if (NarrowTy.isVector()) 1723 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 1724 else 1725 MIRBuilder.buildBuildVector(DstReg, DstRegs); 1726 1727 MI.eraseFromParent(); 1728 return Legalized; 1729 } 1730 1731 LegalizerHelper::LegalizeResult 1732 LegalizerHelper::fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx, 1733 LLT NarrowTy) { 1734 if (TypeIdx != 0) 1735 return UnableToLegalize; 1736 1737 unsigned DstReg = MI.getOperand(0).getReg(); 1738 unsigned SrcReg = MI.getOperand(1).getReg(); 1739 LLT DstTy = MRI.getType(DstReg); 1740 LLT SrcTy = MRI.getType(SrcReg); 1741 1742 LLT NarrowTy0 = NarrowTy; 1743 LLT NarrowTy1; 1744 unsigned NumParts; 1745 1746 if (NarrowTy.isVector()) { 1747 // Uneven breakdown not handled. 1748 NumParts = DstTy.getNumElements() / NarrowTy.getNumElements(); 1749 if (NumParts * NarrowTy.getNumElements() != DstTy.getNumElements()) 1750 return UnableToLegalize; 1751 1752 NarrowTy1 = LLT::vector(NumParts, SrcTy.getElementType().getSizeInBits()); 1753 } else { 1754 NumParts = DstTy.getNumElements(); 1755 NarrowTy1 = SrcTy.getElementType(); 1756 } 1757 1758 SmallVector<unsigned, 4> SrcRegs, DstRegs; 1759 extractParts(SrcReg, NarrowTy1, NumParts, SrcRegs); 1760 1761 for (unsigned I = 0; I < NumParts; ++I) { 1762 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0); 1763 MachineInstr *NewInst = MIRBuilder.buildInstr(MI.getOpcode()) 1764 .addDef(DstReg) 1765 .addUse(SrcRegs[I]); 1766 1767 NewInst->setFlags(MI.getFlags()); 1768 DstRegs.push_back(DstReg); 1769 } 1770 1771 if (NarrowTy.isVector()) 1772 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 1773 else 1774 MIRBuilder.buildBuildVector(DstReg, DstRegs); 1775 1776 MI.eraseFromParent(); 1777 return Legalized; 1778 } 1779 1780 LegalizerHelper::LegalizeResult 1781 LegalizerHelper::fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, 1782 LLT NarrowTy) { 1783 unsigned DstReg = MI.getOperand(0).getReg(); 1784 unsigned Src0Reg = MI.getOperand(2).getReg(); 1785 LLT DstTy = MRI.getType(DstReg); 1786 LLT SrcTy = MRI.getType(Src0Reg); 1787 1788 unsigned NumParts; 1789 LLT NarrowTy0, NarrowTy1; 1790 1791 if (TypeIdx == 0) { 1792 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1; 1793 unsigned OldElts = DstTy.getNumElements(); 1794 1795 NarrowTy0 = NarrowTy; 1796 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : DstTy.getNumElements(); 1797 NarrowTy1 = NarrowTy.isVector() ? 1798 LLT::vector(NarrowTy.getNumElements(), SrcTy.getScalarSizeInBits()) : 1799 SrcTy.getElementType(); 1800 1801 } else { 1802 unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1; 1803 unsigned OldElts = SrcTy.getNumElements(); 1804 1805 NumParts = NarrowTy.isVector() ? (OldElts / NewElts) : 1806 NarrowTy.getNumElements(); 1807 NarrowTy0 = LLT::vector(NarrowTy.getNumElements(), 1808 DstTy.getScalarSizeInBits()); 1809 NarrowTy1 = NarrowTy; 1810 } 1811 1812 // FIXME: Don't know how to handle the situation where the small vectors 1813 // aren't all the same size yet. 1814 if (NarrowTy1.isVector() && 1815 NarrowTy1.getNumElements() * NumParts != DstTy.getNumElements()) 1816 return UnableToLegalize; 1817 1818 CmpInst::Predicate Pred 1819 = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()); 1820 1821 SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; 1822 extractParts(MI.getOperand(2).getReg(), NarrowTy1, NumParts, Src1Regs); 1823 extractParts(MI.getOperand(3).getReg(), NarrowTy1, NumParts, Src2Regs); 1824 1825 for (unsigned I = 0; I < NumParts; ++I) { 1826 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0); 1827 DstRegs.push_back(DstReg); 1828 1829 if (MI.getOpcode() == TargetOpcode::G_ICMP) 1830 MIRBuilder.buildICmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]); 1831 else { 1832 MachineInstr *NewCmp 1833 = MIRBuilder.buildFCmp(Pred, DstReg, Src1Regs[I], Src2Regs[I]); 1834 NewCmp->setFlags(MI.getFlags()); 1835 } 1836 } 1837 1838 if (NarrowTy1.isVector()) 1839 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 1840 else 1841 MIRBuilder.buildBuildVector(DstReg, DstRegs); 1842 1843 MI.eraseFromParent(); 1844 return Legalized; 1845 } 1846 1847 LegalizerHelper::LegalizeResult 1848 LegalizerHelper::fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, 1849 LLT NarrowTy) { 1850 unsigned DstReg = MI.getOperand(0).getReg(); 1851 unsigned CondReg = MI.getOperand(1).getReg(); 1852 1853 unsigned NumParts = 0; 1854 LLT NarrowTy0, NarrowTy1; 1855 1856 LLT DstTy = MRI.getType(DstReg); 1857 LLT CondTy = MRI.getType(CondReg); 1858 unsigned Size = DstTy.getSizeInBits(); 1859 1860 assert(TypeIdx == 0 || CondTy.isVector()); 1861 1862 if (TypeIdx == 0) { 1863 NarrowTy0 = NarrowTy; 1864 NarrowTy1 = CondTy; 1865 1866 unsigned NarrowSize = NarrowTy0.getSizeInBits(); 1867 // FIXME: Don't know how to handle the situation where the small vectors 1868 // aren't all the same size yet. 1869 if (Size % NarrowSize != 0) 1870 return UnableToLegalize; 1871 1872 NumParts = Size / NarrowSize; 1873 1874 // Need to break down the condition type 1875 if (CondTy.isVector()) { 1876 if (CondTy.getNumElements() == NumParts) 1877 NarrowTy1 = CondTy.getElementType(); 1878 else 1879 NarrowTy1 = LLT::vector(CondTy.getNumElements() / NumParts, 1880 CondTy.getScalarSizeInBits()); 1881 } 1882 } else { 1883 NumParts = CondTy.getNumElements(); 1884 if (NarrowTy.isVector()) { 1885 // TODO: Handle uneven breakdown. 1886 if (NumParts * NarrowTy.getNumElements() != CondTy.getNumElements()) 1887 return UnableToLegalize; 1888 1889 return UnableToLegalize; 1890 } else { 1891 NarrowTy0 = DstTy.getElementType(); 1892 NarrowTy1 = NarrowTy; 1893 } 1894 } 1895 1896 SmallVector<unsigned, 2> DstRegs, Src0Regs, Src1Regs, Src2Regs; 1897 if (CondTy.isVector()) 1898 extractParts(MI.getOperand(1).getReg(), NarrowTy1, NumParts, Src0Regs); 1899 1900 extractParts(MI.getOperand(2).getReg(), NarrowTy0, NumParts, Src1Regs); 1901 extractParts(MI.getOperand(3).getReg(), NarrowTy0, NumParts, Src2Regs); 1902 1903 for (unsigned i = 0; i < NumParts; ++i) { 1904 unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy0); 1905 MIRBuilder.buildSelect(DstReg, CondTy.isVector() ? Src0Regs[i] : CondReg, 1906 Src1Regs[i], Src2Regs[i]); 1907 DstRegs.push_back(DstReg); 1908 } 1909 1910 if (NarrowTy0.isVector()) 1911 MIRBuilder.buildConcatVectors(DstReg, DstRegs); 1912 else 1913 MIRBuilder.buildBuildVector(DstReg, DstRegs); 1914 1915 MI.eraseFromParent(); 1916 return Legalized; 1917 } 1918 1919 /// Try to break down \p OrigTy into \p NarrowTy sized pieces. 1920 /// 1921 /// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy, 1922 /// with any leftover piece as type \p LeftoverTy 1923 /// 1924 /// Returns -1 if the breakdown is not satisfiable. 1925 static int getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) { 1926 assert(!LeftoverTy.isValid() && "this is an out argument"); 1927 1928 unsigned Size = OrigTy.getSizeInBits(); 1929 unsigned NarrowSize = NarrowTy.getSizeInBits(); 1930 unsigned NumParts = Size / NarrowSize; 1931 unsigned LeftoverSize = Size - NumParts * NarrowSize; 1932 assert(Size > NarrowSize); 1933 1934 if (LeftoverSize == 0) 1935 return NumParts; 1936 1937 if (NarrowTy.isVector()) { 1938 unsigned EltSize = OrigTy.getScalarSizeInBits(); 1939 if (LeftoverSize % EltSize != 0) 1940 return -1; 1941 LeftoverTy = LLT::scalarOrVector(LeftoverSize / EltSize, EltSize); 1942 } else { 1943 LeftoverTy = LLT::scalar(LeftoverSize); 1944 } 1945 1946 return NumParts; 1947 } 1948 1949 LegalizerHelper::LegalizeResult 1950 LegalizerHelper::reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, 1951 LLT NarrowTy) { 1952 // FIXME: Don't know how to handle secondary types yet. 1953 if (TypeIdx != 0) 1954 return UnableToLegalize; 1955 1956 MachineMemOperand *MMO = *MI.memoperands_begin(); 1957 1958 // This implementation doesn't work for atomics. Give up instead of doing 1959 // something invalid. 1960 if (MMO->getOrdering() != AtomicOrdering::NotAtomic || 1961 MMO->getFailureOrdering() != AtomicOrdering::NotAtomic) 1962 return UnableToLegalize; 1963 1964 bool IsLoad = MI.getOpcode() == TargetOpcode::G_LOAD; 1965 unsigned ValReg = MI.getOperand(0).getReg(); 1966 unsigned AddrReg = MI.getOperand(1).getReg(); 1967 LLT ValTy = MRI.getType(ValReg); 1968 1969 int NumParts = -1; 1970 LLT LeftoverTy; 1971 SmallVector<unsigned, 8> NarrowRegs, NarrowLeftoverRegs; 1972 if (IsLoad) { 1973 NumParts = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy); 1974 } else { 1975 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs, 1976 NarrowLeftoverRegs)) 1977 NumParts = NarrowRegs.size(); 1978 } 1979 1980 if (NumParts == -1) 1981 return UnableToLegalize; 1982 1983 const LLT OffsetTy = LLT::scalar(MRI.getType(AddrReg).getScalarSizeInBits()); 1984 1985 unsigned TotalSize = ValTy.getSizeInBits(); 1986 1987 // Split the load/store into PartTy sized pieces starting at Offset. If this 1988 // is a load, return the new registers in ValRegs. For a store, each elements 1989 // of ValRegs should be PartTy. Returns the next offset that needs to be 1990 // handled. 1991 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<unsigned> &ValRegs, 1992 unsigned Offset) -> unsigned { 1993 MachineFunction &MF = MIRBuilder.getMF(); 1994 unsigned PartSize = PartTy.getSizeInBits(); 1995 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize; 1996 Offset += PartSize, ++Idx) { 1997 unsigned ByteSize = PartSize / 8; 1998 unsigned ByteOffset = Offset / 8; 1999 unsigned NewAddrReg = 0; 2000 2001 MIRBuilder.materializeGEP(NewAddrReg, AddrReg, OffsetTy, ByteOffset); 2002 2003 MachineMemOperand *NewMMO = 2004 MF.getMachineMemOperand(MMO, ByteOffset, ByteSize); 2005 2006 if (IsLoad) { 2007 unsigned Dst = MRI.createGenericVirtualRegister(PartTy); 2008 ValRegs.push_back(Dst); 2009 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO); 2010 } else { 2011 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO); 2012 } 2013 } 2014 2015 return Offset; 2016 }; 2017 2018 unsigned HandledOffset = splitTypePieces(NarrowTy, NarrowRegs, 0); 2019 2020 // Handle the rest of the register if this isn't an even type breakdown. 2021 if (LeftoverTy.isValid()) 2022 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, HandledOffset); 2023 2024 if (IsLoad) { 2025 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs, 2026 LeftoverTy, NarrowLeftoverRegs); 2027 } 2028 2029 MI.eraseFromParent(); 2030 return Legalized; 2031 } 2032 2033 LegalizerHelper::LegalizeResult 2034 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 2035 LLT NarrowTy) { 2036 using namespace TargetOpcode; 2037 2038 MIRBuilder.setInstr(MI); 2039 switch (MI.getOpcode()) { 2040 case G_IMPLICIT_DEF: 2041 return fewerElementsVectorImplicitDef(MI, TypeIdx, NarrowTy); 2042 case G_AND: 2043 case G_OR: 2044 case G_XOR: 2045 case G_ADD: 2046 case G_SUB: 2047 case G_MUL: 2048 case G_SMULH: 2049 case G_UMULH: 2050 case G_FADD: 2051 case G_FMUL: 2052 case G_FSUB: 2053 case G_FNEG: 2054 case G_FABS: 2055 case G_FDIV: 2056 case G_FREM: 2057 case G_FMA: 2058 case G_FPOW: 2059 case G_FEXP: 2060 case G_FEXP2: 2061 case G_FLOG: 2062 case G_FLOG2: 2063 case G_FLOG10: 2064 case G_FCEIL: 2065 case G_INTRINSIC_ROUND: 2066 case G_INTRINSIC_TRUNC: 2067 case G_FCOS: 2068 case G_FSIN: 2069 case G_FSQRT: 2070 case G_BSWAP: 2071 return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy); 2072 case G_ZEXT: 2073 case G_SEXT: 2074 case G_ANYEXT: 2075 case G_FPEXT: 2076 case G_FPTRUNC: 2077 case G_SITOFP: 2078 case G_UITOFP: 2079 case G_FPTOSI: 2080 case G_FPTOUI: 2081 case G_INTTOPTR: 2082 case G_PTRTOINT: 2083 return fewerElementsVectorCasts(MI, TypeIdx, NarrowTy); 2084 case G_ICMP: 2085 case G_FCMP: 2086 return fewerElementsVectorCmp(MI, TypeIdx, NarrowTy); 2087 case G_SELECT: 2088 return fewerElementsVectorSelect(MI, TypeIdx, NarrowTy); 2089 case G_LOAD: 2090 case G_STORE: 2091 return reduceLoadStoreWidth(MI, TypeIdx, NarrowTy); 2092 default: 2093 return UnableToLegalize; 2094 } 2095 } 2096 2097 LegalizerHelper::LegalizeResult 2098 LegalizerHelper::narrowScalarMul(MachineInstr &MI, unsigned TypeIdx, LLT NewTy) { 2099 unsigned DstReg = MI.getOperand(0).getReg(); 2100 unsigned Src0 = MI.getOperand(1).getReg(); 2101 unsigned Src1 = MI.getOperand(2).getReg(); 2102 LLT Ty = MRI.getType(DstReg); 2103 if (Ty.isVector()) 2104 return UnableToLegalize; 2105 2106 unsigned Size = Ty.getSizeInBits(); 2107 unsigned NewSize = Size / 2; 2108 if (Size != 2 * NewSize) 2109 return UnableToLegalize; 2110 2111 LLT HalfTy = LLT::scalar(NewSize); 2112 // TODO: if HalfTy != NewTy, handle the breakdown all at once? 2113 2114 unsigned ShiftAmt = MRI.createGenericVirtualRegister(Ty); 2115 unsigned Lo = MRI.createGenericVirtualRegister(HalfTy); 2116 unsigned Hi = MRI.createGenericVirtualRegister(HalfTy); 2117 unsigned ExtLo = MRI.createGenericVirtualRegister(Ty); 2118 unsigned ExtHi = MRI.createGenericVirtualRegister(Ty); 2119 unsigned ShiftedHi = MRI.createGenericVirtualRegister(Ty); 2120 2121 SmallVector<unsigned, 2> Src0Parts; 2122 SmallVector<unsigned, 2> Src1Parts; 2123 2124 extractParts(Src0, HalfTy, 2, Src0Parts); 2125 extractParts(Src1, HalfTy, 2, Src1Parts); 2126 2127 MIRBuilder.buildMul(Lo, Src0Parts[0], Src1Parts[0]); 2128 2129 // TODO: Use smulh or umulh depending on what the target has. 2130 MIRBuilder.buildUMulH(Hi, Src0Parts[1], Src1Parts[1]); 2131 2132 MIRBuilder.buildConstant(ShiftAmt, NewSize); 2133 MIRBuilder.buildAnyExt(ExtHi, Hi); 2134 MIRBuilder.buildShl(ShiftedHi, ExtHi, ShiftAmt); 2135 2136 MIRBuilder.buildZExt(ExtLo, Lo); 2137 MIRBuilder.buildOr(DstReg, ExtLo, ShiftedHi); 2138 MI.eraseFromParent(); 2139 return Legalized; 2140 } 2141 2142 LegalizerHelper::LegalizeResult 2143 LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, 2144 LLT NarrowTy) { 2145 if (TypeIdx != 0) 2146 return UnableToLegalize; 2147 2148 unsigned CondReg = MI.getOperand(1).getReg(); 2149 LLT CondTy = MRI.getType(CondReg); 2150 if (CondTy.isVector()) // TODO: Handle vselect 2151 return UnableToLegalize; 2152 2153 unsigned DstReg = MI.getOperand(0).getReg(); 2154 LLT DstTy = MRI.getType(DstReg); 2155 2156 SmallVector<unsigned, 4> DstRegs, DstLeftoverRegs; 2157 SmallVector<unsigned, 4> Src1Regs, Src1LeftoverRegs; 2158 SmallVector<unsigned, 4> Src2Regs, Src2LeftoverRegs; 2159 LLT LeftoverTy; 2160 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy, 2161 Src1Regs, Src1LeftoverRegs)) 2162 return UnableToLegalize; 2163 2164 LLT Unused; 2165 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused, 2166 Src2Regs, Src2LeftoverRegs)) 2167 llvm_unreachable("inconsistent extractParts result"); 2168 2169 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) { 2170 auto Select = MIRBuilder.buildSelect(NarrowTy, 2171 CondReg, Src1Regs[I], Src2Regs[I]); 2172 DstRegs.push_back(Select->getOperand(0).getReg()); 2173 } 2174 2175 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) { 2176 auto Select = MIRBuilder.buildSelect( 2177 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]); 2178 DstLeftoverRegs.push_back(Select->getOperand(0).getReg()); 2179 } 2180 2181 insertParts(DstReg, DstTy, NarrowTy, DstRegs, 2182 LeftoverTy, DstLeftoverRegs); 2183 2184 MI.eraseFromParent(); 2185 return Legalized; 2186 } 2187 2188 LegalizerHelper::LegalizeResult 2189 LegalizerHelper::lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { 2190 unsigned Opc = MI.getOpcode(); 2191 auto &TII = *MI.getMF()->getSubtarget().getInstrInfo(); 2192 auto isSupported = [this](const LegalityQuery &Q) { 2193 auto QAction = LI.getAction(Q).Action; 2194 return QAction == Legal || QAction == Libcall || QAction == Custom; 2195 }; 2196 switch (Opc) { 2197 default: 2198 return UnableToLegalize; 2199 case TargetOpcode::G_CTLZ_ZERO_UNDEF: { 2200 // This trivially expands to CTLZ. 2201 Observer.changingInstr(MI); 2202 MI.setDesc(TII.get(TargetOpcode::G_CTLZ)); 2203 Observer.changedInstr(MI); 2204 return Legalized; 2205 } 2206 case TargetOpcode::G_CTLZ: { 2207 unsigned SrcReg = MI.getOperand(1).getReg(); 2208 unsigned Len = Ty.getSizeInBits(); 2209 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {Ty, Ty}})) { 2210 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero. 2211 auto MIBCtlzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, 2212 {Ty}, {SrcReg}); 2213 auto MIBZero = MIRBuilder.buildConstant(Ty, 0); 2214 auto MIBLen = MIRBuilder.buildConstant(Ty, Len); 2215 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), 2216 SrcReg, MIBZero); 2217 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen, 2218 MIBCtlzZU); 2219 MI.eraseFromParent(); 2220 return Legalized; 2221 } 2222 // for now, we do this: 2223 // NewLen = NextPowerOf2(Len); 2224 // x = x | (x >> 1); 2225 // x = x | (x >> 2); 2226 // ... 2227 // x = x | (x >>16); 2228 // x = x | (x >>32); // for 64-bit input 2229 // Upto NewLen/2 2230 // return Len - popcount(x); 2231 // 2232 // Ref: "Hacker's Delight" by Henry Warren 2233 unsigned Op = SrcReg; 2234 unsigned NewLen = PowerOf2Ceil(Len); 2235 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) { 2236 auto MIBShiftAmt = MIRBuilder.buildConstant(Ty, 1ULL << i); 2237 auto MIBOp = MIRBuilder.buildInstr( 2238 TargetOpcode::G_OR, {Ty}, 2239 {Op, MIRBuilder.buildInstr(TargetOpcode::G_LSHR, {Ty}, 2240 {Op, MIBShiftAmt})}); 2241 Op = MIBOp->getOperand(0).getReg(); 2242 } 2243 auto MIBPop = MIRBuilder.buildInstr(TargetOpcode::G_CTPOP, {Ty}, {Op}); 2244 MIRBuilder.buildInstr(TargetOpcode::G_SUB, {MI.getOperand(0).getReg()}, 2245 {MIRBuilder.buildConstant(Ty, Len), MIBPop}); 2246 MI.eraseFromParent(); 2247 return Legalized; 2248 } 2249 case TargetOpcode::G_CTTZ_ZERO_UNDEF: { 2250 // This trivially expands to CTTZ. 2251 Observer.changingInstr(MI); 2252 MI.setDesc(TII.get(TargetOpcode::G_CTTZ)); 2253 Observer.changedInstr(MI); 2254 return Legalized; 2255 } 2256 case TargetOpcode::G_CTTZ: { 2257 unsigned SrcReg = MI.getOperand(1).getReg(); 2258 unsigned Len = Ty.getSizeInBits(); 2259 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {Ty, Ty}})) { 2260 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with 2261 // zero. 2262 auto MIBCttzZU = MIRBuilder.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, 2263 {Ty}, {SrcReg}); 2264 auto MIBZero = MIRBuilder.buildConstant(Ty, 0); 2265 auto MIBLen = MIRBuilder.buildConstant(Ty, Len); 2266 auto MIBICmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), 2267 SrcReg, MIBZero); 2268 MIRBuilder.buildSelect(MI.getOperand(0).getReg(), MIBICmp, MIBLen, 2269 MIBCttzZU); 2270 MI.eraseFromParent(); 2271 return Legalized; 2272 } 2273 // for now, we use: { return popcount(~x & (x - 1)); } 2274 // unless the target has ctlz but not ctpop, in which case we use: 2275 // { return 32 - nlz(~x & (x-1)); } 2276 // Ref: "Hacker's Delight" by Henry Warren 2277 auto MIBCstNeg1 = MIRBuilder.buildConstant(Ty, -1); 2278 auto MIBNot = 2279 MIRBuilder.buildInstr(TargetOpcode::G_XOR, {Ty}, {SrcReg, MIBCstNeg1}); 2280 auto MIBTmp = MIRBuilder.buildInstr( 2281 TargetOpcode::G_AND, {Ty}, 2282 {MIBNot, MIRBuilder.buildInstr(TargetOpcode::G_ADD, {Ty}, 2283 {SrcReg, MIBCstNeg1})}); 2284 if (!isSupported({TargetOpcode::G_CTPOP, {Ty, Ty}}) && 2285 isSupported({TargetOpcode::G_CTLZ, {Ty, Ty}})) { 2286 auto MIBCstLen = MIRBuilder.buildConstant(Ty, Len); 2287 MIRBuilder.buildInstr( 2288 TargetOpcode::G_SUB, {MI.getOperand(0).getReg()}, 2289 {MIBCstLen, 2290 MIRBuilder.buildInstr(TargetOpcode::G_CTLZ, {Ty}, {MIBTmp})}); 2291 MI.eraseFromParent(); 2292 return Legalized; 2293 } 2294 MI.setDesc(TII.get(TargetOpcode::G_CTPOP)); 2295 MI.getOperand(1).setReg(MIBTmp->getOperand(0).getReg()); 2296 return Legalized; 2297 } 2298 } 2299 } 2300