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/GlobalISel/LostDebugLocObserver.h" 20 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 21 #include "llvm/CodeGen/GlobalISel/Utils.h" 22 #include "llvm/CodeGen/MachineFrameInfo.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 #include "llvm/CodeGen/TargetFrameLowering.h" 25 #include "llvm/CodeGen/TargetInstrInfo.h" 26 #include "llvm/CodeGen/TargetLowering.h" 27 #include "llvm/CodeGen/TargetOpcodes.h" 28 #include "llvm/CodeGen/TargetSubtargetInfo.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/MathExtras.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include "llvm/Target/TargetMachine.h" 34 35 #define DEBUG_TYPE "legalizer" 36 37 using namespace llvm; 38 using namespace LegalizeActions; 39 using namespace MIPatternMatch; 40 41 /// Try to break down \p OrigTy into \p NarrowTy sized pieces. 42 /// 43 /// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy, 44 /// with any leftover piece as type \p LeftoverTy 45 /// 46 /// Returns -1 in the first element of the pair if the breakdown is not 47 /// satisfiable. 48 static std::pair<int, int> 49 getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) { 50 assert(!LeftoverTy.isValid() && "this is an out argument"); 51 52 unsigned Size = OrigTy.getSizeInBits(); 53 unsigned NarrowSize = NarrowTy.getSizeInBits(); 54 unsigned NumParts = Size / NarrowSize; 55 unsigned LeftoverSize = Size - NumParts * NarrowSize; 56 assert(Size > NarrowSize); 57 58 if (LeftoverSize == 0) 59 return {NumParts, 0}; 60 61 if (NarrowTy.isVector()) { 62 unsigned EltSize = OrigTy.getScalarSizeInBits(); 63 if (LeftoverSize % EltSize != 0) 64 return {-1, -1}; 65 LeftoverTy = LLT::scalarOrVector( 66 ElementCount::getFixed(LeftoverSize / EltSize), EltSize); 67 } else { 68 LeftoverTy = LLT::scalar(LeftoverSize); 69 } 70 71 int NumLeftover = LeftoverSize / LeftoverTy.getSizeInBits(); 72 return std::make_pair(NumParts, NumLeftover); 73 } 74 75 static Type *getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty) { 76 77 if (!Ty.isScalar()) 78 return nullptr; 79 80 switch (Ty.getSizeInBits()) { 81 case 16: 82 return Type::getHalfTy(Ctx); 83 case 32: 84 return Type::getFloatTy(Ctx); 85 case 64: 86 return Type::getDoubleTy(Ctx); 87 case 80: 88 return Type::getX86_FP80Ty(Ctx); 89 case 128: 90 return Type::getFP128Ty(Ctx); 91 default: 92 return nullptr; 93 } 94 } 95 96 LegalizerHelper::LegalizerHelper(MachineFunction &MF, 97 GISelChangeObserver &Observer, 98 MachineIRBuilder &Builder) 99 : MIRBuilder(Builder), Observer(Observer), MRI(MF.getRegInfo()), 100 LI(*MF.getSubtarget().getLegalizerInfo()), 101 TLI(*MF.getSubtarget().getTargetLowering()) { } 102 103 LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI, 104 GISelChangeObserver &Observer, 105 MachineIRBuilder &B) 106 : MIRBuilder(B), Observer(Observer), MRI(MF.getRegInfo()), LI(LI), 107 TLI(*MF.getSubtarget().getTargetLowering()) { } 108 109 LegalizerHelper::LegalizeResult 110 LegalizerHelper::legalizeInstrStep(MachineInstr &MI, 111 LostDebugLocObserver &LocObserver) { 112 LLVM_DEBUG(dbgs() << "Legalizing: " << MI); 113 114 MIRBuilder.setInstrAndDebugLoc(MI); 115 116 if (MI.getOpcode() == TargetOpcode::G_INTRINSIC || 117 MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS) 118 return LI.legalizeIntrinsic(*this, MI) ? Legalized : UnableToLegalize; 119 auto Step = LI.getAction(MI, MRI); 120 switch (Step.Action) { 121 case Legal: 122 LLVM_DEBUG(dbgs() << ".. Already legal\n"); 123 return AlreadyLegal; 124 case Libcall: 125 LLVM_DEBUG(dbgs() << ".. Convert to libcall\n"); 126 return libcall(MI, LocObserver); 127 case NarrowScalar: 128 LLVM_DEBUG(dbgs() << ".. Narrow scalar\n"); 129 return narrowScalar(MI, Step.TypeIdx, Step.NewType); 130 case WidenScalar: 131 LLVM_DEBUG(dbgs() << ".. Widen scalar\n"); 132 return widenScalar(MI, Step.TypeIdx, Step.NewType); 133 case Bitcast: 134 LLVM_DEBUG(dbgs() << ".. Bitcast type\n"); 135 return bitcast(MI, Step.TypeIdx, Step.NewType); 136 case Lower: 137 LLVM_DEBUG(dbgs() << ".. Lower\n"); 138 return lower(MI, Step.TypeIdx, Step.NewType); 139 case FewerElements: 140 LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n"); 141 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType); 142 case MoreElements: 143 LLVM_DEBUG(dbgs() << ".. Increase number of elements\n"); 144 return moreElementsVector(MI, Step.TypeIdx, Step.NewType); 145 case Custom: 146 LLVM_DEBUG(dbgs() << ".. Custom legalization\n"); 147 return LI.legalizeCustom(*this, MI) ? Legalized : UnableToLegalize; 148 default: 149 LLVM_DEBUG(dbgs() << ".. Unable to legalize\n"); 150 return UnableToLegalize; 151 } 152 } 153 154 void LegalizerHelper::extractParts(Register Reg, LLT Ty, int NumParts, 155 SmallVectorImpl<Register> &VRegs) { 156 for (int i = 0; i < NumParts; ++i) 157 VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); 158 MIRBuilder.buildUnmerge(VRegs, Reg); 159 } 160 161 bool LegalizerHelper::extractParts(Register Reg, LLT RegTy, 162 LLT MainTy, LLT &LeftoverTy, 163 SmallVectorImpl<Register> &VRegs, 164 SmallVectorImpl<Register> &LeftoverRegs) { 165 assert(!LeftoverTy.isValid() && "this is an out argument"); 166 167 unsigned RegSize = RegTy.getSizeInBits(); 168 unsigned MainSize = MainTy.getSizeInBits(); 169 unsigned NumParts = RegSize / MainSize; 170 unsigned LeftoverSize = RegSize - NumParts * MainSize; 171 172 // Use an unmerge when possible. 173 if (LeftoverSize == 0) { 174 for (unsigned I = 0; I < NumParts; ++I) 175 VRegs.push_back(MRI.createGenericVirtualRegister(MainTy)); 176 MIRBuilder.buildUnmerge(VRegs, Reg); 177 return true; 178 } 179 180 // Perform irregular split. Leftover is last element of RegPieces. 181 if (MainTy.isVector()) { 182 SmallVector<Register, 8> RegPieces; 183 extractVectorParts(Reg, MainTy.getNumElements(), RegPieces); 184 for (unsigned i = 0; i < RegPieces.size() - 1; ++i) 185 VRegs.push_back(RegPieces[i]); 186 LeftoverRegs.push_back(RegPieces[RegPieces.size() - 1]); 187 LeftoverTy = MRI.getType(LeftoverRegs[0]); 188 return true; 189 } 190 191 LeftoverTy = LLT::scalar(LeftoverSize); 192 // For irregular sizes, extract the individual parts. 193 for (unsigned I = 0; I != NumParts; ++I) { 194 Register NewReg = MRI.createGenericVirtualRegister(MainTy); 195 VRegs.push_back(NewReg); 196 MIRBuilder.buildExtract(NewReg, Reg, MainSize * I); 197 } 198 199 for (unsigned Offset = MainSize * NumParts; Offset < RegSize; 200 Offset += LeftoverSize) { 201 Register NewReg = MRI.createGenericVirtualRegister(LeftoverTy); 202 LeftoverRegs.push_back(NewReg); 203 MIRBuilder.buildExtract(NewReg, Reg, Offset); 204 } 205 206 return true; 207 } 208 209 void LegalizerHelper::extractVectorParts(Register Reg, unsigned NumElts, 210 SmallVectorImpl<Register> &VRegs) { 211 LLT RegTy = MRI.getType(Reg); 212 assert(RegTy.isVector() && "Expected a vector type"); 213 214 LLT EltTy = RegTy.getElementType(); 215 LLT NarrowTy = (NumElts == 1) ? EltTy : LLT::fixed_vector(NumElts, EltTy); 216 unsigned RegNumElts = RegTy.getNumElements(); 217 unsigned LeftoverNumElts = RegNumElts % NumElts; 218 unsigned NumNarrowTyPieces = RegNumElts / NumElts; 219 220 // Perfect split without leftover 221 if (LeftoverNumElts == 0) 222 return extractParts(Reg, NarrowTy, NumNarrowTyPieces, VRegs); 223 224 // Irregular split. Provide direct access to all elements for artifact 225 // combiner using unmerge to elements. Then build vectors with NumElts 226 // elements. Remaining element(s) will be (used to build vector) Leftover. 227 SmallVector<Register, 8> Elts; 228 extractParts(Reg, EltTy, RegNumElts, Elts); 229 230 unsigned Offset = 0; 231 // Requested sub-vectors of NarrowTy. 232 for (unsigned i = 0; i < NumNarrowTyPieces; ++i, Offset += NumElts) { 233 ArrayRef<Register> Pieces(&Elts[Offset], NumElts); 234 VRegs.push_back(MIRBuilder.buildMerge(NarrowTy, Pieces).getReg(0)); 235 } 236 237 // Leftover element(s). 238 if (LeftoverNumElts == 1) { 239 VRegs.push_back(Elts[Offset]); 240 } else { 241 LLT LeftoverTy = LLT::fixed_vector(LeftoverNumElts, EltTy); 242 ArrayRef<Register> Pieces(&Elts[Offset], LeftoverNumElts); 243 VRegs.push_back(MIRBuilder.buildMerge(LeftoverTy, Pieces).getReg(0)); 244 } 245 } 246 247 void LegalizerHelper::insertParts(Register DstReg, 248 LLT ResultTy, LLT PartTy, 249 ArrayRef<Register> PartRegs, 250 LLT LeftoverTy, 251 ArrayRef<Register> LeftoverRegs) { 252 if (!LeftoverTy.isValid()) { 253 assert(LeftoverRegs.empty()); 254 255 if (!ResultTy.isVector()) { 256 MIRBuilder.buildMerge(DstReg, PartRegs); 257 return; 258 } 259 260 if (PartTy.isVector()) 261 MIRBuilder.buildConcatVectors(DstReg, PartRegs); 262 else 263 MIRBuilder.buildBuildVector(DstReg, PartRegs); 264 return; 265 } 266 267 // Merge sub-vectors with different number of elements and insert into DstReg. 268 if (ResultTy.isVector()) { 269 assert(LeftoverRegs.size() == 1 && "Expected one leftover register"); 270 SmallVector<Register, 8> AllRegs; 271 for (auto Reg : concat<const Register>(PartRegs, LeftoverRegs)) 272 AllRegs.push_back(Reg); 273 return mergeMixedSubvectors(DstReg, AllRegs); 274 } 275 276 SmallVector<Register> GCDRegs; 277 LLT GCDTy = getGCDType(getGCDType(ResultTy, LeftoverTy), PartTy); 278 for (auto PartReg : concat<const Register>(PartRegs, LeftoverRegs)) 279 extractGCDType(GCDRegs, GCDTy, PartReg); 280 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs); 281 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs); 282 } 283 284 void LegalizerHelper::appendVectorElts(SmallVectorImpl<Register> &Elts, 285 Register Reg) { 286 LLT Ty = MRI.getType(Reg); 287 SmallVector<Register, 8> RegElts; 288 extractParts(Reg, Ty.getScalarType(), Ty.getNumElements(), RegElts); 289 Elts.append(RegElts); 290 } 291 292 /// Merge \p PartRegs with different types into \p DstReg. 293 void LegalizerHelper::mergeMixedSubvectors(Register DstReg, 294 ArrayRef<Register> PartRegs) { 295 SmallVector<Register, 8> AllElts; 296 for (unsigned i = 0; i < PartRegs.size() - 1; ++i) 297 appendVectorElts(AllElts, PartRegs[i]); 298 299 Register Leftover = PartRegs[PartRegs.size() - 1]; 300 if (MRI.getType(Leftover).isScalar()) 301 AllElts.push_back(Leftover); 302 else 303 appendVectorElts(AllElts, Leftover); 304 305 MIRBuilder.buildMerge(DstReg, AllElts); 306 } 307 308 /// Append the result registers of G_UNMERGE_VALUES \p MI to \p Regs. 309 static void getUnmergeResults(SmallVectorImpl<Register> &Regs, 310 const MachineInstr &MI) { 311 assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES); 312 313 const int StartIdx = Regs.size(); 314 const int NumResults = MI.getNumOperands() - 1; 315 Regs.resize(Regs.size() + NumResults); 316 for (int I = 0; I != NumResults; ++I) 317 Regs[StartIdx + I] = MI.getOperand(I).getReg(); 318 } 319 320 void LegalizerHelper::extractGCDType(SmallVectorImpl<Register> &Parts, 321 LLT GCDTy, Register SrcReg) { 322 LLT SrcTy = MRI.getType(SrcReg); 323 if (SrcTy == GCDTy) { 324 // If the source already evenly divides the result type, we don't need to do 325 // anything. 326 Parts.push_back(SrcReg); 327 } else { 328 // Need to split into common type sized pieces. 329 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg); 330 getUnmergeResults(Parts, *Unmerge); 331 } 332 } 333 334 LLT LegalizerHelper::extractGCDType(SmallVectorImpl<Register> &Parts, LLT DstTy, 335 LLT NarrowTy, Register SrcReg) { 336 LLT SrcTy = MRI.getType(SrcReg); 337 LLT GCDTy = getGCDType(getGCDType(SrcTy, NarrowTy), DstTy); 338 extractGCDType(Parts, GCDTy, SrcReg); 339 return GCDTy; 340 } 341 342 LLT LegalizerHelper::buildLCMMergePieces(LLT DstTy, LLT NarrowTy, LLT GCDTy, 343 SmallVectorImpl<Register> &VRegs, 344 unsigned PadStrategy) { 345 LLT LCMTy = getLCMType(DstTy, NarrowTy); 346 347 int NumParts = LCMTy.getSizeInBits() / NarrowTy.getSizeInBits(); 348 int NumSubParts = NarrowTy.getSizeInBits() / GCDTy.getSizeInBits(); 349 int NumOrigSrc = VRegs.size(); 350 351 Register PadReg; 352 353 // Get a value we can use to pad the source value if the sources won't evenly 354 // cover the result type. 355 if (NumOrigSrc < NumParts * NumSubParts) { 356 if (PadStrategy == TargetOpcode::G_ZEXT) 357 PadReg = MIRBuilder.buildConstant(GCDTy, 0).getReg(0); 358 else if (PadStrategy == TargetOpcode::G_ANYEXT) 359 PadReg = MIRBuilder.buildUndef(GCDTy).getReg(0); 360 else { 361 assert(PadStrategy == TargetOpcode::G_SEXT); 362 363 // Shift the sign bit of the low register through the high register. 364 auto ShiftAmt = 365 MIRBuilder.buildConstant(LLT::scalar(64), GCDTy.getSizeInBits() - 1); 366 PadReg = MIRBuilder.buildAShr(GCDTy, VRegs.back(), ShiftAmt).getReg(0); 367 } 368 } 369 370 // Registers for the final merge to be produced. 371 SmallVector<Register, 4> Remerge(NumParts); 372 373 // Registers needed for intermediate merges, which will be merged into a 374 // source for Remerge. 375 SmallVector<Register, 4> SubMerge(NumSubParts); 376 377 // Once we've fully read off the end of the original source bits, we can reuse 378 // the same high bits for remaining padding elements. 379 Register AllPadReg; 380 381 // Build merges to the LCM type to cover the original result type. 382 for (int I = 0; I != NumParts; ++I) { 383 bool AllMergePartsArePadding = true; 384 385 // Build the requested merges to the requested type. 386 for (int J = 0; J != NumSubParts; ++J) { 387 int Idx = I * NumSubParts + J; 388 if (Idx >= NumOrigSrc) { 389 SubMerge[J] = PadReg; 390 continue; 391 } 392 393 SubMerge[J] = VRegs[Idx]; 394 395 // There are meaningful bits here we can't reuse later. 396 AllMergePartsArePadding = false; 397 } 398 399 // If we've filled up a complete piece with padding bits, we can directly 400 // emit the natural sized constant if applicable, rather than a merge of 401 // smaller constants. 402 if (AllMergePartsArePadding && !AllPadReg) { 403 if (PadStrategy == TargetOpcode::G_ANYEXT) 404 AllPadReg = MIRBuilder.buildUndef(NarrowTy).getReg(0); 405 else if (PadStrategy == TargetOpcode::G_ZEXT) 406 AllPadReg = MIRBuilder.buildConstant(NarrowTy, 0).getReg(0); 407 408 // If this is a sign extension, we can't materialize a trivial constant 409 // with the right type and have to produce a merge. 410 } 411 412 if (AllPadReg) { 413 // Avoid creating additional instructions if we're just adding additional 414 // copies of padding bits. 415 Remerge[I] = AllPadReg; 416 continue; 417 } 418 419 if (NumSubParts == 1) 420 Remerge[I] = SubMerge[0]; 421 else 422 Remerge[I] = MIRBuilder.buildMerge(NarrowTy, SubMerge).getReg(0); 423 424 // In the sign extend padding case, re-use the first all-signbit merge. 425 if (AllMergePartsArePadding && !AllPadReg) 426 AllPadReg = Remerge[I]; 427 } 428 429 VRegs = std::move(Remerge); 430 return LCMTy; 431 } 432 433 void LegalizerHelper::buildWidenedRemergeToDst(Register DstReg, LLT LCMTy, 434 ArrayRef<Register> RemergeRegs) { 435 LLT DstTy = MRI.getType(DstReg); 436 437 // Create the merge to the widened source, and extract the relevant bits into 438 // the result. 439 440 if (DstTy == LCMTy) { 441 MIRBuilder.buildMerge(DstReg, RemergeRegs); 442 return; 443 } 444 445 auto Remerge = MIRBuilder.buildMerge(LCMTy, RemergeRegs); 446 if (DstTy.isScalar() && LCMTy.isScalar()) { 447 MIRBuilder.buildTrunc(DstReg, Remerge); 448 return; 449 } 450 451 if (LCMTy.isVector()) { 452 unsigned NumDefs = LCMTy.getSizeInBits() / DstTy.getSizeInBits(); 453 SmallVector<Register, 8> UnmergeDefs(NumDefs); 454 UnmergeDefs[0] = DstReg; 455 for (unsigned I = 1; I != NumDefs; ++I) 456 UnmergeDefs[I] = MRI.createGenericVirtualRegister(DstTy); 457 458 MIRBuilder.buildUnmerge(UnmergeDefs, 459 MIRBuilder.buildMerge(LCMTy, RemergeRegs)); 460 return; 461 } 462 463 llvm_unreachable("unhandled case"); 464 } 465 466 static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { 467 #define RTLIBCASE_INT(LibcallPrefix) \ 468 do { \ 469 switch (Size) { \ 470 case 32: \ 471 return RTLIB::LibcallPrefix##32; \ 472 case 64: \ 473 return RTLIB::LibcallPrefix##64; \ 474 case 128: \ 475 return RTLIB::LibcallPrefix##128; \ 476 default: \ 477 llvm_unreachable("unexpected size"); \ 478 } \ 479 } while (0) 480 481 #define RTLIBCASE(LibcallPrefix) \ 482 do { \ 483 switch (Size) { \ 484 case 32: \ 485 return RTLIB::LibcallPrefix##32; \ 486 case 64: \ 487 return RTLIB::LibcallPrefix##64; \ 488 case 80: \ 489 return RTLIB::LibcallPrefix##80; \ 490 case 128: \ 491 return RTLIB::LibcallPrefix##128; \ 492 default: \ 493 llvm_unreachable("unexpected size"); \ 494 } \ 495 } while (0) 496 497 switch (Opcode) { 498 case TargetOpcode::G_SDIV: 499 RTLIBCASE_INT(SDIV_I); 500 case TargetOpcode::G_UDIV: 501 RTLIBCASE_INT(UDIV_I); 502 case TargetOpcode::G_SREM: 503 RTLIBCASE_INT(SREM_I); 504 case TargetOpcode::G_UREM: 505 RTLIBCASE_INT(UREM_I); 506 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 507 RTLIBCASE_INT(CTLZ_I); 508 case TargetOpcode::G_FADD: 509 RTLIBCASE(ADD_F); 510 case TargetOpcode::G_FSUB: 511 RTLIBCASE(SUB_F); 512 case TargetOpcode::G_FMUL: 513 RTLIBCASE(MUL_F); 514 case TargetOpcode::G_FDIV: 515 RTLIBCASE(DIV_F); 516 case TargetOpcode::G_FEXP: 517 RTLIBCASE(EXP_F); 518 case TargetOpcode::G_FEXP2: 519 RTLIBCASE(EXP2_F); 520 case TargetOpcode::G_FREM: 521 RTLIBCASE(REM_F); 522 case TargetOpcode::G_FPOW: 523 RTLIBCASE(POW_F); 524 case TargetOpcode::G_FMA: 525 RTLIBCASE(FMA_F); 526 case TargetOpcode::G_FSIN: 527 RTLIBCASE(SIN_F); 528 case TargetOpcode::G_FCOS: 529 RTLIBCASE(COS_F); 530 case TargetOpcode::G_FLOG10: 531 RTLIBCASE(LOG10_F); 532 case TargetOpcode::G_FLOG: 533 RTLIBCASE(LOG_F); 534 case TargetOpcode::G_FLOG2: 535 RTLIBCASE(LOG2_F); 536 case TargetOpcode::G_FCEIL: 537 RTLIBCASE(CEIL_F); 538 case TargetOpcode::G_FFLOOR: 539 RTLIBCASE(FLOOR_F); 540 case TargetOpcode::G_FMINNUM: 541 RTLIBCASE(FMIN_F); 542 case TargetOpcode::G_FMAXNUM: 543 RTLIBCASE(FMAX_F); 544 case TargetOpcode::G_FSQRT: 545 RTLIBCASE(SQRT_F); 546 case TargetOpcode::G_FRINT: 547 RTLIBCASE(RINT_F); 548 case TargetOpcode::G_FNEARBYINT: 549 RTLIBCASE(NEARBYINT_F); 550 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: 551 RTLIBCASE(ROUNDEVEN_F); 552 } 553 llvm_unreachable("Unknown libcall function"); 554 } 555 556 /// True if an instruction is in tail position in its caller. Intended for 557 /// legalizing libcalls as tail calls when possible. 558 static bool isLibCallInTailPosition(MachineInstr &MI, 559 const TargetInstrInfo &TII, 560 MachineRegisterInfo &MRI) { 561 MachineBasicBlock &MBB = *MI.getParent(); 562 const Function &F = MBB.getParent()->getFunction(); 563 564 // Conservatively require the attributes of the call to match those of 565 // the return. Ignore NoAlias and NonNull because they don't affect the 566 // call sequence. 567 AttributeList CallerAttrs = F.getAttributes(); 568 if (AttrBuilder(F.getContext(), CallerAttrs.getRetAttrs()) 569 .removeAttribute(Attribute::NoAlias) 570 .removeAttribute(Attribute::NonNull) 571 .hasAttributes()) 572 return false; 573 574 // It's not safe to eliminate the sign / zero extension of the return value. 575 if (CallerAttrs.hasRetAttr(Attribute::ZExt) || 576 CallerAttrs.hasRetAttr(Attribute::SExt)) 577 return false; 578 579 // Only tail call if the following instruction is a standard return or if we 580 // have a `thisreturn` callee, and a sequence like: 581 // 582 // G_MEMCPY %0, %1, %2 583 // $x0 = COPY %0 584 // RET_ReallyLR implicit $x0 585 auto Next = next_nodbg(MI.getIterator(), MBB.instr_end()); 586 if (Next != MBB.instr_end() && Next->isCopy()) { 587 switch (MI.getOpcode()) { 588 default: 589 llvm_unreachable("unsupported opcode"); 590 case TargetOpcode::G_BZERO: 591 return false; 592 case TargetOpcode::G_MEMCPY: 593 case TargetOpcode::G_MEMMOVE: 594 case TargetOpcode::G_MEMSET: 595 break; 596 } 597 598 Register VReg = MI.getOperand(0).getReg(); 599 if (!VReg.isVirtual() || VReg != Next->getOperand(1).getReg()) 600 return false; 601 602 Register PReg = Next->getOperand(0).getReg(); 603 if (!PReg.isPhysical()) 604 return false; 605 606 auto Ret = next_nodbg(Next, MBB.instr_end()); 607 if (Ret == MBB.instr_end() || !Ret->isReturn()) 608 return false; 609 610 if (Ret->getNumImplicitOperands() != 1) 611 return false; 612 613 if (PReg != Ret->getOperand(0).getReg()) 614 return false; 615 616 // Skip over the COPY that we just validated. 617 Next = Ret; 618 } 619 620 if (Next == MBB.instr_end() || TII.isTailCall(*Next) || !Next->isReturn()) 621 return false; 622 623 return true; 624 } 625 626 LegalizerHelper::LegalizeResult 627 llvm::createLibcall(MachineIRBuilder &MIRBuilder, const char *Name, 628 const CallLowering::ArgInfo &Result, 629 ArrayRef<CallLowering::ArgInfo> Args, 630 const CallingConv::ID CC) { 631 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 632 633 CallLowering::CallLoweringInfo Info; 634 Info.CallConv = CC; 635 Info.Callee = MachineOperand::CreateES(Name); 636 Info.OrigRet = Result; 637 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs)); 638 if (!CLI.lowerCall(MIRBuilder, Info)) 639 return LegalizerHelper::UnableToLegalize; 640 641 return LegalizerHelper::Legalized; 642 } 643 644 LegalizerHelper::LegalizeResult 645 llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, 646 const CallLowering::ArgInfo &Result, 647 ArrayRef<CallLowering::ArgInfo> Args) { 648 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 649 const char *Name = TLI.getLibcallName(Libcall); 650 const CallingConv::ID CC = TLI.getLibcallCallingConv(Libcall); 651 return createLibcall(MIRBuilder, Name, Result, Args, CC); 652 } 653 654 // Useful for libcalls where all operands have the same type. 655 static LegalizerHelper::LegalizeResult 656 simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, 657 Type *OpType) { 658 auto Libcall = getRTLibDesc(MI.getOpcode(), Size); 659 660 // FIXME: What does the original arg index mean here? 661 SmallVector<CallLowering::ArgInfo, 3> Args; 662 for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) 663 Args.push_back({MO.getReg(), OpType, 0}); 664 return createLibcall(MIRBuilder, Libcall, 665 {MI.getOperand(0).getReg(), OpType, 0}, Args); 666 } 667 668 LegalizerHelper::LegalizeResult 669 llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, 670 MachineInstr &MI, LostDebugLocObserver &LocObserver) { 671 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 672 673 SmallVector<CallLowering::ArgInfo, 3> Args; 674 // Add all the args, except for the last which is an imm denoting 'tail'. 675 for (unsigned i = 0; i < MI.getNumOperands() - 1; ++i) { 676 Register Reg = MI.getOperand(i).getReg(); 677 678 // Need derive an IR type for call lowering. 679 LLT OpLLT = MRI.getType(Reg); 680 Type *OpTy = nullptr; 681 if (OpLLT.isPointer()) 682 OpTy = Type::getInt8PtrTy(Ctx, OpLLT.getAddressSpace()); 683 else 684 OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits()); 685 Args.push_back({Reg, OpTy, 0}); 686 } 687 688 auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); 689 auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); 690 RTLIB::Libcall RTLibcall; 691 unsigned Opc = MI.getOpcode(); 692 switch (Opc) { 693 case TargetOpcode::G_BZERO: 694 RTLibcall = RTLIB::BZERO; 695 break; 696 case TargetOpcode::G_MEMCPY: 697 RTLibcall = RTLIB::MEMCPY; 698 Args[0].Flags[0].setReturned(); 699 break; 700 case TargetOpcode::G_MEMMOVE: 701 RTLibcall = RTLIB::MEMMOVE; 702 Args[0].Flags[0].setReturned(); 703 break; 704 case TargetOpcode::G_MEMSET: 705 RTLibcall = RTLIB::MEMSET; 706 Args[0].Flags[0].setReturned(); 707 break; 708 default: 709 llvm_unreachable("unsupported opcode"); 710 } 711 const char *Name = TLI.getLibcallName(RTLibcall); 712 713 // Unsupported libcall on the target. 714 if (!Name) { 715 LLVM_DEBUG(dbgs() << ".. .. Could not find libcall name for " 716 << MIRBuilder.getTII().getName(Opc) << "\n"); 717 return LegalizerHelper::UnableToLegalize; 718 } 719 720 CallLowering::CallLoweringInfo Info; 721 Info.CallConv = TLI.getLibcallCallingConv(RTLibcall); 722 Info.Callee = MachineOperand::CreateES(Name); 723 Info.OrigRet = CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0); 724 Info.IsTailCall = MI.getOperand(MI.getNumOperands() - 1).getImm() && 725 isLibCallInTailPosition(MI, MIRBuilder.getTII(), MRI); 726 727 std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs)); 728 if (!CLI.lowerCall(MIRBuilder, Info)) 729 return LegalizerHelper::UnableToLegalize; 730 731 if (Info.LoweredTailCall) { 732 assert(Info.IsTailCall && "Lowered tail call when it wasn't a tail call?"); 733 734 // Check debug locations before removing the return. 735 LocObserver.checkpoint(true); 736 737 // We must have a return following the call (or debug insts) to get past 738 // isLibCallInTailPosition. 739 do { 740 MachineInstr *Next = MI.getNextNode(); 741 assert(Next && 742 (Next->isCopy() || Next->isReturn() || Next->isDebugInstr()) && 743 "Expected instr following MI to be return or debug inst?"); 744 // We lowered a tail call, so the call is now the return from the block. 745 // Delete the old return. 746 Next->eraseFromParent(); 747 } while (MI.getNextNode()); 748 749 // We expect to lose the debug location from the return. 750 LocObserver.checkpoint(false); 751 } 752 753 return LegalizerHelper::Legalized; 754 } 755 756 static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, 757 Type *FromType) { 758 auto ToMVT = MVT::getVT(ToType); 759 auto FromMVT = MVT::getVT(FromType); 760 761 switch (Opcode) { 762 case TargetOpcode::G_FPEXT: 763 return RTLIB::getFPEXT(FromMVT, ToMVT); 764 case TargetOpcode::G_FPTRUNC: 765 return RTLIB::getFPROUND(FromMVT, ToMVT); 766 case TargetOpcode::G_FPTOSI: 767 return RTLIB::getFPTOSINT(FromMVT, ToMVT); 768 case TargetOpcode::G_FPTOUI: 769 return RTLIB::getFPTOUINT(FromMVT, ToMVT); 770 case TargetOpcode::G_SITOFP: 771 return RTLIB::getSINTTOFP(FromMVT, ToMVT); 772 case TargetOpcode::G_UITOFP: 773 return RTLIB::getUINTTOFP(FromMVT, ToMVT); 774 } 775 llvm_unreachable("Unsupported libcall function"); 776 } 777 778 static LegalizerHelper::LegalizeResult 779 conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType, 780 Type *FromType) { 781 RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType); 782 return createLibcall(MIRBuilder, Libcall, 783 {MI.getOperand(0).getReg(), ToType, 0}, 784 {{MI.getOperand(1).getReg(), FromType, 0}}); 785 } 786 787 LegalizerHelper::LegalizeResult 788 LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) { 789 LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); 790 unsigned Size = LLTy.getSizeInBits(); 791 auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); 792 793 switch (MI.getOpcode()) { 794 default: 795 return UnableToLegalize; 796 case TargetOpcode::G_SDIV: 797 case TargetOpcode::G_UDIV: 798 case TargetOpcode::G_SREM: 799 case TargetOpcode::G_UREM: 800 case TargetOpcode::G_CTLZ_ZERO_UNDEF: { 801 Type *HLTy = IntegerType::get(Ctx, Size); 802 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 803 if (Status != Legalized) 804 return Status; 805 break; 806 } 807 case TargetOpcode::G_FADD: 808 case TargetOpcode::G_FSUB: 809 case TargetOpcode::G_FMUL: 810 case TargetOpcode::G_FDIV: 811 case TargetOpcode::G_FMA: 812 case TargetOpcode::G_FPOW: 813 case TargetOpcode::G_FREM: 814 case TargetOpcode::G_FCOS: 815 case TargetOpcode::G_FSIN: 816 case TargetOpcode::G_FLOG10: 817 case TargetOpcode::G_FLOG: 818 case TargetOpcode::G_FLOG2: 819 case TargetOpcode::G_FEXP: 820 case TargetOpcode::G_FEXP2: 821 case TargetOpcode::G_FCEIL: 822 case TargetOpcode::G_FFLOOR: 823 case TargetOpcode::G_FMINNUM: 824 case TargetOpcode::G_FMAXNUM: 825 case TargetOpcode::G_FSQRT: 826 case TargetOpcode::G_FRINT: 827 case TargetOpcode::G_FNEARBYINT: 828 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: { 829 Type *HLTy = getFloatTypeForLLT(Ctx, LLTy); 830 if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) { 831 LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n"); 832 return UnableToLegalize; 833 } 834 auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy); 835 if (Status != Legalized) 836 return Status; 837 break; 838 } 839 case TargetOpcode::G_FPEXT: 840 case TargetOpcode::G_FPTRUNC: { 841 Type *FromTy = getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(1).getReg())); 842 Type *ToTy = getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(0).getReg())); 843 if (!FromTy || !ToTy) 844 return UnableToLegalize; 845 LegalizeResult Status = conversionLibcall(MI, MIRBuilder, ToTy, FromTy ); 846 if (Status != Legalized) 847 return Status; 848 break; 849 } 850 case TargetOpcode::G_FPTOSI: 851 case TargetOpcode::G_FPTOUI: { 852 // FIXME: Support other types 853 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 854 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 855 if ((ToSize != 32 && ToSize != 64) || (FromSize != 32 && FromSize != 64)) 856 return UnableToLegalize; 857 LegalizeResult Status = conversionLibcall( 858 MI, MIRBuilder, 859 ToSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx), 860 FromSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx)); 861 if (Status != Legalized) 862 return Status; 863 break; 864 } 865 case TargetOpcode::G_SITOFP: 866 case TargetOpcode::G_UITOFP: { 867 // FIXME: Support other types 868 unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 869 unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 870 if ((FromSize != 32 && FromSize != 64) || (ToSize != 32 && ToSize != 64)) 871 return UnableToLegalize; 872 LegalizeResult Status = conversionLibcall( 873 MI, MIRBuilder, 874 ToSize == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx), 875 FromSize == 32 ? Type::getInt32Ty(Ctx) : Type::getInt64Ty(Ctx)); 876 if (Status != Legalized) 877 return Status; 878 break; 879 } 880 case TargetOpcode::G_BZERO: 881 case TargetOpcode::G_MEMCPY: 882 case TargetOpcode::G_MEMMOVE: 883 case TargetOpcode::G_MEMSET: { 884 LegalizeResult Result = 885 createMemLibcall(MIRBuilder, *MIRBuilder.getMRI(), MI, LocObserver); 886 if (Result != Legalized) 887 return Result; 888 MI.eraseFromParent(); 889 return Result; 890 } 891 } 892 893 MI.eraseFromParent(); 894 return Legalized; 895 } 896 897 LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, 898 unsigned TypeIdx, 899 LLT NarrowTy) { 900 uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 901 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 902 903 switch (MI.getOpcode()) { 904 default: 905 return UnableToLegalize; 906 case TargetOpcode::G_IMPLICIT_DEF: { 907 Register DstReg = MI.getOperand(0).getReg(); 908 LLT DstTy = MRI.getType(DstReg); 909 910 // If SizeOp0 is not an exact multiple of NarrowSize, emit 911 // G_ANYEXT(G_IMPLICIT_DEF). Cast result to vector if needed. 912 // FIXME: Although this would also be legal for the general case, it causes 913 // a lot of regressions in the emitted code (superfluous COPYs, artifact 914 // combines not being hit). This seems to be a problem related to the 915 // artifact combiner. 916 if (SizeOp0 % NarrowSize != 0) { 917 LLT ImplicitTy = NarrowTy; 918 if (DstTy.isVector()) 919 ImplicitTy = LLT::vector(DstTy.getElementCount(), ImplicitTy); 920 921 Register ImplicitReg = MIRBuilder.buildUndef(ImplicitTy).getReg(0); 922 MIRBuilder.buildAnyExt(DstReg, ImplicitReg); 923 924 MI.eraseFromParent(); 925 return Legalized; 926 } 927 928 int NumParts = SizeOp0 / NarrowSize; 929 930 SmallVector<Register, 2> DstRegs; 931 for (int i = 0; i < NumParts; ++i) 932 DstRegs.push_back(MIRBuilder.buildUndef(NarrowTy).getReg(0)); 933 934 if (DstTy.isVector()) 935 MIRBuilder.buildBuildVector(DstReg, DstRegs); 936 else 937 MIRBuilder.buildMerge(DstReg, DstRegs); 938 MI.eraseFromParent(); 939 return Legalized; 940 } 941 case TargetOpcode::G_CONSTANT: { 942 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 943 const APInt &Val = MI.getOperand(1).getCImm()->getValue(); 944 unsigned TotalSize = Ty.getSizeInBits(); 945 unsigned NarrowSize = NarrowTy.getSizeInBits(); 946 int NumParts = TotalSize / NarrowSize; 947 948 SmallVector<Register, 4> PartRegs; 949 for (int I = 0; I != NumParts; ++I) { 950 unsigned Offset = I * NarrowSize; 951 auto K = MIRBuilder.buildConstant(NarrowTy, 952 Val.lshr(Offset).trunc(NarrowSize)); 953 PartRegs.push_back(K.getReg(0)); 954 } 955 956 LLT LeftoverTy; 957 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize; 958 SmallVector<Register, 1> LeftoverRegs; 959 if (LeftoverBits != 0) { 960 LeftoverTy = LLT::scalar(LeftoverBits); 961 auto K = MIRBuilder.buildConstant( 962 LeftoverTy, 963 Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits)); 964 LeftoverRegs.push_back(K.getReg(0)); 965 } 966 967 insertParts(MI.getOperand(0).getReg(), 968 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs); 969 970 MI.eraseFromParent(); 971 return Legalized; 972 } 973 case TargetOpcode::G_SEXT: 974 case TargetOpcode::G_ZEXT: 975 case TargetOpcode::G_ANYEXT: 976 return narrowScalarExt(MI, TypeIdx, NarrowTy); 977 case TargetOpcode::G_TRUNC: { 978 if (TypeIdx != 1) 979 return UnableToLegalize; 980 981 uint64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 982 if (NarrowTy.getSizeInBits() * 2 != SizeOp1) { 983 LLVM_DEBUG(dbgs() << "Can't narrow trunc to type " << NarrowTy << "\n"); 984 return UnableToLegalize; 985 } 986 987 auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1)); 988 MIRBuilder.buildCopy(MI.getOperand(0), Unmerge.getReg(0)); 989 MI.eraseFromParent(); 990 return Legalized; 991 } 992 993 case TargetOpcode::G_FREEZE: { 994 if (TypeIdx != 0) 995 return UnableToLegalize; 996 997 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 998 // Should widen scalar first 999 if (Ty.getSizeInBits() % NarrowTy.getSizeInBits() != 0) 1000 return UnableToLegalize; 1001 1002 auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1).getReg()); 1003 SmallVector<Register, 8> Parts; 1004 for (unsigned i = 0; i < Unmerge->getNumDefs(); ++i) { 1005 Parts.push_back( 1006 MIRBuilder.buildFreeze(NarrowTy, Unmerge.getReg(i)).getReg(0)); 1007 } 1008 1009 MIRBuilder.buildMerge(MI.getOperand(0).getReg(), Parts); 1010 MI.eraseFromParent(); 1011 return Legalized; 1012 } 1013 case TargetOpcode::G_ADD: 1014 case TargetOpcode::G_SUB: 1015 case TargetOpcode::G_SADDO: 1016 case TargetOpcode::G_SSUBO: 1017 case TargetOpcode::G_SADDE: 1018 case TargetOpcode::G_SSUBE: 1019 case TargetOpcode::G_UADDO: 1020 case TargetOpcode::G_USUBO: 1021 case TargetOpcode::G_UADDE: 1022 case TargetOpcode::G_USUBE: 1023 return narrowScalarAddSub(MI, TypeIdx, NarrowTy); 1024 case TargetOpcode::G_MUL: 1025 case TargetOpcode::G_UMULH: 1026 return narrowScalarMul(MI, NarrowTy); 1027 case TargetOpcode::G_EXTRACT: 1028 return narrowScalarExtract(MI, TypeIdx, NarrowTy); 1029 case TargetOpcode::G_INSERT: 1030 return narrowScalarInsert(MI, TypeIdx, NarrowTy); 1031 case TargetOpcode::G_LOAD: { 1032 auto &LoadMI = cast<GLoad>(MI); 1033 Register DstReg = LoadMI.getDstReg(); 1034 LLT DstTy = MRI.getType(DstReg); 1035 if (DstTy.isVector()) 1036 return UnableToLegalize; 1037 1038 if (8 * LoadMI.getMemSize() != DstTy.getSizeInBits()) { 1039 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 1040 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO()); 1041 MIRBuilder.buildAnyExt(DstReg, TmpReg); 1042 LoadMI.eraseFromParent(); 1043 return Legalized; 1044 } 1045 1046 return reduceLoadStoreWidth(LoadMI, TypeIdx, NarrowTy); 1047 } 1048 case TargetOpcode::G_ZEXTLOAD: 1049 case TargetOpcode::G_SEXTLOAD: { 1050 auto &LoadMI = cast<GExtLoad>(MI); 1051 Register DstReg = LoadMI.getDstReg(); 1052 Register PtrReg = LoadMI.getPointerReg(); 1053 1054 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 1055 auto &MMO = LoadMI.getMMO(); 1056 unsigned MemSize = MMO.getSizeInBits(); 1057 1058 if (MemSize == NarrowSize) { 1059 MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); 1060 } else if (MemSize < NarrowSize) { 1061 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO); 1062 } else if (MemSize > NarrowSize) { 1063 // FIXME: Need to split the load. 1064 return UnableToLegalize; 1065 } 1066 1067 if (isa<GZExtLoad>(LoadMI)) 1068 MIRBuilder.buildZExt(DstReg, TmpReg); 1069 else 1070 MIRBuilder.buildSExt(DstReg, TmpReg); 1071 1072 LoadMI.eraseFromParent(); 1073 return Legalized; 1074 } 1075 case TargetOpcode::G_STORE: { 1076 auto &StoreMI = cast<GStore>(MI); 1077 1078 Register SrcReg = StoreMI.getValueReg(); 1079 LLT SrcTy = MRI.getType(SrcReg); 1080 if (SrcTy.isVector()) 1081 return UnableToLegalize; 1082 1083 int NumParts = SizeOp0 / NarrowSize; 1084 unsigned HandledSize = NumParts * NarrowTy.getSizeInBits(); 1085 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize; 1086 if (SrcTy.isVector() && LeftoverBits != 0) 1087 return UnableToLegalize; 1088 1089 if (8 * StoreMI.getMemSize() != SrcTy.getSizeInBits()) { 1090 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); 1091 MIRBuilder.buildTrunc(TmpReg, SrcReg); 1092 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO()); 1093 StoreMI.eraseFromParent(); 1094 return Legalized; 1095 } 1096 1097 return reduceLoadStoreWidth(StoreMI, 0, NarrowTy); 1098 } 1099 case TargetOpcode::G_SELECT: 1100 return narrowScalarSelect(MI, TypeIdx, NarrowTy); 1101 case TargetOpcode::G_AND: 1102 case TargetOpcode::G_OR: 1103 case TargetOpcode::G_XOR: { 1104 // Legalize bitwise operation: 1105 // A = BinOp<Ty> B, C 1106 // into: 1107 // B1, ..., BN = G_UNMERGE_VALUES B 1108 // C1, ..., CN = G_UNMERGE_VALUES C 1109 // A1 = BinOp<Ty/N> B1, C2 1110 // ... 1111 // AN = BinOp<Ty/N> BN, CN 1112 // A = G_MERGE_VALUES A1, ..., AN 1113 return narrowScalarBasic(MI, TypeIdx, NarrowTy); 1114 } 1115 case TargetOpcode::G_SHL: 1116 case TargetOpcode::G_LSHR: 1117 case TargetOpcode::G_ASHR: 1118 return narrowScalarShift(MI, TypeIdx, NarrowTy); 1119 case TargetOpcode::G_CTLZ: 1120 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 1121 case TargetOpcode::G_CTTZ: 1122 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 1123 case TargetOpcode::G_CTPOP: 1124 if (TypeIdx == 1) 1125 switch (MI.getOpcode()) { 1126 case TargetOpcode::G_CTLZ: 1127 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 1128 return narrowScalarCTLZ(MI, TypeIdx, NarrowTy); 1129 case TargetOpcode::G_CTTZ: 1130 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 1131 return narrowScalarCTTZ(MI, TypeIdx, NarrowTy); 1132 case TargetOpcode::G_CTPOP: 1133 return narrowScalarCTPOP(MI, TypeIdx, NarrowTy); 1134 default: 1135 return UnableToLegalize; 1136 } 1137 1138 Observer.changingInstr(MI); 1139 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT); 1140 Observer.changedInstr(MI); 1141 return Legalized; 1142 case TargetOpcode::G_INTTOPTR: 1143 if (TypeIdx != 1) 1144 return UnableToLegalize; 1145 1146 Observer.changingInstr(MI); 1147 narrowScalarSrc(MI, NarrowTy, 1); 1148 Observer.changedInstr(MI); 1149 return Legalized; 1150 case TargetOpcode::G_PTRTOINT: 1151 if (TypeIdx != 0) 1152 return UnableToLegalize; 1153 1154 Observer.changingInstr(MI); 1155 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT); 1156 Observer.changedInstr(MI); 1157 return Legalized; 1158 case TargetOpcode::G_PHI: { 1159 // FIXME: add support for when SizeOp0 isn't an exact multiple of 1160 // NarrowSize. 1161 if (SizeOp0 % NarrowSize != 0) 1162 return UnableToLegalize; 1163 1164 unsigned NumParts = SizeOp0 / NarrowSize; 1165 SmallVector<Register, 2> DstRegs(NumParts); 1166 SmallVector<SmallVector<Register, 2>, 2> SrcRegs(MI.getNumOperands() / 2); 1167 Observer.changingInstr(MI); 1168 for (unsigned i = 1; i < MI.getNumOperands(); i += 2) { 1169 MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB(); 1170 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 1171 extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts, 1172 SrcRegs[i / 2]); 1173 } 1174 MachineBasicBlock &MBB = *MI.getParent(); 1175 MIRBuilder.setInsertPt(MBB, MI); 1176 for (unsigned i = 0; i < NumParts; ++i) { 1177 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy); 1178 MachineInstrBuilder MIB = 1179 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]); 1180 for (unsigned j = 1; j < MI.getNumOperands(); j += 2) 1181 MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1)); 1182 } 1183 MIRBuilder.setInsertPt(MBB, MBB.getFirstNonPHI()); 1184 MIRBuilder.buildMerge(MI.getOperand(0), DstRegs); 1185 Observer.changedInstr(MI); 1186 MI.eraseFromParent(); 1187 return Legalized; 1188 } 1189 case TargetOpcode::G_EXTRACT_VECTOR_ELT: 1190 case TargetOpcode::G_INSERT_VECTOR_ELT: { 1191 if (TypeIdx != 2) 1192 return UnableToLegalize; 1193 1194 int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3; 1195 Observer.changingInstr(MI); 1196 narrowScalarSrc(MI, NarrowTy, OpIdx); 1197 Observer.changedInstr(MI); 1198 return Legalized; 1199 } 1200 case TargetOpcode::G_ICMP: { 1201 Register LHS = MI.getOperand(2).getReg(); 1202 LLT SrcTy = MRI.getType(LHS); 1203 uint64_t SrcSize = SrcTy.getSizeInBits(); 1204 CmpInst::Predicate Pred = 1205 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()); 1206 1207 // TODO: Handle the non-equality case for weird sizes. 1208 if (NarrowSize * 2 != SrcSize && !ICmpInst::isEquality(Pred)) 1209 return UnableToLegalize; 1210 1211 LLT LeftoverTy; // Example: s88 -> s64 (NarrowTy) + s24 (leftover) 1212 SmallVector<Register, 4> LHSPartRegs, LHSLeftoverRegs; 1213 if (!extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs, 1214 LHSLeftoverRegs)) 1215 return UnableToLegalize; 1216 1217 LLT Unused; // Matches LeftoverTy; G_ICMP LHS and RHS are the same type. 1218 SmallVector<Register, 4> RHSPartRegs, RHSLeftoverRegs; 1219 if (!extractParts(MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused, 1220 RHSPartRegs, RHSLeftoverRegs)) 1221 return UnableToLegalize; 1222 1223 // We now have the LHS and RHS of the compare split into narrow-type 1224 // registers, plus potentially some leftover type. 1225 Register Dst = MI.getOperand(0).getReg(); 1226 LLT ResTy = MRI.getType(Dst); 1227 if (ICmpInst::isEquality(Pred)) { 1228 // For each part on the LHS and RHS, keep track of the result of XOR-ing 1229 // them together. For each equal part, the result should be all 0s. For 1230 // each non-equal part, we'll get at least one 1. 1231 auto Zero = MIRBuilder.buildConstant(NarrowTy, 0); 1232 SmallVector<Register, 4> Xors; 1233 for (auto LHSAndRHS : zip(LHSPartRegs, RHSPartRegs)) { 1234 auto LHS = std::get<0>(LHSAndRHS); 1235 auto RHS = std::get<1>(LHSAndRHS); 1236 auto Xor = MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0); 1237 Xors.push_back(Xor); 1238 } 1239 1240 // Build a G_XOR for each leftover register. Each G_XOR must be widened 1241 // to the desired narrow type so that we can OR them together later. 1242 SmallVector<Register, 4> WidenedXors; 1243 for (auto LHSAndRHS : zip(LHSLeftoverRegs, RHSLeftoverRegs)) { 1244 auto LHS = std::get<0>(LHSAndRHS); 1245 auto RHS = std::get<1>(LHSAndRHS); 1246 auto Xor = MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0); 1247 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy, Xor); 1248 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors, 1249 /* PadStrategy = */ TargetOpcode::G_ZEXT); 1250 Xors.insert(Xors.end(), WidenedXors.begin(), WidenedXors.end()); 1251 } 1252 1253 // Now, for each part we broke up, we know if they are equal/not equal 1254 // based off the G_XOR. We can OR these all together and compare against 1255 // 0 to get the result. 1256 assert(Xors.size() >= 2 && "Should have gotten at least two Xors?"); 1257 auto Or = MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]); 1258 for (unsigned I = 2, E = Xors.size(); I < E; ++I) 1259 Or = MIRBuilder.buildOr(NarrowTy, Or, Xors[I]); 1260 MIRBuilder.buildICmp(Pred, Dst, Or, Zero); 1261 } else { 1262 // TODO: Handle non-power-of-two types. 1263 assert(LHSPartRegs.size() == 2 && "Expected exactly 2 LHS part regs?"); 1264 assert(RHSPartRegs.size() == 2 && "Expected exactly 2 RHS part regs?"); 1265 Register LHSL = LHSPartRegs[0]; 1266 Register LHSH = LHSPartRegs[1]; 1267 Register RHSL = RHSPartRegs[0]; 1268 Register RHSH = RHSPartRegs[1]; 1269 MachineInstrBuilder CmpH = MIRBuilder.buildICmp(Pred, ResTy, LHSH, RHSH); 1270 MachineInstrBuilder CmpHEQ = 1271 MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy, LHSH, RHSH); 1272 MachineInstrBuilder CmpLU = MIRBuilder.buildICmp( 1273 ICmpInst::getUnsignedPredicate(Pred), ResTy, LHSL, RHSL); 1274 MIRBuilder.buildSelect(Dst, CmpHEQ, CmpLU, CmpH); 1275 } 1276 MI.eraseFromParent(); 1277 return Legalized; 1278 } 1279 case TargetOpcode::G_SEXT_INREG: { 1280 if (TypeIdx != 0) 1281 return UnableToLegalize; 1282 1283 int64_t SizeInBits = MI.getOperand(2).getImm(); 1284 1285 // So long as the new type has more bits than the bits we're extending we 1286 // don't need to break it apart. 1287 if (NarrowTy.getScalarSizeInBits() >= SizeInBits) { 1288 Observer.changingInstr(MI); 1289 // We don't lose any non-extension bits by truncating the src and 1290 // sign-extending the dst. 1291 MachineOperand &MO1 = MI.getOperand(1); 1292 auto TruncMIB = MIRBuilder.buildTrunc(NarrowTy, MO1); 1293 MO1.setReg(TruncMIB.getReg(0)); 1294 1295 MachineOperand &MO2 = MI.getOperand(0); 1296 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy); 1297 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1298 MIRBuilder.buildSExt(MO2, DstExt); 1299 MO2.setReg(DstExt); 1300 Observer.changedInstr(MI); 1301 return Legalized; 1302 } 1303 1304 // Break it apart. Components below the extension point are unmodified. The 1305 // component containing the extension point becomes a narrower SEXT_INREG. 1306 // Components above it are ashr'd from the component containing the 1307 // extension point. 1308 if (SizeOp0 % NarrowSize != 0) 1309 return UnableToLegalize; 1310 int NumParts = SizeOp0 / NarrowSize; 1311 1312 // List the registers where the destination will be scattered. 1313 SmallVector<Register, 2> DstRegs; 1314 // List the registers where the source will be split. 1315 SmallVector<Register, 2> SrcRegs; 1316 1317 // Create all the temporary registers. 1318 for (int i = 0; i < NumParts; ++i) { 1319 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy); 1320 1321 SrcRegs.push_back(SrcReg); 1322 } 1323 1324 // Explode the big arguments into smaller chunks. 1325 MIRBuilder.buildUnmerge(SrcRegs, MI.getOperand(1)); 1326 1327 Register AshrCstReg = 1328 MIRBuilder.buildConstant(NarrowTy, NarrowTy.getScalarSizeInBits() - 1) 1329 .getReg(0); 1330 Register FullExtensionReg = 0; 1331 Register PartialExtensionReg = 0; 1332 1333 // Do the operation on each small part. 1334 for (int i = 0; i < NumParts; ++i) { 1335 if ((i + 1) * NarrowTy.getScalarSizeInBits() < SizeInBits) 1336 DstRegs.push_back(SrcRegs[i]); 1337 else if (i * NarrowTy.getScalarSizeInBits() > SizeInBits) { 1338 assert(PartialExtensionReg && 1339 "Expected to visit partial extension before full"); 1340 if (FullExtensionReg) { 1341 DstRegs.push_back(FullExtensionReg); 1342 continue; 1343 } 1344 DstRegs.push_back( 1345 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg) 1346 .getReg(0)); 1347 FullExtensionReg = DstRegs.back(); 1348 } else { 1349 DstRegs.push_back( 1350 MIRBuilder 1351 .buildInstr( 1352 TargetOpcode::G_SEXT_INREG, {NarrowTy}, 1353 {SrcRegs[i], SizeInBits % NarrowTy.getScalarSizeInBits()}) 1354 .getReg(0)); 1355 PartialExtensionReg = DstRegs.back(); 1356 } 1357 } 1358 1359 // Gather the destination registers into the final destination. 1360 Register DstReg = MI.getOperand(0).getReg(); 1361 MIRBuilder.buildMerge(DstReg, DstRegs); 1362 MI.eraseFromParent(); 1363 return Legalized; 1364 } 1365 case TargetOpcode::G_BSWAP: 1366 case TargetOpcode::G_BITREVERSE: { 1367 if (SizeOp0 % NarrowSize != 0) 1368 return UnableToLegalize; 1369 1370 Observer.changingInstr(MI); 1371 SmallVector<Register, 2> SrcRegs, DstRegs; 1372 unsigned NumParts = SizeOp0 / NarrowSize; 1373 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 1374 1375 for (unsigned i = 0; i < NumParts; ++i) { 1376 auto DstPart = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy}, 1377 {SrcRegs[NumParts - 1 - i]}); 1378 DstRegs.push_back(DstPart.getReg(0)); 1379 } 1380 1381 MIRBuilder.buildMerge(MI.getOperand(0), DstRegs); 1382 1383 Observer.changedInstr(MI); 1384 MI.eraseFromParent(); 1385 return Legalized; 1386 } 1387 case TargetOpcode::G_PTR_ADD: 1388 case TargetOpcode::G_PTRMASK: { 1389 if (TypeIdx != 1) 1390 return UnableToLegalize; 1391 Observer.changingInstr(MI); 1392 narrowScalarSrc(MI, NarrowTy, 2); 1393 Observer.changedInstr(MI); 1394 return Legalized; 1395 } 1396 case TargetOpcode::G_FPTOUI: 1397 case TargetOpcode::G_FPTOSI: 1398 return narrowScalarFPTOI(MI, TypeIdx, NarrowTy); 1399 case TargetOpcode::G_FPEXT: 1400 if (TypeIdx != 0) 1401 return UnableToLegalize; 1402 Observer.changingInstr(MI); 1403 narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_FPEXT); 1404 Observer.changedInstr(MI); 1405 return Legalized; 1406 } 1407 } 1408 1409 Register LegalizerHelper::coerceToScalar(Register Val) { 1410 LLT Ty = MRI.getType(Val); 1411 if (Ty.isScalar()) 1412 return Val; 1413 1414 const DataLayout &DL = MIRBuilder.getDataLayout(); 1415 LLT NewTy = LLT::scalar(Ty.getSizeInBits()); 1416 if (Ty.isPointer()) { 1417 if (DL.isNonIntegralAddressSpace(Ty.getAddressSpace())) 1418 return Register(); 1419 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0); 1420 } 1421 1422 Register NewVal = Val; 1423 1424 assert(Ty.isVector()); 1425 LLT EltTy = Ty.getElementType(); 1426 if (EltTy.isPointer()) 1427 NewVal = MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0); 1428 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0); 1429 } 1430 1431 void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy, 1432 unsigned OpIdx, unsigned ExtOpcode) { 1433 MachineOperand &MO = MI.getOperand(OpIdx); 1434 auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO}); 1435 MO.setReg(ExtB.getReg(0)); 1436 } 1437 1438 void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, 1439 unsigned OpIdx) { 1440 MachineOperand &MO = MI.getOperand(OpIdx); 1441 auto ExtB = MIRBuilder.buildTrunc(NarrowTy, MO); 1442 MO.setReg(ExtB.getReg(0)); 1443 } 1444 1445 void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy, 1446 unsigned OpIdx, unsigned TruncOpcode) { 1447 MachineOperand &MO = MI.getOperand(OpIdx); 1448 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 1449 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1450 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt}); 1451 MO.setReg(DstExt); 1452 } 1453 1454 void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy, 1455 unsigned OpIdx, unsigned ExtOpcode) { 1456 MachineOperand &MO = MI.getOperand(OpIdx); 1457 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy); 1458 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1459 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc}); 1460 MO.setReg(DstTrunc); 1461 } 1462 1463 void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy, 1464 unsigned OpIdx) { 1465 MachineOperand &MO = MI.getOperand(OpIdx); 1466 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1467 Register Dst = MO.getReg(); 1468 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 1469 MO.setReg(DstExt); 1470 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt); 1471 } 1472 1473 void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, 1474 unsigned OpIdx) { 1475 MachineOperand &MO = MI.getOperand(OpIdx); 1476 SmallVector<Register, 8> Regs; 1477 MO.setReg(MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0)); 1478 } 1479 1480 void LegalizerHelper::bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx) { 1481 MachineOperand &Op = MI.getOperand(OpIdx); 1482 Op.setReg(MIRBuilder.buildBitcast(CastTy, Op).getReg(0)); 1483 } 1484 1485 void LegalizerHelper::bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx) { 1486 MachineOperand &MO = MI.getOperand(OpIdx); 1487 Register CastDst = MRI.createGenericVirtualRegister(CastTy); 1488 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 1489 MIRBuilder.buildBitcast(MO, CastDst); 1490 MO.setReg(CastDst); 1491 } 1492 1493 LegalizerHelper::LegalizeResult 1494 LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, 1495 LLT WideTy) { 1496 if (TypeIdx != 1) 1497 return UnableToLegalize; 1498 1499 Register DstReg = MI.getOperand(0).getReg(); 1500 LLT DstTy = MRI.getType(DstReg); 1501 if (DstTy.isVector()) 1502 return UnableToLegalize; 1503 1504 Register Src1 = MI.getOperand(1).getReg(); 1505 LLT SrcTy = MRI.getType(Src1); 1506 const int DstSize = DstTy.getSizeInBits(); 1507 const int SrcSize = SrcTy.getSizeInBits(); 1508 const int WideSize = WideTy.getSizeInBits(); 1509 const int NumMerge = (DstSize + WideSize - 1) / WideSize; 1510 1511 unsigned NumOps = MI.getNumOperands(); 1512 unsigned NumSrc = MI.getNumOperands() - 1; 1513 unsigned PartSize = DstTy.getSizeInBits() / NumSrc; 1514 1515 if (WideSize >= DstSize) { 1516 // Directly pack the bits in the target type. 1517 Register ResultReg = MIRBuilder.buildZExt(WideTy, Src1).getReg(0); 1518 1519 for (unsigned I = 2; I != NumOps; ++I) { 1520 const unsigned Offset = (I - 1) * PartSize; 1521 1522 Register SrcReg = MI.getOperand(I).getReg(); 1523 assert(MRI.getType(SrcReg) == LLT::scalar(PartSize)); 1524 1525 auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg); 1526 1527 Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg : 1528 MRI.createGenericVirtualRegister(WideTy); 1529 1530 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset); 1531 auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt); 1532 MIRBuilder.buildOr(NextResult, ResultReg, Shl); 1533 ResultReg = NextResult; 1534 } 1535 1536 if (WideSize > DstSize) 1537 MIRBuilder.buildTrunc(DstReg, ResultReg); 1538 else if (DstTy.isPointer()) 1539 MIRBuilder.buildIntToPtr(DstReg, ResultReg); 1540 1541 MI.eraseFromParent(); 1542 return Legalized; 1543 } 1544 1545 // Unmerge the original values to the GCD type, and recombine to the next 1546 // multiple greater than the original type. 1547 // 1548 // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6 1549 // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0 1550 // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1 1551 // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2 1552 // %10:_(s6) = G_MERGE_VALUES %4, %5, %6 1553 // %11:_(s6) = G_MERGE_VALUES %7, %8, %9 1554 // %12:_(s12) = G_MERGE_VALUES %10, %11 1555 // 1556 // Padding with undef if necessary: 1557 // 1558 // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6 1559 // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0 1560 // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1 1561 // %7:_(s2) = G_IMPLICIT_DEF 1562 // %8:_(s6) = G_MERGE_VALUES %3, %4, %5 1563 // %9:_(s6) = G_MERGE_VALUES %6, %7, %7 1564 // %10:_(s12) = G_MERGE_VALUES %8, %9 1565 1566 const int GCD = greatestCommonDivisor(SrcSize, WideSize); 1567 LLT GCDTy = LLT::scalar(GCD); 1568 1569 SmallVector<Register, 8> Parts; 1570 SmallVector<Register, 8> NewMergeRegs; 1571 SmallVector<Register, 8> Unmerges; 1572 LLT WideDstTy = LLT::scalar(NumMerge * WideSize); 1573 1574 // Decompose the original operands if they don't evenly divide. 1575 for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) { 1576 Register SrcReg = MO.getReg(); 1577 if (GCD == SrcSize) { 1578 Unmerges.push_back(SrcReg); 1579 } else { 1580 auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg); 1581 for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J) 1582 Unmerges.push_back(Unmerge.getReg(J)); 1583 } 1584 } 1585 1586 // Pad with undef to the next size that is a multiple of the requested size. 1587 if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) { 1588 Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0); 1589 for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I) 1590 Unmerges.push_back(UndefReg); 1591 } 1592 1593 const int PartsPerGCD = WideSize / GCD; 1594 1595 // Build merges of each piece. 1596 ArrayRef<Register> Slicer(Unmerges); 1597 for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) { 1598 auto Merge = MIRBuilder.buildMerge(WideTy, Slicer.take_front(PartsPerGCD)); 1599 NewMergeRegs.push_back(Merge.getReg(0)); 1600 } 1601 1602 // A truncate may be necessary if the requested type doesn't evenly divide the 1603 // original result type. 1604 if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) { 1605 MIRBuilder.buildMerge(DstReg, NewMergeRegs); 1606 } else { 1607 auto FinalMerge = MIRBuilder.buildMerge(WideDstTy, NewMergeRegs); 1608 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0)); 1609 } 1610 1611 MI.eraseFromParent(); 1612 return Legalized; 1613 } 1614 1615 Register LegalizerHelper::widenWithUnmerge(LLT WideTy, Register OrigReg) { 1616 Register WideReg = MRI.createGenericVirtualRegister(WideTy); 1617 LLT OrigTy = MRI.getType(OrigReg); 1618 LLT LCMTy = getLCMType(WideTy, OrigTy); 1619 1620 const int NumMergeParts = LCMTy.getSizeInBits() / WideTy.getSizeInBits(); 1621 const int NumUnmergeParts = LCMTy.getSizeInBits() / OrigTy.getSizeInBits(); 1622 1623 Register UnmergeSrc = WideReg; 1624 1625 // Create a merge to the LCM type, padding with undef 1626 // %0:_(<3 x s32>) = G_FOO => <4 x s32> 1627 // => 1628 // %1:_(<4 x s32>) = G_FOO 1629 // %2:_(<4 x s32>) = G_IMPLICIT_DEF 1630 // %3:_(<12 x s32>) = G_CONCAT_VECTORS %1, %2, %2 1631 // %0:_(<3 x s32>), %4:_, %5:_, %6:_ = G_UNMERGE_VALUES %3 1632 if (NumMergeParts > 1) { 1633 Register Undef = MIRBuilder.buildUndef(WideTy).getReg(0); 1634 SmallVector<Register, 8> MergeParts(NumMergeParts, Undef); 1635 MergeParts[0] = WideReg; 1636 UnmergeSrc = MIRBuilder.buildMerge(LCMTy, MergeParts).getReg(0); 1637 } 1638 1639 // Unmerge to the original register and pad with dead defs. 1640 SmallVector<Register, 8> UnmergeResults(NumUnmergeParts); 1641 UnmergeResults[0] = OrigReg; 1642 for (int I = 1; I != NumUnmergeParts; ++I) 1643 UnmergeResults[I] = MRI.createGenericVirtualRegister(OrigTy); 1644 1645 MIRBuilder.buildUnmerge(UnmergeResults, UnmergeSrc); 1646 return WideReg; 1647 } 1648 1649 LegalizerHelper::LegalizeResult 1650 LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, 1651 LLT WideTy) { 1652 if (TypeIdx != 0) 1653 return UnableToLegalize; 1654 1655 int NumDst = MI.getNumOperands() - 1; 1656 Register SrcReg = MI.getOperand(NumDst).getReg(); 1657 LLT SrcTy = MRI.getType(SrcReg); 1658 if (SrcTy.isVector()) 1659 return UnableToLegalize; 1660 1661 Register Dst0Reg = MI.getOperand(0).getReg(); 1662 LLT DstTy = MRI.getType(Dst0Reg); 1663 if (!DstTy.isScalar()) 1664 return UnableToLegalize; 1665 1666 if (WideTy.getSizeInBits() >= SrcTy.getSizeInBits()) { 1667 if (SrcTy.isPointer()) { 1668 const DataLayout &DL = MIRBuilder.getDataLayout(); 1669 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) { 1670 LLVM_DEBUG( 1671 dbgs() << "Not casting non-integral address space integer\n"); 1672 return UnableToLegalize; 1673 } 1674 1675 SrcTy = LLT::scalar(SrcTy.getSizeInBits()); 1676 SrcReg = MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0); 1677 } 1678 1679 // Widen SrcTy to WideTy. This does not affect the result, but since the 1680 // user requested this size, it is probably better handled than SrcTy and 1681 // should reduce the total number of legalization artifacts. 1682 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) { 1683 SrcTy = WideTy; 1684 SrcReg = MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0); 1685 } 1686 1687 // Theres no unmerge type to target. Directly extract the bits from the 1688 // source type 1689 unsigned DstSize = DstTy.getSizeInBits(); 1690 1691 MIRBuilder.buildTrunc(Dst0Reg, SrcReg); 1692 for (int I = 1; I != NumDst; ++I) { 1693 auto ShiftAmt = MIRBuilder.buildConstant(SrcTy, DstSize * I); 1694 auto Shr = MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt); 1695 MIRBuilder.buildTrunc(MI.getOperand(I), Shr); 1696 } 1697 1698 MI.eraseFromParent(); 1699 return Legalized; 1700 } 1701 1702 // Extend the source to a wider type. 1703 LLT LCMTy = getLCMType(SrcTy, WideTy); 1704 1705 Register WideSrc = SrcReg; 1706 if (LCMTy.getSizeInBits() != SrcTy.getSizeInBits()) { 1707 // TODO: If this is an integral address space, cast to integer and anyext. 1708 if (SrcTy.isPointer()) { 1709 LLVM_DEBUG(dbgs() << "Widening pointer source types not implemented\n"); 1710 return UnableToLegalize; 1711 } 1712 1713 WideSrc = MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0); 1714 } 1715 1716 auto Unmerge = MIRBuilder.buildUnmerge(WideTy, WideSrc); 1717 1718 // Create a sequence of unmerges and merges to the original results. Since we 1719 // may have widened the source, we will need to pad the results with dead defs 1720 // to cover the source register. 1721 // e.g. widen s48 to s64: 1722 // %1:_(s48), %2:_(s48) = G_UNMERGE_VALUES %0:_(s96) 1723 // 1724 // => 1725 // %4:_(s192) = G_ANYEXT %0:_(s96) 1726 // %5:_(s64), %6, %7 = G_UNMERGE_VALUES %4 ; Requested unmerge 1727 // ; unpack to GCD type, with extra dead defs 1728 // %8:_(s16), %9, %10, %11 = G_UNMERGE_VALUES %5:_(s64) 1729 // %12:_(s16), %13, dead %14, dead %15 = G_UNMERGE_VALUES %6:_(s64) 1730 // dead %16:_(s16), dead %17, dead %18, dead %18 = G_UNMERGE_VALUES %7:_(s64) 1731 // %1:_(s48) = G_MERGE_VALUES %8:_(s16), %9, %10 ; Remerge to destination 1732 // %2:_(s48) = G_MERGE_VALUES %11:_(s16), %12, %13 ; Remerge to destination 1733 const LLT GCDTy = getGCDType(WideTy, DstTy); 1734 const int NumUnmerge = Unmerge->getNumOperands() - 1; 1735 const int PartsPerRemerge = DstTy.getSizeInBits() / GCDTy.getSizeInBits(); 1736 1737 // Directly unmerge to the destination without going through a GCD type 1738 // if possible 1739 if (PartsPerRemerge == 1) { 1740 const int PartsPerUnmerge = WideTy.getSizeInBits() / DstTy.getSizeInBits(); 1741 1742 for (int I = 0; I != NumUnmerge; ++I) { 1743 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES); 1744 1745 for (int J = 0; J != PartsPerUnmerge; ++J) { 1746 int Idx = I * PartsPerUnmerge + J; 1747 if (Idx < NumDst) 1748 MIB.addDef(MI.getOperand(Idx).getReg()); 1749 else { 1750 // Create dead def for excess components. 1751 MIB.addDef(MRI.createGenericVirtualRegister(DstTy)); 1752 } 1753 } 1754 1755 MIB.addUse(Unmerge.getReg(I)); 1756 } 1757 } else { 1758 SmallVector<Register, 16> Parts; 1759 for (int J = 0; J != NumUnmerge; ++J) 1760 extractGCDType(Parts, GCDTy, Unmerge.getReg(J)); 1761 1762 SmallVector<Register, 8> RemergeParts; 1763 for (int I = 0; I != NumDst; ++I) { 1764 for (int J = 0; J < PartsPerRemerge; ++J) { 1765 const int Idx = I * PartsPerRemerge + J; 1766 RemergeParts.emplace_back(Parts[Idx]); 1767 } 1768 1769 MIRBuilder.buildMerge(MI.getOperand(I).getReg(), RemergeParts); 1770 RemergeParts.clear(); 1771 } 1772 } 1773 1774 MI.eraseFromParent(); 1775 return Legalized; 1776 } 1777 1778 LegalizerHelper::LegalizeResult 1779 LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, 1780 LLT WideTy) { 1781 Register DstReg = MI.getOperand(0).getReg(); 1782 Register SrcReg = MI.getOperand(1).getReg(); 1783 LLT SrcTy = MRI.getType(SrcReg); 1784 1785 LLT DstTy = MRI.getType(DstReg); 1786 unsigned Offset = MI.getOperand(2).getImm(); 1787 1788 if (TypeIdx == 0) { 1789 if (SrcTy.isVector() || DstTy.isVector()) 1790 return UnableToLegalize; 1791 1792 SrcOp Src(SrcReg); 1793 if (SrcTy.isPointer()) { 1794 // Extracts from pointers can be handled only if they are really just 1795 // simple integers. 1796 const DataLayout &DL = MIRBuilder.getDataLayout(); 1797 if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) 1798 return UnableToLegalize; 1799 1800 LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits()); 1801 Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src); 1802 SrcTy = SrcAsIntTy; 1803 } 1804 1805 if (DstTy.isPointer()) 1806 return UnableToLegalize; 1807 1808 if (Offset == 0) { 1809 // Avoid a shift in the degenerate case. 1810 MIRBuilder.buildTrunc(DstReg, 1811 MIRBuilder.buildAnyExtOrTrunc(WideTy, Src)); 1812 MI.eraseFromParent(); 1813 return Legalized; 1814 } 1815 1816 // Do a shift in the source type. 1817 LLT ShiftTy = SrcTy; 1818 if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) { 1819 Src = MIRBuilder.buildAnyExt(WideTy, Src); 1820 ShiftTy = WideTy; 1821 } 1822 1823 auto LShr = MIRBuilder.buildLShr( 1824 ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset)); 1825 MIRBuilder.buildTrunc(DstReg, LShr); 1826 MI.eraseFromParent(); 1827 return Legalized; 1828 } 1829 1830 if (SrcTy.isScalar()) { 1831 Observer.changingInstr(MI); 1832 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1833 Observer.changedInstr(MI); 1834 return Legalized; 1835 } 1836 1837 if (!SrcTy.isVector()) 1838 return UnableToLegalize; 1839 1840 if (DstTy != SrcTy.getElementType()) 1841 return UnableToLegalize; 1842 1843 if (Offset % SrcTy.getScalarSizeInBits() != 0) 1844 return UnableToLegalize; 1845 1846 Observer.changingInstr(MI); 1847 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1848 1849 MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) * 1850 Offset); 1851 widenScalarDst(MI, WideTy.getScalarType(), 0); 1852 Observer.changedInstr(MI); 1853 return Legalized; 1854 } 1855 1856 LegalizerHelper::LegalizeResult 1857 LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, 1858 LLT WideTy) { 1859 if (TypeIdx != 0 || WideTy.isVector()) 1860 return UnableToLegalize; 1861 Observer.changingInstr(MI); 1862 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 1863 widenScalarDst(MI, WideTy); 1864 Observer.changedInstr(MI); 1865 return Legalized; 1866 } 1867 1868 LegalizerHelper::LegalizeResult 1869 LegalizerHelper::widenScalarAddSubOverflow(MachineInstr &MI, unsigned TypeIdx, 1870 LLT WideTy) { 1871 if (TypeIdx == 1) 1872 return UnableToLegalize; // TODO 1873 1874 unsigned Opcode; 1875 unsigned ExtOpcode; 1876 Optional<Register> CarryIn = None; 1877 switch (MI.getOpcode()) { 1878 default: 1879 llvm_unreachable("Unexpected opcode!"); 1880 case TargetOpcode::G_SADDO: 1881 Opcode = TargetOpcode::G_ADD; 1882 ExtOpcode = TargetOpcode::G_SEXT; 1883 break; 1884 case TargetOpcode::G_SSUBO: 1885 Opcode = TargetOpcode::G_SUB; 1886 ExtOpcode = TargetOpcode::G_SEXT; 1887 break; 1888 case TargetOpcode::G_UADDO: 1889 Opcode = TargetOpcode::G_ADD; 1890 ExtOpcode = TargetOpcode::G_ZEXT; 1891 break; 1892 case TargetOpcode::G_USUBO: 1893 Opcode = TargetOpcode::G_SUB; 1894 ExtOpcode = TargetOpcode::G_ZEXT; 1895 break; 1896 case TargetOpcode::G_SADDE: 1897 Opcode = TargetOpcode::G_UADDE; 1898 ExtOpcode = TargetOpcode::G_SEXT; 1899 CarryIn = MI.getOperand(4).getReg(); 1900 break; 1901 case TargetOpcode::G_SSUBE: 1902 Opcode = TargetOpcode::G_USUBE; 1903 ExtOpcode = TargetOpcode::G_SEXT; 1904 CarryIn = MI.getOperand(4).getReg(); 1905 break; 1906 case TargetOpcode::G_UADDE: 1907 Opcode = TargetOpcode::G_UADDE; 1908 ExtOpcode = TargetOpcode::G_ZEXT; 1909 CarryIn = MI.getOperand(4).getReg(); 1910 break; 1911 case TargetOpcode::G_USUBE: 1912 Opcode = TargetOpcode::G_USUBE; 1913 ExtOpcode = TargetOpcode::G_ZEXT; 1914 CarryIn = MI.getOperand(4).getReg(); 1915 break; 1916 } 1917 1918 auto LHSExt = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MI.getOperand(2)}); 1919 auto RHSExt = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MI.getOperand(3)}); 1920 // Do the arithmetic in the larger type. 1921 Register NewOp; 1922 if (CarryIn) { 1923 LLT CarryOutTy = MRI.getType(MI.getOperand(1).getReg()); 1924 NewOp = MIRBuilder 1925 .buildInstr(Opcode, {WideTy, CarryOutTy}, 1926 {LHSExt, RHSExt, *CarryIn}) 1927 .getReg(0); 1928 } else { 1929 NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).getReg(0); 1930 } 1931 LLT OrigTy = MRI.getType(MI.getOperand(0).getReg()); 1932 auto TruncOp = MIRBuilder.buildTrunc(OrigTy, NewOp); 1933 auto ExtOp = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp}); 1934 // There is no overflow if the ExtOp is the same as NewOp. 1935 MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1), NewOp, ExtOp); 1936 // Now trunc the NewOp to the original result. 1937 MIRBuilder.buildTrunc(MI.getOperand(0), NewOp); 1938 MI.eraseFromParent(); 1939 return Legalized; 1940 } 1941 1942 LegalizerHelper::LegalizeResult 1943 LegalizerHelper::widenScalarAddSubShlSat(MachineInstr &MI, unsigned TypeIdx, 1944 LLT WideTy) { 1945 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SADDSAT || 1946 MI.getOpcode() == TargetOpcode::G_SSUBSAT || 1947 MI.getOpcode() == TargetOpcode::G_SSHLSAT; 1948 bool IsShift = MI.getOpcode() == TargetOpcode::G_SSHLSAT || 1949 MI.getOpcode() == TargetOpcode::G_USHLSAT; 1950 // We can convert this to: 1951 // 1. Any extend iN to iM 1952 // 2. SHL by M-N 1953 // 3. [US][ADD|SUB|SHL]SAT 1954 // 4. L/ASHR by M-N 1955 // 1956 // It may be more efficient to lower this to a min and a max operation in 1957 // the higher precision arithmetic if the promoted operation isn't legal, 1958 // but this decision is up to the target's lowering request. 1959 Register DstReg = MI.getOperand(0).getReg(); 1960 1961 unsigned NewBits = WideTy.getScalarSizeInBits(); 1962 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits(); 1963 1964 // Shifts must zero-extend the RHS to preserve the unsigned quantity, and 1965 // must not left shift the RHS to preserve the shift amount. 1966 auto LHS = MIRBuilder.buildAnyExt(WideTy, MI.getOperand(1)); 1967 auto RHS = IsShift ? MIRBuilder.buildZExt(WideTy, MI.getOperand(2)) 1968 : MIRBuilder.buildAnyExt(WideTy, MI.getOperand(2)); 1969 auto ShiftK = MIRBuilder.buildConstant(WideTy, SHLAmount); 1970 auto ShiftL = MIRBuilder.buildShl(WideTy, LHS, ShiftK); 1971 auto ShiftR = IsShift ? RHS : MIRBuilder.buildShl(WideTy, RHS, ShiftK); 1972 1973 auto WideInst = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, 1974 {ShiftL, ShiftR}, MI.getFlags()); 1975 1976 // Use a shift that will preserve the number of sign bits when the trunc is 1977 // folded away. 1978 auto Result = IsSigned ? MIRBuilder.buildAShr(WideTy, WideInst, ShiftK) 1979 : MIRBuilder.buildLShr(WideTy, WideInst, ShiftK); 1980 1981 MIRBuilder.buildTrunc(DstReg, Result); 1982 MI.eraseFromParent(); 1983 return Legalized; 1984 } 1985 1986 LegalizerHelper::LegalizeResult 1987 LegalizerHelper::widenScalarMulo(MachineInstr &MI, unsigned TypeIdx, 1988 LLT WideTy) { 1989 if (TypeIdx == 1) 1990 return UnableToLegalize; 1991 1992 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SMULO; 1993 Register Result = MI.getOperand(0).getReg(); 1994 Register OriginalOverflow = MI.getOperand(1).getReg(); 1995 Register LHS = MI.getOperand(2).getReg(); 1996 Register RHS = MI.getOperand(3).getReg(); 1997 LLT SrcTy = MRI.getType(LHS); 1998 LLT OverflowTy = MRI.getType(OriginalOverflow); 1999 unsigned SrcBitWidth = SrcTy.getScalarSizeInBits(); 2000 2001 // To determine if the result overflowed in the larger type, we extend the 2002 // input to the larger type, do the multiply (checking if it overflows), 2003 // then also check the high bits of the result to see if overflow happened 2004 // there. 2005 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT; 2006 auto LeftOperand = MIRBuilder.buildInstr(ExtOp, {WideTy}, {LHS}); 2007 auto RightOperand = MIRBuilder.buildInstr(ExtOp, {WideTy}, {RHS}); 2008 2009 auto Mulo = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy, OverflowTy}, 2010 {LeftOperand, RightOperand}); 2011 auto Mul = Mulo->getOperand(0); 2012 MIRBuilder.buildTrunc(Result, Mul); 2013 2014 MachineInstrBuilder ExtResult; 2015 // Overflow occurred if it occurred in the larger type, or if the high part 2016 // of the result does not zero/sign-extend the low part. Check this second 2017 // possibility first. 2018 if (IsSigned) { 2019 // For signed, overflow occurred when the high part does not sign-extend 2020 // the low part. 2021 ExtResult = MIRBuilder.buildSExtInReg(WideTy, Mul, SrcBitWidth); 2022 } else { 2023 // Unsigned overflow occurred when the high part does not zero-extend the 2024 // low part. 2025 ExtResult = MIRBuilder.buildZExtInReg(WideTy, Mul, SrcBitWidth); 2026 } 2027 2028 // Multiplication cannot overflow if the WideTy is >= 2 * original width, 2029 // so we don't need to check the overflow result of larger type Mulo. 2030 if (WideTy.getScalarSizeInBits() < 2 * SrcBitWidth) { 2031 auto Overflow = 2032 MIRBuilder.buildICmp(CmpInst::ICMP_NE, OverflowTy, Mul, ExtResult); 2033 // Finally check if the multiplication in the larger type itself overflowed. 2034 MIRBuilder.buildOr(OriginalOverflow, Mulo->getOperand(1), Overflow); 2035 } else { 2036 MIRBuilder.buildICmp(CmpInst::ICMP_NE, OriginalOverflow, Mul, ExtResult); 2037 } 2038 MI.eraseFromParent(); 2039 return Legalized; 2040 } 2041 2042 LegalizerHelper::LegalizeResult 2043 LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 2044 switch (MI.getOpcode()) { 2045 default: 2046 return UnableToLegalize; 2047 case TargetOpcode::G_ATOMICRMW_XCHG: 2048 case TargetOpcode::G_ATOMICRMW_ADD: 2049 case TargetOpcode::G_ATOMICRMW_SUB: 2050 case TargetOpcode::G_ATOMICRMW_AND: 2051 case TargetOpcode::G_ATOMICRMW_OR: 2052 case TargetOpcode::G_ATOMICRMW_XOR: 2053 case TargetOpcode::G_ATOMICRMW_MIN: 2054 case TargetOpcode::G_ATOMICRMW_MAX: 2055 case TargetOpcode::G_ATOMICRMW_UMIN: 2056 case TargetOpcode::G_ATOMICRMW_UMAX: 2057 assert(TypeIdx == 0 && "atomicrmw with second scalar type"); 2058 Observer.changingInstr(MI); 2059 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 2060 widenScalarDst(MI, WideTy, 0); 2061 Observer.changedInstr(MI); 2062 return Legalized; 2063 case TargetOpcode::G_ATOMIC_CMPXCHG: 2064 assert(TypeIdx == 0 && "G_ATOMIC_CMPXCHG with second scalar type"); 2065 Observer.changingInstr(MI); 2066 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 2067 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT); 2068 widenScalarDst(MI, WideTy, 0); 2069 Observer.changedInstr(MI); 2070 return Legalized; 2071 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: 2072 if (TypeIdx == 0) { 2073 Observer.changingInstr(MI); 2074 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT); 2075 widenScalarSrc(MI, WideTy, 4, TargetOpcode::G_ANYEXT); 2076 widenScalarDst(MI, WideTy, 0); 2077 Observer.changedInstr(MI); 2078 return Legalized; 2079 } 2080 assert(TypeIdx == 1 && 2081 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type"); 2082 Observer.changingInstr(MI); 2083 widenScalarDst(MI, WideTy, 1); 2084 Observer.changedInstr(MI); 2085 return Legalized; 2086 case TargetOpcode::G_EXTRACT: 2087 return widenScalarExtract(MI, TypeIdx, WideTy); 2088 case TargetOpcode::G_INSERT: 2089 return widenScalarInsert(MI, TypeIdx, WideTy); 2090 case TargetOpcode::G_MERGE_VALUES: 2091 return widenScalarMergeValues(MI, TypeIdx, WideTy); 2092 case TargetOpcode::G_UNMERGE_VALUES: 2093 return widenScalarUnmergeValues(MI, TypeIdx, WideTy); 2094 case TargetOpcode::G_SADDO: 2095 case TargetOpcode::G_SSUBO: 2096 case TargetOpcode::G_UADDO: 2097 case TargetOpcode::G_USUBO: 2098 case TargetOpcode::G_SADDE: 2099 case TargetOpcode::G_SSUBE: 2100 case TargetOpcode::G_UADDE: 2101 case TargetOpcode::G_USUBE: 2102 return widenScalarAddSubOverflow(MI, TypeIdx, WideTy); 2103 case TargetOpcode::G_UMULO: 2104 case TargetOpcode::G_SMULO: 2105 return widenScalarMulo(MI, TypeIdx, WideTy); 2106 case TargetOpcode::G_SADDSAT: 2107 case TargetOpcode::G_SSUBSAT: 2108 case TargetOpcode::G_SSHLSAT: 2109 case TargetOpcode::G_UADDSAT: 2110 case TargetOpcode::G_USUBSAT: 2111 case TargetOpcode::G_USHLSAT: 2112 return widenScalarAddSubShlSat(MI, TypeIdx, WideTy); 2113 case TargetOpcode::G_CTTZ: 2114 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 2115 case TargetOpcode::G_CTLZ: 2116 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 2117 case TargetOpcode::G_CTPOP: { 2118 if (TypeIdx == 0) { 2119 Observer.changingInstr(MI); 2120 widenScalarDst(MI, WideTy, 0); 2121 Observer.changedInstr(MI); 2122 return Legalized; 2123 } 2124 2125 Register SrcReg = MI.getOperand(1).getReg(); 2126 2127 // First extend the input. 2128 unsigned ExtOpc = MI.getOpcode() == TargetOpcode::G_CTTZ || 2129 MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF 2130 ? TargetOpcode::G_ANYEXT 2131 : TargetOpcode::G_ZEXT; 2132 auto MIBSrc = MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg}); 2133 LLT CurTy = MRI.getType(SrcReg); 2134 unsigned NewOpc = MI.getOpcode(); 2135 if (NewOpc == TargetOpcode::G_CTTZ) { 2136 // The count is the same in the larger type except if the original 2137 // value was zero. This can be handled by setting the bit just off 2138 // the top of the original type. 2139 auto TopBit = 2140 APInt::getOneBitSet(WideTy.getSizeInBits(), CurTy.getSizeInBits()); 2141 MIBSrc = MIRBuilder.buildOr( 2142 WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit)); 2143 // Now we know the operand is non-zero, use the more relaxed opcode. 2144 NewOpc = TargetOpcode::G_CTTZ_ZERO_UNDEF; 2145 } 2146 2147 // Perform the operation at the larger size. 2148 auto MIBNewOp = MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc}); 2149 // This is already the correct result for CTPOP and CTTZs 2150 if (MI.getOpcode() == TargetOpcode::G_CTLZ || 2151 MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF) { 2152 // The correct result is NewOp - (Difference in widety and current ty). 2153 unsigned SizeDiff = WideTy.getSizeInBits() - CurTy.getSizeInBits(); 2154 MIBNewOp = MIRBuilder.buildSub( 2155 WideTy, MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff)); 2156 } 2157 2158 MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp); 2159 MI.eraseFromParent(); 2160 return Legalized; 2161 } 2162 case TargetOpcode::G_BSWAP: { 2163 Observer.changingInstr(MI); 2164 Register DstReg = MI.getOperand(0).getReg(); 2165 2166 Register ShrReg = MRI.createGenericVirtualRegister(WideTy); 2167 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 2168 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy); 2169 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2170 2171 MI.getOperand(0).setReg(DstExt); 2172 2173 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 2174 2175 LLT Ty = MRI.getType(DstReg); 2176 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits(); 2177 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits); 2178 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg); 2179 2180 MIRBuilder.buildTrunc(DstReg, ShrReg); 2181 Observer.changedInstr(MI); 2182 return Legalized; 2183 } 2184 case TargetOpcode::G_BITREVERSE: { 2185 Observer.changingInstr(MI); 2186 2187 Register DstReg = MI.getOperand(0).getReg(); 2188 LLT Ty = MRI.getType(DstReg); 2189 unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits(); 2190 2191 Register DstExt = MRI.createGenericVirtualRegister(WideTy); 2192 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2193 MI.getOperand(0).setReg(DstExt); 2194 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 2195 2196 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, DiffBits); 2197 auto Shift = MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt); 2198 MIRBuilder.buildTrunc(DstReg, Shift); 2199 Observer.changedInstr(MI); 2200 return Legalized; 2201 } 2202 case TargetOpcode::G_FREEZE: 2203 Observer.changingInstr(MI); 2204 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2205 widenScalarDst(MI, WideTy); 2206 Observer.changedInstr(MI); 2207 return Legalized; 2208 2209 case TargetOpcode::G_ABS: 2210 Observer.changingInstr(MI); 2211 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 2212 widenScalarDst(MI, WideTy); 2213 Observer.changedInstr(MI); 2214 return Legalized; 2215 2216 case TargetOpcode::G_ADD: 2217 case TargetOpcode::G_AND: 2218 case TargetOpcode::G_MUL: 2219 case TargetOpcode::G_OR: 2220 case TargetOpcode::G_XOR: 2221 case TargetOpcode::G_SUB: 2222 // Perform operation at larger width (any extension is fines here, high bits 2223 // don't affect the result) and then truncate the result back to the 2224 // original type. 2225 Observer.changingInstr(MI); 2226 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2227 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 2228 widenScalarDst(MI, WideTy); 2229 Observer.changedInstr(MI); 2230 return Legalized; 2231 2232 case TargetOpcode::G_SBFX: 2233 case TargetOpcode::G_UBFX: 2234 Observer.changingInstr(MI); 2235 2236 if (TypeIdx == 0) { 2237 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2238 widenScalarDst(MI, WideTy); 2239 } else { 2240 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 2241 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ZEXT); 2242 } 2243 2244 Observer.changedInstr(MI); 2245 return Legalized; 2246 2247 case TargetOpcode::G_SHL: 2248 Observer.changingInstr(MI); 2249 2250 if (TypeIdx == 0) { 2251 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2252 widenScalarDst(MI, WideTy); 2253 } else { 2254 assert(TypeIdx == 1); 2255 // The "number of bits to shift" operand must preserve its value as an 2256 // unsigned integer: 2257 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 2258 } 2259 2260 Observer.changedInstr(MI); 2261 return Legalized; 2262 2263 case TargetOpcode::G_SDIV: 2264 case TargetOpcode::G_SREM: 2265 case TargetOpcode::G_SMIN: 2266 case TargetOpcode::G_SMAX: 2267 Observer.changingInstr(MI); 2268 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 2269 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 2270 widenScalarDst(MI, WideTy); 2271 Observer.changedInstr(MI); 2272 return Legalized; 2273 2274 case TargetOpcode::G_SDIVREM: 2275 Observer.changingInstr(MI); 2276 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 2277 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_SEXT); 2278 widenScalarDst(MI, WideTy); 2279 widenScalarDst(MI, WideTy, 1); 2280 Observer.changedInstr(MI); 2281 return Legalized; 2282 2283 case TargetOpcode::G_ASHR: 2284 case TargetOpcode::G_LSHR: 2285 Observer.changingInstr(MI); 2286 2287 if (TypeIdx == 0) { 2288 unsigned CvtOp = MI.getOpcode() == TargetOpcode::G_ASHR ? 2289 TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT; 2290 2291 widenScalarSrc(MI, WideTy, 1, CvtOp); 2292 widenScalarDst(MI, WideTy); 2293 } else { 2294 assert(TypeIdx == 1); 2295 // The "number of bits to shift" operand must preserve its value as an 2296 // unsigned integer: 2297 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 2298 } 2299 2300 Observer.changedInstr(MI); 2301 return Legalized; 2302 case TargetOpcode::G_UDIV: 2303 case TargetOpcode::G_UREM: 2304 case TargetOpcode::G_UMIN: 2305 case TargetOpcode::G_UMAX: 2306 Observer.changingInstr(MI); 2307 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 2308 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 2309 widenScalarDst(MI, WideTy); 2310 Observer.changedInstr(MI); 2311 return Legalized; 2312 2313 case TargetOpcode::G_UDIVREM: 2314 Observer.changingInstr(MI); 2315 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 2316 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ZEXT); 2317 widenScalarDst(MI, WideTy); 2318 widenScalarDst(MI, WideTy, 1); 2319 Observer.changedInstr(MI); 2320 return Legalized; 2321 2322 case TargetOpcode::G_SELECT: 2323 Observer.changingInstr(MI); 2324 if (TypeIdx == 0) { 2325 // Perform operation at larger width (any extension is fine here, high 2326 // bits don't affect the result) and then truncate the result back to the 2327 // original type. 2328 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 2329 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT); 2330 widenScalarDst(MI, WideTy); 2331 } else { 2332 bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector(); 2333 // Explicit extension is required here since high bits affect the result. 2334 widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false)); 2335 } 2336 Observer.changedInstr(MI); 2337 return Legalized; 2338 2339 case TargetOpcode::G_FPTOSI: 2340 case TargetOpcode::G_FPTOUI: 2341 Observer.changingInstr(MI); 2342 2343 if (TypeIdx == 0) 2344 widenScalarDst(MI, WideTy); 2345 else 2346 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_FPEXT); 2347 2348 Observer.changedInstr(MI); 2349 return Legalized; 2350 case TargetOpcode::G_SITOFP: 2351 Observer.changingInstr(MI); 2352 2353 if (TypeIdx == 0) 2354 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 2355 else 2356 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); 2357 2358 Observer.changedInstr(MI); 2359 return Legalized; 2360 case TargetOpcode::G_UITOFP: 2361 Observer.changingInstr(MI); 2362 2363 if (TypeIdx == 0) 2364 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 2365 else 2366 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 2367 2368 Observer.changedInstr(MI); 2369 return Legalized; 2370 case TargetOpcode::G_LOAD: 2371 case TargetOpcode::G_SEXTLOAD: 2372 case TargetOpcode::G_ZEXTLOAD: 2373 Observer.changingInstr(MI); 2374 widenScalarDst(MI, WideTy); 2375 Observer.changedInstr(MI); 2376 return Legalized; 2377 2378 case TargetOpcode::G_STORE: { 2379 if (TypeIdx != 0) 2380 return UnableToLegalize; 2381 2382 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 2383 if (!Ty.isScalar()) 2384 return UnableToLegalize; 2385 2386 Observer.changingInstr(MI); 2387 2388 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ? 2389 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT; 2390 widenScalarSrc(MI, WideTy, 0, ExtType); 2391 2392 Observer.changedInstr(MI); 2393 return Legalized; 2394 } 2395 case TargetOpcode::G_CONSTANT: { 2396 MachineOperand &SrcMO = MI.getOperand(1); 2397 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 2398 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant( 2399 MRI.getType(MI.getOperand(0).getReg())); 2400 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT || 2401 ExtOpc == TargetOpcode::G_ANYEXT) && 2402 "Illegal Extend"); 2403 const APInt &SrcVal = SrcMO.getCImm()->getValue(); 2404 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT) 2405 ? SrcVal.sext(WideTy.getSizeInBits()) 2406 : SrcVal.zext(WideTy.getSizeInBits()); 2407 Observer.changingInstr(MI); 2408 SrcMO.setCImm(ConstantInt::get(Ctx, Val)); 2409 2410 widenScalarDst(MI, WideTy); 2411 Observer.changedInstr(MI); 2412 return Legalized; 2413 } 2414 case TargetOpcode::G_FCONSTANT: { 2415 MachineOperand &SrcMO = MI.getOperand(1); 2416 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); 2417 APFloat Val = SrcMO.getFPImm()->getValueAPF(); 2418 bool LosesInfo; 2419 switch (WideTy.getSizeInBits()) { 2420 case 32: 2421 Val.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, 2422 &LosesInfo); 2423 break; 2424 case 64: 2425 Val.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, 2426 &LosesInfo); 2427 break; 2428 default: 2429 return UnableToLegalize; 2430 } 2431 2432 assert(!LosesInfo && "extend should always be lossless"); 2433 2434 Observer.changingInstr(MI); 2435 SrcMO.setFPImm(ConstantFP::get(Ctx, Val)); 2436 2437 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 2438 Observer.changedInstr(MI); 2439 return Legalized; 2440 } 2441 case TargetOpcode::G_IMPLICIT_DEF: { 2442 Observer.changingInstr(MI); 2443 widenScalarDst(MI, WideTy); 2444 Observer.changedInstr(MI); 2445 return Legalized; 2446 } 2447 case TargetOpcode::G_BRCOND: 2448 Observer.changingInstr(MI); 2449 widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false)); 2450 Observer.changedInstr(MI); 2451 return Legalized; 2452 2453 case TargetOpcode::G_FCMP: 2454 Observer.changingInstr(MI); 2455 if (TypeIdx == 0) 2456 widenScalarDst(MI, WideTy); 2457 else { 2458 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_FPEXT); 2459 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_FPEXT); 2460 } 2461 Observer.changedInstr(MI); 2462 return Legalized; 2463 2464 case TargetOpcode::G_ICMP: 2465 Observer.changingInstr(MI); 2466 if (TypeIdx == 0) 2467 widenScalarDst(MI, WideTy); 2468 else { 2469 unsigned ExtOpcode = CmpInst::isSigned(static_cast<CmpInst::Predicate>( 2470 MI.getOperand(1).getPredicate())) 2471 ? TargetOpcode::G_SEXT 2472 : TargetOpcode::G_ZEXT; 2473 widenScalarSrc(MI, WideTy, 2, ExtOpcode); 2474 widenScalarSrc(MI, WideTy, 3, ExtOpcode); 2475 } 2476 Observer.changedInstr(MI); 2477 return Legalized; 2478 2479 case TargetOpcode::G_PTR_ADD: 2480 assert(TypeIdx == 1 && "unable to legalize pointer of G_PTR_ADD"); 2481 Observer.changingInstr(MI); 2482 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 2483 Observer.changedInstr(MI); 2484 return Legalized; 2485 2486 case TargetOpcode::G_PHI: { 2487 assert(TypeIdx == 0 && "Expecting only Idx 0"); 2488 2489 Observer.changingInstr(MI); 2490 for (unsigned I = 1; I < MI.getNumOperands(); I += 2) { 2491 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB(); 2492 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 2493 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT); 2494 } 2495 2496 MachineBasicBlock &MBB = *MI.getParent(); 2497 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI()); 2498 widenScalarDst(MI, WideTy); 2499 Observer.changedInstr(MI); 2500 return Legalized; 2501 } 2502 case TargetOpcode::G_EXTRACT_VECTOR_ELT: { 2503 if (TypeIdx == 0) { 2504 Register VecReg = MI.getOperand(1).getReg(); 2505 LLT VecTy = MRI.getType(VecReg); 2506 Observer.changingInstr(MI); 2507 2508 widenScalarSrc( 2509 MI, LLT::vector(VecTy.getElementCount(), WideTy.getSizeInBits()), 1, 2510 TargetOpcode::G_ANYEXT); 2511 2512 widenScalarDst(MI, WideTy, 0); 2513 Observer.changedInstr(MI); 2514 return Legalized; 2515 } 2516 2517 if (TypeIdx != 2) 2518 return UnableToLegalize; 2519 Observer.changingInstr(MI); 2520 // TODO: Probably should be zext 2521 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); 2522 Observer.changedInstr(MI); 2523 return Legalized; 2524 } 2525 case TargetOpcode::G_INSERT_VECTOR_ELT: { 2526 if (TypeIdx == 1) { 2527 Observer.changingInstr(MI); 2528 2529 Register VecReg = MI.getOperand(1).getReg(); 2530 LLT VecTy = MRI.getType(VecReg); 2531 LLT WideVecTy = LLT::vector(VecTy.getElementCount(), WideTy); 2532 2533 widenScalarSrc(MI, WideVecTy, 1, TargetOpcode::G_ANYEXT); 2534 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT); 2535 widenScalarDst(MI, WideVecTy, 0); 2536 Observer.changedInstr(MI); 2537 return Legalized; 2538 } 2539 2540 if (TypeIdx == 2) { 2541 Observer.changingInstr(MI); 2542 // TODO: Probably should be zext 2543 widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_SEXT); 2544 Observer.changedInstr(MI); 2545 return Legalized; 2546 } 2547 2548 return UnableToLegalize; 2549 } 2550 case TargetOpcode::G_FADD: 2551 case TargetOpcode::G_FMUL: 2552 case TargetOpcode::G_FSUB: 2553 case TargetOpcode::G_FMA: 2554 case TargetOpcode::G_FMAD: 2555 case TargetOpcode::G_FNEG: 2556 case TargetOpcode::G_FABS: 2557 case TargetOpcode::G_FCANONICALIZE: 2558 case TargetOpcode::G_FMINNUM: 2559 case TargetOpcode::G_FMAXNUM: 2560 case TargetOpcode::G_FMINNUM_IEEE: 2561 case TargetOpcode::G_FMAXNUM_IEEE: 2562 case TargetOpcode::G_FMINIMUM: 2563 case TargetOpcode::G_FMAXIMUM: 2564 case TargetOpcode::G_FDIV: 2565 case TargetOpcode::G_FREM: 2566 case TargetOpcode::G_FCEIL: 2567 case TargetOpcode::G_FFLOOR: 2568 case TargetOpcode::G_FCOS: 2569 case TargetOpcode::G_FSIN: 2570 case TargetOpcode::G_FLOG10: 2571 case TargetOpcode::G_FLOG: 2572 case TargetOpcode::G_FLOG2: 2573 case TargetOpcode::G_FRINT: 2574 case TargetOpcode::G_FNEARBYINT: 2575 case TargetOpcode::G_FSQRT: 2576 case TargetOpcode::G_FEXP: 2577 case TargetOpcode::G_FEXP2: 2578 case TargetOpcode::G_FPOW: 2579 case TargetOpcode::G_INTRINSIC_TRUNC: 2580 case TargetOpcode::G_INTRINSIC_ROUND: 2581 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: 2582 assert(TypeIdx == 0); 2583 Observer.changingInstr(MI); 2584 2585 for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I) 2586 widenScalarSrc(MI, WideTy, I, TargetOpcode::G_FPEXT); 2587 2588 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 2589 Observer.changedInstr(MI); 2590 return Legalized; 2591 case TargetOpcode::G_FPOWI: { 2592 if (TypeIdx != 0) 2593 return UnableToLegalize; 2594 Observer.changingInstr(MI); 2595 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_FPEXT); 2596 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_FPTRUNC); 2597 Observer.changedInstr(MI); 2598 return Legalized; 2599 } 2600 case TargetOpcode::G_INTTOPTR: 2601 if (TypeIdx != 1) 2602 return UnableToLegalize; 2603 2604 Observer.changingInstr(MI); 2605 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); 2606 Observer.changedInstr(MI); 2607 return Legalized; 2608 case TargetOpcode::G_PTRTOINT: 2609 if (TypeIdx != 0) 2610 return UnableToLegalize; 2611 2612 Observer.changingInstr(MI); 2613 widenScalarDst(MI, WideTy, 0); 2614 Observer.changedInstr(MI); 2615 return Legalized; 2616 case TargetOpcode::G_BUILD_VECTOR: { 2617 Observer.changingInstr(MI); 2618 2619 const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType(); 2620 for (int I = 1, E = MI.getNumOperands(); I != E; ++I) 2621 widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT); 2622 2623 // Avoid changing the result vector type if the source element type was 2624 // requested. 2625 if (TypeIdx == 1) { 2626 MI.setDesc(MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC)); 2627 } else { 2628 widenScalarDst(MI, WideTy, 0); 2629 } 2630 2631 Observer.changedInstr(MI); 2632 return Legalized; 2633 } 2634 case TargetOpcode::G_SEXT_INREG: 2635 if (TypeIdx != 0) 2636 return UnableToLegalize; 2637 2638 Observer.changingInstr(MI); 2639 widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); 2640 widenScalarDst(MI, WideTy, 0, TargetOpcode::G_TRUNC); 2641 Observer.changedInstr(MI); 2642 return Legalized; 2643 case TargetOpcode::G_PTRMASK: { 2644 if (TypeIdx != 1) 2645 return UnableToLegalize; 2646 Observer.changingInstr(MI); 2647 widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); 2648 Observer.changedInstr(MI); 2649 return Legalized; 2650 } 2651 } 2652 } 2653 2654 static void getUnmergePieces(SmallVectorImpl<Register> &Pieces, 2655 MachineIRBuilder &B, Register Src, LLT Ty) { 2656 auto Unmerge = B.buildUnmerge(Ty, Src); 2657 for (int I = 0, E = Unmerge->getNumOperands() - 1; I != E; ++I) 2658 Pieces.push_back(Unmerge.getReg(I)); 2659 } 2660 2661 LegalizerHelper::LegalizeResult 2662 LegalizerHelper::lowerBitcast(MachineInstr &MI) { 2663 Register Dst = MI.getOperand(0).getReg(); 2664 Register Src = MI.getOperand(1).getReg(); 2665 LLT DstTy = MRI.getType(Dst); 2666 LLT SrcTy = MRI.getType(Src); 2667 2668 if (SrcTy.isVector()) { 2669 LLT SrcEltTy = SrcTy.getElementType(); 2670 SmallVector<Register, 8> SrcRegs; 2671 2672 if (DstTy.isVector()) { 2673 int NumDstElt = DstTy.getNumElements(); 2674 int NumSrcElt = SrcTy.getNumElements(); 2675 2676 LLT DstEltTy = DstTy.getElementType(); 2677 LLT DstCastTy = DstEltTy; // Intermediate bitcast result type 2678 LLT SrcPartTy = SrcEltTy; // Original unmerge result type. 2679 2680 // If there's an element size mismatch, insert intermediate casts to match 2681 // the result element type. 2682 if (NumSrcElt < NumDstElt) { // Source element type is larger. 2683 // %1:_(<4 x s8>) = G_BITCAST %0:_(<2 x s16>) 2684 // 2685 // => 2686 // 2687 // %2:_(s16), %3:_(s16) = G_UNMERGE_VALUES %0 2688 // %3:_(<2 x s8>) = G_BITCAST %2 2689 // %4:_(<2 x s8>) = G_BITCAST %3 2690 // %1:_(<4 x s16>) = G_CONCAT_VECTORS %3, %4 2691 DstCastTy = LLT::fixed_vector(NumDstElt / NumSrcElt, DstEltTy); 2692 SrcPartTy = SrcEltTy; 2693 } else if (NumSrcElt > NumDstElt) { // Source element type is smaller. 2694 // 2695 // %1:_(<2 x s16>) = G_BITCAST %0:_(<4 x s8>) 2696 // 2697 // => 2698 // 2699 // %2:_(<2 x s8>), %3:_(<2 x s8>) = G_UNMERGE_VALUES %0 2700 // %3:_(s16) = G_BITCAST %2 2701 // %4:_(s16) = G_BITCAST %3 2702 // %1:_(<2 x s16>) = G_BUILD_VECTOR %3, %4 2703 SrcPartTy = LLT::fixed_vector(NumSrcElt / NumDstElt, SrcEltTy); 2704 DstCastTy = DstEltTy; 2705 } 2706 2707 getUnmergePieces(SrcRegs, MIRBuilder, Src, SrcPartTy); 2708 for (Register &SrcReg : SrcRegs) 2709 SrcReg = MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0); 2710 } else 2711 getUnmergePieces(SrcRegs, MIRBuilder, Src, SrcEltTy); 2712 2713 MIRBuilder.buildMerge(Dst, SrcRegs); 2714 MI.eraseFromParent(); 2715 return Legalized; 2716 } 2717 2718 if (DstTy.isVector()) { 2719 SmallVector<Register, 8> SrcRegs; 2720 getUnmergePieces(SrcRegs, MIRBuilder, Src, DstTy.getElementType()); 2721 MIRBuilder.buildMerge(Dst, SrcRegs); 2722 MI.eraseFromParent(); 2723 return Legalized; 2724 } 2725 2726 return UnableToLegalize; 2727 } 2728 2729 /// Figure out the bit offset into a register when coercing a vector index for 2730 /// the wide element type. This is only for the case when promoting vector to 2731 /// one with larger elements. 2732 // 2733 /// 2734 /// %offset_idx = G_AND %idx, ~(-1 << Log2(DstEltSize / SrcEltSize)) 2735 /// %offset_bits = G_SHL %offset_idx, Log2(SrcEltSize) 2736 static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, 2737 Register Idx, 2738 unsigned NewEltSize, 2739 unsigned OldEltSize) { 2740 const unsigned Log2EltRatio = Log2_32(NewEltSize / OldEltSize); 2741 LLT IdxTy = B.getMRI()->getType(Idx); 2742 2743 // Now figure out the amount we need to shift to get the target bits. 2744 auto OffsetMask = B.buildConstant( 2745 IdxTy, ~(APInt::getAllOnes(IdxTy.getSizeInBits()) << Log2EltRatio)); 2746 auto OffsetIdx = B.buildAnd(IdxTy, Idx, OffsetMask); 2747 return B.buildShl(IdxTy, OffsetIdx, 2748 B.buildConstant(IdxTy, Log2_32(OldEltSize))).getReg(0); 2749 } 2750 2751 /// Perform a G_EXTRACT_VECTOR_ELT in a different sized vector element. If this 2752 /// is casting to a vector with a smaller element size, perform multiple element 2753 /// extracts and merge the results. If this is coercing to a vector with larger 2754 /// elements, index the bitcasted vector and extract the target element with bit 2755 /// operations. This is intended to force the indexing in the native register 2756 /// size for architectures that can dynamically index the register file. 2757 LegalizerHelper::LegalizeResult 2758 LegalizerHelper::bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, 2759 LLT CastTy) { 2760 if (TypeIdx != 1) 2761 return UnableToLegalize; 2762 2763 Register Dst = MI.getOperand(0).getReg(); 2764 Register SrcVec = MI.getOperand(1).getReg(); 2765 Register Idx = MI.getOperand(2).getReg(); 2766 LLT SrcVecTy = MRI.getType(SrcVec); 2767 LLT IdxTy = MRI.getType(Idx); 2768 2769 LLT SrcEltTy = SrcVecTy.getElementType(); 2770 unsigned NewNumElts = CastTy.isVector() ? CastTy.getNumElements() : 1; 2771 unsigned OldNumElts = SrcVecTy.getNumElements(); 2772 2773 LLT NewEltTy = CastTy.isVector() ? CastTy.getElementType() : CastTy; 2774 Register CastVec = MIRBuilder.buildBitcast(CastTy, SrcVec).getReg(0); 2775 2776 const unsigned NewEltSize = NewEltTy.getSizeInBits(); 2777 const unsigned OldEltSize = SrcEltTy.getSizeInBits(); 2778 if (NewNumElts > OldNumElts) { 2779 // Decreasing the vector element size 2780 // 2781 // e.g. i64 = extract_vector_elt x:v2i64, y:i32 2782 // => 2783 // v4i32:castx = bitcast x:v2i64 2784 // 2785 // i64 = bitcast 2786 // (v2i32 build_vector (i32 (extract_vector_elt castx, (2 * y))), 2787 // (i32 (extract_vector_elt castx, (2 * y + 1))) 2788 // 2789 if (NewNumElts % OldNumElts != 0) 2790 return UnableToLegalize; 2791 2792 // Type of the intermediate result vector. 2793 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts; 2794 LLT MidTy = 2795 LLT::scalarOrVector(ElementCount::getFixed(NewEltsPerOldElt), NewEltTy); 2796 2797 auto NewEltsPerOldEltK = MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt); 2798 2799 SmallVector<Register, 8> NewOps(NewEltsPerOldElt); 2800 auto NewBaseIdx = MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK); 2801 2802 for (unsigned I = 0; I < NewEltsPerOldElt; ++I) { 2803 auto IdxOffset = MIRBuilder.buildConstant(IdxTy, I); 2804 auto TmpIdx = MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset); 2805 auto Elt = MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx); 2806 NewOps[I] = Elt.getReg(0); 2807 } 2808 2809 auto NewVec = MIRBuilder.buildBuildVector(MidTy, NewOps); 2810 MIRBuilder.buildBitcast(Dst, NewVec); 2811 MI.eraseFromParent(); 2812 return Legalized; 2813 } 2814 2815 if (NewNumElts < OldNumElts) { 2816 if (NewEltSize % OldEltSize != 0) 2817 return UnableToLegalize; 2818 2819 // This only depends on powers of 2 because we use bit tricks to figure out 2820 // the bit offset we need to shift to get the target element. A general 2821 // expansion could emit division/multiply. 2822 if (!isPowerOf2_32(NewEltSize / OldEltSize)) 2823 return UnableToLegalize; 2824 2825 // Increasing the vector element size. 2826 // %elt:_(small_elt) = G_EXTRACT_VECTOR_ELT %vec:_(<N x small_elt>), %idx 2827 // 2828 // => 2829 // 2830 // %cast = G_BITCAST %vec 2831 // %scaled_idx = G_LSHR %idx, Log2(DstEltSize / SrcEltSize) 2832 // %wide_elt = G_EXTRACT_VECTOR_ELT %cast, %scaled_idx 2833 // %offset_idx = G_AND %idx, ~(-1 << Log2(DstEltSize / SrcEltSize)) 2834 // %offset_bits = G_SHL %offset_idx, Log2(SrcEltSize) 2835 // %elt_bits = G_LSHR %wide_elt, %offset_bits 2836 // %elt = G_TRUNC %elt_bits 2837 2838 const unsigned Log2EltRatio = Log2_32(NewEltSize / OldEltSize); 2839 auto Log2Ratio = MIRBuilder.buildConstant(IdxTy, Log2EltRatio); 2840 2841 // Divide to get the index in the wider element type. 2842 auto ScaledIdx = MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio); 2843 2844 Register WideElt = CastVec; 2845 if (CastTy.isVector()) { 2846 WideElt = MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, 2847 ScaledIdx).getReg(0); 2848 } 2849 2850 // Compute the bit offset into the register of the target element. 2851 Register OffsetBits = getBitcastWiderVectorElementOffset( 2852 MIRBuilder, Idx, NewEltSize, OldEltSize); 2853 2854 // Shift the wide element to get the target element. 2855 auto ExtractedBits = MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits); 2856 MIRBuilder.buildTrunc(Dst, ExtractedBits); 2857 MI.eraseFromParent(); 2858 return Legalized; 2859 } 2860 2861 return UnableToLegalize; 2862 } 2863 2864 /// Emit code to insert \p InsertReg into \p TargetRet at \p OffsetBits in \p 2865 /// TargetReg, while preserving other bits in \p TargetReg. 2866 /// 2867 /// (InsertReg << Offset) | (TargetReg & ~(-1 >> InsertReg.size()) << Offset) 2868 static Register buildBitFieldInsert(MachineIRBuilder &B, 2869 Register TargetReg, Register InsertReg, 2870 Register OffsetBits) { 2871 LLT TargetTy = B.getMRI()->getType(TargetReg); 2872 LLT InsertTy = B.getMRI()->getType(InsertReg); 2873 auto ZextVal = B.buildZExt(TargetTy, InsertReg); 2874 auto ShiftedInsertVal = B.buildShl(TargetTy, ZextVal, OffsetBits); 2875 2876 // Produce a bitmask of the value to insert 2877 auto EltMask = B.buildConstant( 2878 TargetTy, APInt::getLowBitsSet(TargetTy.getSizeInBits(), 2879 InsertTy.getSizeInBits())); 2880 // Shift it into position 2881 auto ShiftedMask = B.buildShl(TargetTy, EltMask, OffsetBits); 2882 auto InvShiftedMask = B.buildNot(TargetTy, ShiftedMask); 2883 2884 // Clear out the bits in the wide element 2885 auto MaskedOldElt = B.buildAnd(TargetTy, TargetReg, InvShiftedMask); 2886 2887 // The value to insert has all zeros already, so stick it into the masked 2888 // wide element. 2889 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0); 2890 } 2891 2892 /// Perform a G_INSERT_VECTOR_ELT in a different sized vector element. If this 2893 /// is increasing the element size, perform the indexing in the target element 2894 /// type, and use bit operations to insert at the element position. This is 2895 /// intended for architectures that can dynamically index the register file and 2896 /// want to force indexing in the native register size. 2897 LegalizerHelper::LegalizeResult 2898 LegalizerHelper::bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, 2899 LLT CastTy) { 2900 if (TypeIdx != 0) 2901 return UnableToLegalize; 2902 2903 Register Dst = MI.getOperand(0).getReg(); 2904 Register SrcVec = MI.getOperand(1).getReg(); 2905 Register Val = MI.getOperand(2).getReg(); 2906 Register Idx = MI.getOperand(3).getReg(); 2907 2908 LLT VecTy = MRI.getType(Dst); 2909 LLT IdxTy = MRI.getType(Idx); 2910 2911 LLT VecEltTy = VecTy.getElementType(); 2912 LLT NewEltTy = CastTy.isVector() ? CastTy.getElementType() : CastTy; 2913 const unsigned NewEltSize = NewEltTy.getSizeInBits(); 2914 const unsigned OldEltSize = VecEltTy.getSizeInBits(); 2915 2916 unsigned NewNumElts = CastTy.isVector() ? CastTy.getNumElements() : 1; 2917 unsigned OldNumElts = VecTy.getNumElements(); 2918 2919 Register CastVec = MIRBuilder.buildBitcast(CastTy, SrcVec).getReg(0); 2920 if (NewNumElts < OldNumElts) { 2921 if (NewEltSize % OldEltSize != 0) 2922 return UnableToLegalize; 2923 2924 // This only depends on powers of 2 because we use bit tricks to figure out 2925 // the bit offset we need to shift to get the target element. A general 2926 // expansion could emit division/multiply. 2927 if (!isPowerOf2_32(NewEltSize / OldEltSize)) 2928 return UnableToLegalize; 2929 2930 const unsigned Log2EltRatio = Log2_32(NewEltSize / OldEltSize); 2931 auto Log2Ratio = MIRBuilder.buildConstant(IdxTy, Log2EltRatio); 2932 2933 // Divide to get the index in the wider element type. 2934 auto ScaledIdx = MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio); 2935 2936 Register ExtractedElt = CastVec; 2937 if (CastTy.isVector()) { 2938 ExtractedElt = MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, 2939 ScaledIdx).getReg(0); 2940 } 2941 2942 // Compute the bit offset into the register of the target element. 2943 Register OffsetBits = getBitcastWiderVectorElementOffset( 2944 MIRBuilder, Idx, NewEltSize, OldEltSize); 2945 2946 Register InsertedElt = buildBitFieldInsert(MIRBuilder, ExtractedElt, 2947 Val, OffsetBits); 2948 if (CastTy.isVector()) { 2949 InsertedElt = MIRBuilder.buildInsertVectorElement( 2950 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0); 2951 } 2952 2953 MIRBuilder.buildBitcast(Dst, InsertedElt); 2954 MI.eraseFromParent(); 2955 return Legalized; 2956 } 2957 2958 return UnableToLegalize; 2959 } 2960 2961 LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) { 2962 // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT 2963 Register DstReg = LoadMI.getDstReg(); 2964 Register PtrReg = LoadMI.getPointerReg(); 2965 LLT DstTy = MRI.getType(DstReg); 2966 MachineMemOperand &MMO = LoadMI.getMMO(); 2967 LLT MemTy = MMO.getMemoryType(); 2968 MachineFunction &MF = MIRBuilder.getMF(); 2969 2970 unsigned MemSizeInBits = MemTy.getSizeInBits(); 2971 unsigned MemStoreSizeInBits = 8 * MemTy.getSizeInBytes(); 2972 2973 if (MemSizeInBits != MemStoreSizeInBits) { 2974 if (MemTy.isVector()) 2975 return UnableToLegalize; 2976 2977 // Promote to a byte-sized load if not loading an integral number of 2978 // bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24. 2979 LLT WideMemTy = LLT::scalar(MemStoreSizeInBits); 2980 MachineMemOperand *NewMMO = 2981 MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideMemTy); 2982 2983 Register LoadReg = DstReg; 2984 LLT LoadTy = DstTy; 2985 2986 // If this wasn't already an extending load, we need to widen the result 2987 // register to avoid creating a load with a narrower result than the source. 2988 if (MemStoreSizeInBits > DstTy.getSizeInBits()) { 2989 LoadTy = WideMemTy; 2990 LoadReg = MRI.createGenericVirtualRegister(WideMemTy); 2991 } 2992 2993 if (isa<GSExtLoad>(LoadMI)) { 2994 auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO); 2995 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits); 2996 } else if (isa<GZExtLoad>(LoadMI) || WideMemTy == DstTy) { 2997 auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO); 2998 // The extra bits are guaranteed to be zero, since we stored them that 2999 // way. A zext load from Wide thus automatically gives zext from MemVT. 3000 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits); 3001 } else { 3002 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO); 3003 } 3004 3005 if (DstTy != LoadTy) 3006 MIRBuilder.buildTrunc(DstReg, LoadReg); 3007 3008 LoadMI.eraseFromParent(); 3009 return Legalized; 3010 } 3011 3012 // Big endian lowering not implemented. 3013 if (MIRBuilder.getDataLayout().isBigEndian()) 3014 return UnableToLegalize; 3015 3016 // This load needs splitting into power of 2 sized loads. 3017 // 3018 // Our strategy here is to generate anyextending loads for the smaller 3019 // types up to next power-2 result type, and then combine the two larger 3020 // result values together, before truncating back down to the non-pow-2 3021 // type. 3022 // E.g. v1 = i24 load => 3023 // v2 = i32 zextload (2 byte) 3024 // v3 = i32 load (1 byte) 3025 // v4 = i32 shl v3, 16 3026 // v5 = i32 or v4, v2 3027 // v1 = i24 trunc v5 3028 // By doing this we generate the correct truncate which should get 3029 // combined away as an artifact with a matching extend. 3030 3031 uint64_t LargeSplitSize, SmallSplitSize; 3032 3033 if (!isPowerOf2_32(MemSizeInBits)) { 3034 // This load needs splitting into power of 2 sized loads. 3035 LargeSplitSize = PowerOf2Floor(MemSizeInBits); 3036 SmallSplitSize = MemSizeInBits - LargeSplitSize; 3037 } else { 3038 // This is already a power of 2, but we still need to split this in half. 3039 // 3040 // Assume we're being asked to decompose an unaligned load. 3041 // TODO: If this requires multiple splits, handle them all at once. 3042 auto &Ctx = MF.getFunction().getContext(); 3043 if (TLI.allowsMemoryAccess(Ctx, MIRBuilder.getDataLayout(), MemTy, MMO)) 3044 return UnableToLegalize; 3045 3046 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2; 3047 } 3048 3049 if (MemTy.isVector()) { 3050 // TODO: Handle vector extloads 3051 if (MemTy != DstTy) 3052 return UnableToLegalize; 3053 3054 // TODO: We can do better than scalarizing the vector and at least split it 3055 // in half. 3056 return reduceLoadStoreWidth(LoadMI, 0, DstTy.getElementType()); 3057 } 3058 3059 MachineMemOperand *LargeMMO = 3060 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8); 3061 MachineMemOperand *SmallMMO = 3062 MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8); 3063 3064 LLT PtrTy = MRI.getType(PtrReg); 3065 unsigned AnyExtSize = PowerOf2Ceil(DstTy.getSizeInBits()); 3066 LLT AnyExtTy = LLT::scalar(AnyExtSize); 3067 auto LargeLoad = MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy, 3068 PtrReg, *LargeMMO); 3069 3070 auto OffsetCst = MIRBuilder.buildConstant(LLT::scalar(PtrTy.getSizeInBits()), 3071 LargeSplitSize / 8); 3072 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy); 3073 auto SmallPtr = MIRBuilder.buildPtrAdd(PtrAddReg, PtrReg, OffsetCst); 3074 auto SmallLoad = MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), AnyExtTy, 3075 SmallPtr, *SmallMMO); 3076 3077 auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize); 3078 auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt); 3079 3080 if (AnyExtTy == DstTy) 3081 MIRBuilder.buildOr(DstReg, Shift, LargeLoad); 3082 else if (AnyExtTy.getSizeInBits() != DstTy.getSizeInBits()) { 3083 auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad); 3084 MIRBuilder.buildTrunc(DstReg, {Or}); 3085 } else { 3086 assert(DstTy.isPointer() && "expected pointer"); 3087 auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad); 3088 3089 // FIXME: We currently consider this to be illegal for non-integral address 3090 // spaces, but we need still need a way to reinterpret the bits. 3091 MIRBuilder.buildIntToPtr(DstReg, Or); 3092 } 3093 3094 LoadMI.eraseFromParent(); 3095 return Legalized; 3096 } 3097 3098 LegalizerHelper::LegalizeResult LegalizerHelper::lowerStore(GStore &StoreMI) { 3099 // Lower a non-power of 2 store into multiple pow-2 stores. 3100 // E.g. split an i24 store into an i16 store + i8 store. 3101 // We do this by first extending the stored value to the next largest power 3102 // of 2 type, and then using truncating stores to store the components. 3103 // By doing this, likewise with G_LOAD, generate an extend that can be 3104 // artifact-combined away instead of leaving behind extracts. 3105 Register SrcReg = StoreMI.getValueReg(); 3106 Register PtrReg = StoreMI.getPointerReg(); 3107 LLT SrcTy = MRI.getType(SrcReg); 3108 MachineFunction &MF = MIRBuilder.getMF(); 3109 MachineMemOperand &MMO = **StoreMI.memoperands_begin(); 3110 LLT MemTy = MMO.getMemoryType(); 3111 3112 unsigned StoreWidth = MemTy.getSizeInBits(); 3113 unsigned StoreSizeInBits = 8 * MemTy.getSizeInBytes(); 3114 3115 if (StoreWidth != StoreSizeInBits) { 3116 if (SrcTy.isVector()) 3117 return UnableToLegalize; 3118 3119 // Promote to a byte-sized store with upper bits zero if not 3120 // storing an integral number of bytes. For example, promote 3121 // TRUNCSTORE:i1 X -> TRUNCSTORE:i8 (and X, 1) 3122 LLT WideTy = LLT::scalar(StoreSizeInBits); 3123 3124 if (StoreSizeInBits > SrcTy.getSizeInBits()) { 3125 // Avoid creating a store with a narrower source than result. 3126 SrcReg = MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0); 3127 SrcTy = WideTy; 3128 } 3129 3130 auto ZextInReg = MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth); 3131 3132 MachineMemOperand *NewMMO = 3133 MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideTy); 3134 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO); 3135 StoreMI.eraseFromParent(); 3136 return Legalized; 3137 } 3138 3139 if (MemTy.isVector()) { 3140 // TODO: Handle vector trunc stores 3141 if (MemTy != SrcTy) 3142 return UnableToLegalize; 3143 3144 // TODO: We can do better than scalarizing the vector and at least split it 3145 // in half. 3146 return reduceLoadStoreWidth(StoreMI, 0, SrcTy.getElementType()); 3147 } 3148 3149 unsigned MemSizeInBits = MemTy.getSizeInBits(); 3150 uint64_t LargeSplitSize, SmallSplitSize; 3151 3152 if (!isPowerOf2_32(MemSizeInBits)) { 3153 LargeSplitSize = PowerOf2Floor(MemTy.getSizeInBits()); 3154 SmallSplitSize = MemTy.getSizeInBits() - LargeSplitSize; 3155 } else { 3156 auto &Ctx = MF.getFunction().getContext(); 3157 if (TLI.allowsMemoryAccess(Ctx, MIRBuilder.getDataLayout(), MemTy, MMO)) 3158 return UnableToLegalize; // Don't know what we're being asked to do. 3159 3160 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2; 3161 } 3162 3163 // Extend to the next pow-2. If this store was itself the result of lowering, 3164 // e.g. an s56 store being broken into s32 + s24, we might have a stored type 3165 // that's wider than the stored size. 3166 unsigned AnyExtSize = PowerOf2Ceil(MemTy.getSizeInBits()); 3167 const LLT NewSrcTy = LLT::scalar(AnyExtSize); 3168 3169 if (SrcTy.isPointer()) { 3170 const LLT IntPtrTy = LLT::scalar(SrcTy.getSizeInBits()); 3171 SrcReg = MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0); 3172 } 3173 3174 auto ExtVal = MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg); 3175 3176 // Obtain the smaller value by shifting away the larger value. 3177 auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize); 3178 auto SmallVal = MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt); 3179 3180 // Generate the PtrAdd and truncating stores. 3181 LLT PtrTy = MRI.getType(PtrReg); 3182 auto OffsetCst = MIRBuilder.buildConstant( 3183 LLT::scalar(PtrTy.getSizeInBits()), LargeSplitSize / 8); 3184 auto SmallPtr = 3185 MIRBuilder.buildPtrAdd(PtrTy, PtrReg, OffsetCst); 3186 3187 MachineMemOperand *LargeMMO = 3188 MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8); 3189 MachineMemOperand *SmallMMO = 3190 MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8); 3191 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO); 3192 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO); 3193 StoreMI.eraseFromParent(); 3194 return Legalized; 3195 } 3196 3197 LegalizerHelper::LegalizeResult 3198 LegalizerHelper::bitcast(MachineInstr &MI, unsigned TypeIdx, LLT CastTy) { 3199 switch (MI.getOpcode()) { 3200 case TargetOpcode::G_LOAD: { 3201 if (TypeIdx != 0) 3202 return UnableToLegalize; 3203 MachineMemOperand &MMO = **MI.memoperands_begin(); 3204 3205 // Not sure how to interpret a bitcast of an extending load. 3206 if (MMO.getMemoryType().getSizeInBits() != CastTy.getSizeInBits()) 3207 return UnableToLegalize; 3208 3209 Observer.changingInstr(MI); 3210 bitcastDst(MI, CastTy, 0); 3211 MMO.setType(CastTy); 3212 Observer.changedInstr(MI); 3213 return Legalized; 3214 } 3215 case TargetOpcode::G_STORE: { 3216 if (TypeIdx != 0) 3217 return UnableToLegalize; 3218 3219 MachineMemOperand &MMO = **MI.memoperands_begin(); 3220 3221 // Not sure how to interpret a bitcast of a truncating store. 3222 if (MMO.getMemoryType().getSizeInBits() != CastTy.getSizeInBits()) 3223 return UnableToLegalize; 3224 3225 Observer.changingInstr(MI); 3226 bitcastSrc(MI, CastTy, 0); 3227 MMO.setType(CastTy); 3228 Observer.changedInstr(MI); 3229 return Legalized; 3230 } 3231 case TargetOpcode::G_SELECT: { 3232 if (TypeIdx != 0) 3233 return UnableToLegalize; 3234 3235 if (MRI.getType(MI.getOperand(1).getReg()).isVector()) { 3236 LLVM_DEBUG( 3237 dbgs() << "bitcast action not implemented for vector select\n"); 3238 return UnableToLegalize; 3239 } 3240 3241 Observer.changingInstr(MI); 3242 bitcastSrc(MI, CastTy, 2); 3243 bitcastSrc(MI, CastTy, 3); 3244 bitcastDst(MI, CastTy, 0); 3245 Observer.changedInstr(MI); 3246 return Legalized; 3247 } 3248 case TargetOpcode::G_AND: 3249 case TargetOpcode::G_OR: 3250 case TargetOpcode::G_XOR: { 3251 Observer.changingInstr(MI); 3252 bitcastSrc(MI, CastTy, 1); 3253 bitcastSrc(MI, CastTy, 2); 3254 bitcastDst(MI, CastTy, 0); 3255 Observer.changedInstr(MI); 3256 return Legalized; 3257 } 3258 case TargetOpcode::G_EXTRACT_VECTOR_ELT: 3259 return bitcastExtractVectorElt(MI, TypeIdx, CastTy); 3260 case TargetOpcode::G_INSERT_VECTOR_ELT: 3261 return bitcastInsertVectorElt(MI, TypeIdx, CastTy); 3262 default: 3263 return UnableToLegalize; 3264 } 3265 } 3266 3267 // Legalize an instruction by changing the opcode in place. 3268 void LegalizerHelper::changeOpcode(MachineInstr &MI, unsigned NewOpcode) { 3269 Observer.changingInstr(MI); 3270 MI.setDesc(MIRBuilder.getTII().get(NewOpcode)); 3271 Observer.changedInstr(MI); 3272 } 3273 3274 LegalizerHelper::LegalizeResult 3275 LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { 3276 using namespace TargetOpcode; 3277 3278 switch(MI.getOpcode()) { 3279 default: 3280 return UnableToLegalize; 3281 case TargetOpcode::G_BITCAST: 3282 return lowerBitcast(MI); 3283 case TargetOpcode::G_SREM: 3284 case TargetOpcode::G_UREM: { 3285 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 3286 auto Quot = 3287 MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty}, 3288 {MI.getOperand(1), MI.getOperand(2)}); 3289 3290 auto Prod = MIRBuilder.buildMul(Ty, Quot, MI.getOperand(2)); 3291 MIRBuilder.buildSub(MI.getOperand(0), MI.getOperand(1), Prod); 3292 MI.eraseFromParent(); 3293 return Legalized; 3294 } 3295 case TargetOpcode::G_SADDO: 3296 case TargetOpcode::G_SSUBO: 3297 return lowerSADDO_SSUBO(MI); 3298 case TargetOpcode::G_UMULH: 3299 case TargetOpcode::G_SMULH: 3300 return lowerSMULH_UMULH(MI); 3301 case TargetOpcode::G_SMULO: 3302 case TargetOpcode::G_UMULO: { 3303 // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the 3304 // result. 3305 Register Res = MI.getOperand(0).getReg(); 3306 Register Overflow = MI.getOperand(1).getReg(); 3307 Register LHS = MI.getOperand(2).getReg(); 3308 Register RHS = MI.getOperand(3).getReg(); 3309 LLT Ty = MRI.getType(Res); 3310 3311 unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO 3312 ? TargetOpcode::G_SMULH 3313 : TargetOpcode::G_UMULH; 3314 3315 Observer.changingInstr(MI); 3316 const auto &TII = MIRBuilder.getTII(); 3317 MI.setDesc(TII.get(TargetOpcode::G_MUL)); 3318 MI.RemoveOperand(1); 3319 Observer.changedInstr(MI); 3320 3321 auto HiPart = MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS}); 3322 auto Zero = MIRBuilder.buildConstant(Ty, 0); 3323 3324 // Move insert point forward so we can use the Res register if needed. 3325 MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt()); 3326 3327 // For *signed* multiply, overflow is detected by checking: 3328 // (hi != (lo >> bitwidth-1)) 3329 if (Opcode == TargetOpcode::G_SMULH) { 3330 auto ShiftAmt = MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1); 3331 auto Shifted = MIRBuilder.buildAShr(Ty, Res, ShiftAmt); 3332 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted); 3333 } else { 3334 MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero); 3335 } 3336 return Legalized; 3337 } 3338 case TargetOpcode::G_FNEG: { 3339 Register Res = MI.getOperand(0).getReg(); 3340 LLT Ty = MRI.getType(Res); 3341 3342 // TODO: Handle vector types once we are able to 3343 // represent them. 3344 if (Ty.isVector()) 3345 return UnableToLegalize; 3346 auto SignMask = 3347 MIRBuilder.buildConstant(Ty, APInt::getSignMask(Ty.getSizeInBits())); 3348 Register SubByReg = MI.getOperand(1).getReg(); 3349 MIRBuilder.buildXor(Res, SubByReg, SignMask); 3350 MI.eraseFromParent(); 3351 return Legalized; 3352 } 3353 case TargetOpcode::G_FSUB: { 3354 Register Res = MI.getOperand(0).getReg(); 3355 LLT Ty = MRI.getType(Res); 3356 3357 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)). 3358 // First, check if G_FNEG is marked as Lower. If so, we may 3359 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG. 3360 if (LI.getAction({G_FNEG, {Ty}}).Action == Lower) 3361 return UnableToLegalize; 3362 Register LHS = MI.getOperand(1).getReg(); 3363 Register RHS = MI.getOperand(2).getReg(); 3364 Register Neg = MRI.createGenericVirtualRegister(Ty); 3365 MIRBuilder.buildFNeg(Neg, RHS); 3366 MIRBuilder.buildFAdd(Res, LHS, Neg, MI.getFlags()); 3367 MI.eraseFromParent(); 3368 return Legalized; 3369 } 3370 case TargetOpcode::G_FMAD: 3371 return lowerFMad(MI); 3372 case TargetOpcode::G_FFLOOR: 3373 return lowerFFloor(MI); 3374 case TargetOpcode::G_INTRINSIC_ROUND: 3375 return lowerIntrinsicRound(MI); 3376 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: { 3377 // Since round even is the assumed rounding mode for unconstrained FP 3378 // operations, rint and roundeven are the same operation. 3379 changeOpcode(MI, TargetOpcode::G_FRINT); 3380 return Legalized; 3381 } 3382 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { 3383 Register OldValRes = MI.getOperand(0).getReg(); 3384 Register SuccessRes = MI.getOperand(1).getReg(); 3385 Register Addr = MI.getOperand(2).getReg(); 3386 Register CmpVal = MI.getOperand(3).getReg(); 3387 Register NewVal = MI.getOperand(4).getReg(); 3388 MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, 3389 **MI.memoperands_begin()); 3390 MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); 3391 MI.eraseFromParent(); 3392 return Legalized; 3393 } 3394 case TargetOpcode::G_LOAD: 3395 case TargetOpcode::G_SEXTLOAD: 3396 case TargetOpcode::G_ZEXTLOAD: 3397 return lowerLoad(cast<GAnyLoad>(MI)); 3398 case TargetOpcode::G_STORE: 3399 return lowerStore(cast<GStore>(MI)); 3400 case TargetOpcode::G_CTLZ_ZERO_UNDEF: 3401 case TargetOpcode::G_CTTZ_ZERO_UNDEF: 3402 case TargetOpcode::G_CTLZ: 3403 case TargetOpcode::G_CTTZ: 3404 case TargetOpcode::G_CTPOP: 3405 return lowerBitCount(MI); 3406 case G_UADDO: { 3407 Register Res = MI.getOperand(0).getReg(); 3408 Register CarryOut = MI.getOperand(1).getReg(); 3409 Register LHS = MI.getOperand(2).getReg(); 3410 Register RHS = MI.getOperand(3).getReg(); 3411 3412 MIRBuilder.buildAdd(Res, LHS, RHS); 3413 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS); 3414 3415 MI.eraseFromParent(); 3416 return Legalized; 3417 } 3418 case G_UADDE: { 3419 Register Res = MI.getOperand(0).getReg(); 3420 Register CarryOut = MI.getOperand(1).getReg(); 3421 Register LHS = MI.getOperand(2).getReg(); 3422 Register RHS = MI.getOperand(3).getReg(); 3423 Register CarryIn = MI.getOperand(4).getReg(); 3424 LLT Ty = MRI.getType(Res); 3425 3426 auto TmpRes = MIRBuilder.buildAdd(Ty, LHS, RHS); 3427 auto ZExtCarryIn = MIRBuilder.buildZExt(Ty, CarryIn); 3428 MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn); 3429 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, LHS); 3430 3431 MI.eraseFromParent(); 3432 return Legalized; 3433 } 3434 case G_USUBO: { 3435 Register Res = MI.getOperand(0).getReg(); 3436 Register BorrowOut = MI.getOperand(1).getReg(); 3437 Register LHS = MI.getOperand(2).getReg(); 3438 Register RHS = MI.getOperand(3).getReg(); 3439 3440 MIRBuilder.buildSub(Res, LHS, RHS); 3441 MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS); 3442 3443 MI.eraseFromParent(); 3444 return Legalized; 3445 } 3446 case G_USUBE: { 3447 Register Res = MI.getOperand(0).getReg(); 3448 Register BorrowOut = MI.getOperand(1).getReg(); 3449 Register LHS = MI.getOperand(2).getReg(); 3450 Register RHS = MI.getOperand(3).getReg(); 3451 Register BorrowIn = MI.getOperand(4).getReg(); 3452 const LLT CondTy = MRI.getType(BorrowOut); 3453 const LLT Ty = MRI.getType(Res); 3454 3455 auto TmpRes = MIRBuilder.buildSub(Ty, LHS, RHS); 3456 auto ZExtBorrowIn = MIRBuilder.buildZExt(Ty, BorrowIn); 3457 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn); 3458 3459 auto LHS_EQ_RHS = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, CondTy, LHS, RHS); 3460 auto LHS_ULT_RHS = MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CondTy, LHS, RHS); 3461 MIRBuilder.buildSelect(BorrowOut, LHS_EQ_RHS, BorrowIn, LHS_ULT_RHS); 3462 3463 MI.eraseFromParent(); 3464 return Legalized; 3465 } 3466 case G_UITOFP: 3467 return lowerUITOFP(MI); 3468 case G_SITOFP: 3469 return lowerSITOFP(MI); 3470 case G_FPTOUI: 3471 return lowerFPTOUI(MI); 3472 case G_FPTOSI: 3473 return lowerFPTOSI(MI); 3474 case G_FPTRUNC: 3475 return lowerFPTRUNC(MI); 3476 case G_FPOWI: 3477 return lowerFPOWI(MI); 3478 case G_SMIN: 3479 case G_SMAX: 3480 case G_UMIN: 3481 case G_UMAX: 3482 return lowerMinMax(MI); 3483 case G_FCOPYSIGN: 3484 return lowerFCopySign(MI); 3485 case G_FMINNUM: 3486 case G_FMAXNUM: 3487 return lowerFMinNumMaxNum(MI); 3488 case G_MERGE_VALUES: 3489 return lowerMergeValues(MI); 3490 case G_UNMERGE_VALUES: 3491 return lowerUnmergeValues(MI); 3492 case TargetOpcode::G_SEXT_INREG: { 3493 assert(MI.getOperand(2).isImm() && "Expected immediate"); 3494 int64_t SizeInBits = MI.getOperand(2).getImm(); 3495 3496 Register DstReg = MI.getOperand(0).getReg(); 3497 Register SrcReg = MI.getOperand(1).getReg(); 3498 LLT DstTy = MRI.getType(DstReg); 3499 Register TmpRes = MRI.createGenericVirtualRegister(DstTy); 3500 3501 auto MIBSz = MIRBuilder.buildConstant(DstTy, DstTy.getScalarSizeInBits() - SizeInBits); 3502 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0)); 3503 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0)); 3504 MI.eraseFromParent(); 3505 return Legalized; 3506 } 3507 case G_EXTRACT_VECTOR_ELT: 3508 case G_INSERT_VECTOR_ELT: 3509 return lowerExtractInsertVectorElt(MI); 3510 case G_SHUFFLE_VECTOR: 3511 return lowerShuffleVector(MI); 3512 case G_DYN_STACKALLOC: 3513 return lowerDynStackAlloc(MI); 3514 case G_EXTRACT: 3515 return lowerExtract(MI); 3516 case G_INSERT: 3517 return lowerInsert(MI); 3518 case G_BSWAP: 3519 return lowerBswap(MI); 3520 case G_BITREVERSE: 3521 return lowerBitreverse(MI); 3522 case G_READ_REGISTER: 3523 case G_WRITE_REGISTER: 3524 return lowerReadWriteRegister(MI); 3525 case G_UADDSAT: 3526 case G_USUBSAT: { 3527 // Try to make a reasonable guess about which lowering strategy to use. The 3528 // target can override this with custom lowering and calling the 3529 // implementation functions. 3530 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 3531 if (LI.isLegalOrCustom({G_UMIN, Ty})) 3532 return lowerAddSubSatToMinMax(MI); 3533 return lowerAddSubSatToAddoSubo(MI); 3534 } 3535 case G_SADDSAT: 3536 case G_SSUBSAT: { 3537 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 3538 3539 // FIXME: It would probably make more sense to see if G_SADDO is preferred, 3540 // since it's a shorter expansion. However, we would need to figure out the 3541 // preferred boolean type for the carry out for the query. 3542 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty})) 3543 return lowerAddSubSatToMinMax(MI); 3544 return lowerAddSubSatToAddoSubo(MI); 3545 } 3546 case G_SSHLSAT: 3547 case G_USHLSAT: 3548 return lowerShlSat(MI); 3549 case G_ABS: 3550 return lowerAbsToAddXor(MI); 3551 case G_SELECT: 3552 return lowerSelect(MI); 3553 case G_SDIVREM: 3554 case G_UDIVREM: 3555 return lowerDIVREM(MI); 3556 case G_FSHL: 3557 case G_FSHR: 3558 return lowerFunnelShift(MI); 3559 case G_ROTL: 3560 case G_ROTR: 3561 return lowerRotate(MI); 3562 case G_MEMSET: 3563 case G_MEMCPY: 3564 case G_MEMMOVE: 3565 return lowerMemCpyFamily(MI); 3566 case G_MEMCPY_INLINE: 3567 return lowerMemcpyInline(MI); 3568 GISEL_VECREDUCE_CASES_NONSEQ 3569 return lowerVectorReduction(MI); 3570 } 3571 } 3572 3573 Align LegalizerHelper::getStackTemporaryAlignment(LLT Ty, 3574 Align MinAlign) const { 3575 // FIXME: We're missing a way to go back from LLT to llvm::Type to query the 3576 // datalayout for the preferred alignment. Also there should be a target hook 3577 // for this to allow targets to reduce the alignment and ignore the 3578 // datalayout. e.g. AMDGPU should always use a 4-byte alignment, regardless of 3579 // the type. 3580 return std::max(Align(PowerOf2Ceil(Ty.getSizeInBytes())), MinAlign); 3581 } 3582 3583 MachineInstrBuilder 3584 LegalizerHelper::createStackTemporary(TypeSize Bytes, Align Alignment, 3585 MachinePointerInfo &PtrInfo) { 3586 MachineFunction &MF = MIRBuilder.getMF(); 3587 const DataLayout &DL = MIRBuilder.getDataLayout(); 3588 int FrameIdx = MF.getFrameInfo().CreateStackObject(Bytes, Alignment, false); 3589 3590 unsigned AddrSpace = DL.getAllocaAddrSpace(); 3591 LLT FramePtrTy = LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)); 3592 3593 PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIdx); 3594 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx); 3595 } 3596 3597 static Register clampDynamicVectorIndex(MachineIRBuilder &B, Register IdxReg, 3598 LLT VecTy) { 3599 int64_t IdxVal; 3600 if (mi_match(IdxReg, *B.getMRI(), m_ICst(IdxVal))) 3601 return IdxReg; 3602 3603 LLT IdxTy = B.getMRI()->getType(IdxReg); 3604 unsigned NElts = VecTy.getNumElements(); 3605 if (isPowerOf2_32(NElts)) { 3606 APInt Imm = APInt::getLowBitsSet(IdxTy.getSizeInBits(), Log2_32(NElts)); 3607 return B.buildAnd(IdxTy, IdxReg, B.buildConstant(IdxTy, Imm)).getReg(0); 3608 } 3609 3610 return B.buildUMin(IdxTy, IdxReg, B.buildConstant(IdxTy, NElts - 1)) 3611 .getReg(0); 3612 } 3613 3614 Register LegalizerHelper::getVectorElementPointer(Register VecPtr, LLT VecTy, 3615 Register Index) { 3616 LLT EltTy = VecTy.getElementType(); 3617 3618 // Calculate the element offset and add it to the pointer. 3619 unsigned EltSize = EltTy.getSizeInBits() / 8; // FIXME: should be ABI size. 3620 assert(EltSize * 8 == EltTy.getSizeInBits() && 3621 "Converting bits to bytes lost precision"); 3622 3623 Index = clampDynamicVectorIndex(MIRBuilder, Index, VecTy); 3624 3625 LLT IdxTy = MRI.getType(Index); 3626 auto Mul = MIRBuilder.buildMul(IdxTy, Index, 3627 MIRBuilder.buildConstant(IdxTy, EltSize)); 3628 3629 LLT PtrTy = MRI.getType(VecPtr); 3630 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr, Mul).getReg(0); 3631 } 3632 3633 #ifndef NDEBUG 3634 /// Check that all vector operands have same number of elements. Other operands 3635 /// should be listed in NonVecOp. 3636 static bool hasSameNumEltsOnAllVectorOperands( 3637 GenericMachineInstr &MI, MachineRegisterInfo &MRI, 3638 std::initializer_list<unsigned> NonVecOpIndices) { 3639 if (MI.getNumMemOperands() != 0) 3640 return false; 3641 3642 LLT VecTy = MRI.getType(MI.getReg(0)); 3643 if (!VecTy.isVector()) 3644 return false; 3645 unsigned NumElts = VecTy.getNumElements(); 3646 3647 for (unsigned OpIdx = 1; OpIdx < MI.getNumOperands(); ++OpIdx) { 3648 MachineOperand &Op = MI.getOperand(OpIdx); 3649 if (!Op.isReg()) { 3650 if (!is_contained(NonVecOpIndices, OpIdx)) 3651 return false; 3652 continue; 3653 } 3654 3655 LLT Ty = MRI.getType(Op.getReg()); 3656 if (!Ty.isVector()) { 3657 if (!is_contained(NonVecOpIndices, OpIdx)) 3658 return false; 3659 continue; 3660 } 3661 3662 if (Ty.getNumElements() != NumElts) 3663 return false; 3664 } 3665 3666 return true; 3667 } 3668 #endif 3669 3670 /// Fill \p DstOps with DstOps that have same number of elements combined as 3671 /// the Ty. These DstOps have either scalar type when \p NumElts = 1 or are 3672 /// vectors with \p NumElts elements. When Ty.getNumElements() is not multiple 3673 /// of \p NumElts last DstOp (leftover) has fewer then \p NumElts elements. 3674 static void makeDstOps(SmallVectorImpl<DstOp> &DstOps, LLT Ty, 3675 unsigned NumElts) { 3676 LLT LeftoverTy; 3677 assert(Ty.isVector() && "Expected vector type"); 3678 LLT EltTy = Ty.getElementType(); 3679 LLT NarrowTy = (NumElts == 1) ? EltTy : LLT::fixed_vector(NumElts, EltTy); 3680 int NumParts, NumLeftover; 3681 std::tie(NumParts, NumLeftover) = 3682 getNarrowTypeBreakDown(Ty, NarrowTy, LeftoverTy); 3683 3684 assert(NumParts > 0 && "Error in getNarrowTypeBreakDown"); 3685 for (int i = 0; i < NumParts; ++i) { 3686 DstOps.push_back(NarrowTy); 3687 } 3688 3689 if (LeftoverTy.isValid()) { 3690 assert(NumLeftover == 1 && "expected exactly one leftover"); 3691 DstOps.push_back(LeftoverTy); 3692 } 3693 } 3694 3695 /// Operand \p Op is used on \p N sub-instructions. Fill \p Ops with \p N SrcOps 3696 /// made from \p Op depending on operand type. 3697 static void broadcastSrcOp(SmallVectorImpl<SrcOp> &Ops, unsigned N, 3698 MachineOperand &Op) { 3699 for (unsigned i = 0; i < N; ++i) { 3700 if (Op.isReg()) 3701 Ops.push_back(Op.getReg()); 3702 else if (Op.isImm()) 3703 Ops.push_back(Op.getImm()); 3704 else if (Op.isPredicate()) 3705 Ops.push_back(static_cast<CmpInst::Predicate>(Op.getPredicate())); 3706 else 3707 llvm_unreachable("Unsupported type"); 3708 } 3709 } 3710 3711 // Handle splitting vector operations which need to have the same number of 3712 // elements in each type index, but each type index may have a different element 3713 // type. 3714 // 3715 // e.g. <4 x s64> = G_SHL <4 x s64>, <4 x s32> -> 3716 // <2 x s64> = G_SHL <2 x s64>, <2 x s32> 3717 // <2 x s64> = G_SHL <2 x s64>, <2 x s32> 3718 // 3719 // Also handles some irregular breakdown cases, e.g. 3720 // e.g. <3 x s64> = G_SHL <3 x s64>, <3 x s32> -> 3721 // <2 x s64> = G_SHL <2 x s64>, <2 x s32> 3722 // s64 = G_SHL s64, s32 3723 LegalizerHelper::LegalizeResult 3724 LegalizerHelper::fewerElementsVectorMultiEltType( 3725 GenericMachineInstr &MI, unsigned NumElts, 3726 std::initializer_list<unsigned> NonVecOpIndices) { 3727 assert(hasSameNumEltsOnAllVectorOperands(MI, MRI, NonVecOpIndices) && 3728 "Non-compatible opcode or not specified non-vector operands"); 3729 unsigned OrigNumElts = MRI.getType(MI.getReg(0)).getNumElements(); 3730 3731 unsigned NumInputs = MI.getNumOperands() - MI.getNumDefs(); 3732 unsigned NumDefs = MI.getNumDefs(); 3733 3734 // Create DstOps (sub-vectors with NumElts elts + Leftover) for each output. 3735 // Build instructions with DstOps to use instruction found by CSE directly. 3736 // CSE copies found instruction into given vreg when building with vreg dest. 3737 SmallVector<SmallVector<DstOp, 8>, 2> OutputOpsPieces(NumDefs); 3738 // Output registers will be taken from created instructions. 3739 SmallVector<SmallVector<Register, 8>, 2> OutputRegs(NumDefs); 3740 for (unsigned i = 0; i < NumDefs; ++i) { 3741 makeDstOps(OutputOpsPieces[i], MRI.getType(MI.getReg(i)), NumElts); 3742 } 3743 3744 // Split vector input operands into sub-vectors with NumElts elts + Leftover. 3745 // Operands listed in NonVecOpIndices will be used as is without splitting; 3746 // examples: compare predicate in icmp and fcmp (op 1), vector select with i1 3747 // scalar condition (op 1), immediate in sext_inreg (op 2). 3748 SmallVector<SmallVector<SrcOp, 8>, 3> InputOpsPieces(NumInputs); 3749 for (unsigned UseIdx = NumDefs, UseNo = 0; UseIdx < MI.getNumOperands(); 3750 ++UseIdx, ++UseNo) { 3751 if (is_contained(NonVecOpIndices, UseIdx)) { 3752 broadcastSrcOp(InputOpsPieces[UseNo], OutputOpsPieces[0].size(), 3753 MI.getOperand(UseIdx)); 3754 } else { 3755 SmallVector<Register, 8> SplitPieces; 3756 extractVectorParts(MI.getReg(UseIdx), NumElts, SplitPieces); 3757 for (auto Reg : SplitPieces) 3758 InputOpsPieces[UseNo].push_back(Reg); 3759 } 3760 } 3761 3762 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0; 3763 3764 // Take i-th piece of each input operand split and build sub-vector/scalar 3765 // instruction. Set i-th DstOp(s) from OutputOpsPieces as destination(s). 3766 for (unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) { 3767 SmallVector<DstOp, 2> Defs; 3768 for (unsigned DstNo = 0; DstNo < NumDefs; ++DstNo) 3769 Defs.push_back(OutputOpsPieces[DstNo][i]); 3770 3771 SmallVector<SrcOp, 3> Uses; 3772 for (unsigned InputNo = 0; InputNo < NumInputs; ++InputNo) 3773 Uses.push_back(InputOpsPieces[InputNo][i]); 3774 3775 auto I = MIRBuilder.buildInstr(MI.getOpcode(), Defs, Uses, MI.getFlags()); 3776 for (unsigned DstNo = 0; DstNo < NumDefs; ++DstNo) 3777 OutputRegs[DstNo].push_back(I.getReg(DstNo)); 3778 } 3779 3780 // Merge small outputs into MI's output for each def operand. 3781 if (NumLeftovers) { 3782 for (unsigned i = 0; i < NumDefs; ++i) 3783 mergeMixedSubvectors(MI.getReg(i), OutputRegs[i]); 3784 } else { 3785 for (unsigned i = 0; i < NumDefs; ++i) 3786 MIRBuilder.buildMerge(MI.getReg(i), OutputRegs[i]); 3787 } 3788 3789 MI.eraseFromParent(); 3790 return Legalized; 3791 } 3792 3793 LegalizerHelper::LegalizeResult 3794 LegalizerHelper::fewerElementsVectorPhi(GenericMachineInstr &MI, 3795 unsigned NumElts) { 3796 unsigned OrigNumElts = MRI.getType(MI.getReg(0)).getNumElements(); 3797 3798 unsigned NumInputs = MI.getNumOperands() - MI.getNumDefs(); 3799 unsigned NumDefs = MI.getNumDefs(); 3800 3801 SmallVector<DstOp, 8> OutputOpsPieces; 3802 SmallVector<Register, 8> OutputRegs; 3803 makeDstOps(OutputOpsPieces, MRI.getType(MI.getReg(0)), NumElts); 3804 3805 // Instructions that perform register split will be inserted in basic block 3806 // where register is defined (basic block is in the next operand). 3807 SmallVector<SmallVector<Register, 8>, 3> InputOpsPieces(NumInputs / 2); 3808 for (unsigned UseIdx = NumDefs, UseNo = 0; UseIdx < MI.getNumOperands(); 3809 UseIdx += 2, ++UseNo) { 3810 MachineBasicBlock &OpMBB = *MI.getOperand(UseIdx + 1).getMBB(); 3811 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 3812 extractVectorParts(MI.getReg(UseIdx), NumElts, InputOpsPieces[UseNo]); 3813 } 3814 3815 // Build PHIs with fewer elements. 3816 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0; 3817 MIRBuilder.setInsertPt(*MI.getParent(), MI); 3818 for (unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) { 3819 auto Phi = MIRBuilder.buildInstr(TargetOpcode::G_PHI); 3820 Phi.addDef( 3821 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI))); 3822 OutputRegs.push_back(Phi.getReg(0)); 3823 3824 for (unsigned j = 0; j < NumInputs / 2; ++j) { 3825 Phi.addUse(InputOpsPieces[j][i]); 3826 Phi.add(MI.getOperand(1 + j * 2 + 1)); 3827 } 3828 } 3829 3830 // Merge small outputs into MI's def. 3831 if (NumLeftovers) { 3832 mergeMixedSubvectors(MI.getReg(0), OutputRegs); 3833 } else { 3834 MIRBuilder.buildMerge(MI.getReg(0), OutputRegs); 3835 } 3836 3837 MI.eraseFromParent(); 3838 return Legalized; 3839 } 3840 3841 LegalizerHelper::LegalizeResult 3842 LegalizerHelper::fewerElementsVectorUnmergeValues(MachineInstr &MI, 3843 unsigned TypeIdx, 3844 LLT NarrowTy) { 3845 const int NumDst = MI.getNumOperands() - 1; 3846 const Register SrcReg = MI.getOperand(NumDst).getReg(); 3847 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 3848 LLT SrcTy = MRI.getType(SrcReg); 3849 3850 if (TypeIdx != 1 || NarrowTy == DstTy) 3851 return UnableToLegalize; 3852 3853 // Requires compatible types. Otherwise SrcReg should have been defined by 3854 // merge-like instruction that would get artifact combined. Most likely 3855 // instruction that defines SrcReg has to perform more/fewer elements 3856 // legalization compatible with NarrowTy. 3857 assert(SrcTy.isVector() && NarrowTy.isVector() && "Expected vector types"); 3858 assert((SrcTy.getScalarType() == NarrowTy.getScalarType()) && "bad type"); 3859 3860 if ((SrcTy.getSizeInBits() % NarrowTy.getSizeInBits() != 0) || 3861 (NarrowTy.getSizeInBits() % DstTy.getSizeInBits() != 0)) 3862 return UnableToLegalize; 3863 3864 // This is most likely DstTy (smaller then register size) packed in SrcTy 3865 // (larger then register size) and since unmerge was not combined it will be 3866 // lowered to bit sequence extracts from register. Unpack SrcTy to NarrowTy 3867 // (register size) pieces first. Then unpack each of NarrowTy pieces to DstTy. 3868 3869 // %1:_(DstTy), %2, %3, %4 = G_UNMERGE_VALUES %0:_(SrcTy) 3870 // 3871 // %5:_(NarrowTy), %6 = G_UNMERGE_VALUES %0:_(SrcTy) - reg sequence 3872 // %1:_(DstTy), %2 = G_UNMERGE_VALUES %5:_(NarrowTy) - sequence of bits in reg 3873 // %3:_(DstTy), %4 = G_UNMERGE_VALUES %6:_(NarrowTy) 3874 auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, SrcReg); 3875 const int NumUnmerge = Unmerge->getNumOperands() - 1; 3876 const int PartsPerUnmerge = NumDst / NumUnmerge; 3877 3878 for (int I = 0; I != NumUnmerge; ++I) { 3879 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES); 3880 3881 for (int J = 0; J != PartsPerUnmerge; ++J) 3882 MIB.addDef(MI.getOperand(I * PartsPerUnmerge + J).getReg()); 3883 MIB.addUse(Unmerge.getReg(I)); 3884 } 3885 3886 MI.eraseFromParent(); 3887 return Legalized; 3888 } 3889 3890 LegalizerHelper::LegalizeResult 3891 LegalizerHelper::fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, 3892 LLT NarrowTy) { 3893 Register DstReg = MI.getOperand(0).getReg(); 3894 LLT DstTy = MRI.getType(DstReg); 3895 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 3896 // Requires compatible types. Otherwise user of DstReg did not perform unmerge 3897 // that should have been artifact combined. Most likely instruction that uses 3898 // DstReg has to do more/fewer elements legalization compatible with NarrowTy. 3899 assert(DstTy.isVector() && NarrowTy.isVector() && "Expected vector types"); 3900 assert((DstTy.getScalarType() == NarrowTy.getScalarType()) && "bad type"); 3901 if (NarrowTy == SrcTy) 3902 return UnableToLegalize; 3903 3904 // This attempts to lower part of LCMTy merge/unmerge sequence. Intended use 3905 // is for old mir tests. Since the changes to more/fewer elements it should no 3906 // longer be possible to generate MIR like this when starting from llvm-ir 3907 // because LCMTy approach was replaced with merge/unmerge to vector elements. 3908 if (TypeIdx == 1) { 3909 assert(SrcTy.isVector() && "Expected vector types"); 3910 assert((SrcTy.getScalarType() == NarrowTy.getScalarType()) && "bad type"); 3911 if ((DstTy.getSizeInBits() % NarrowTy.getSizeInBits() != 0) || 3912 (NarrowTy.getNumElements() >= SrcTy.getNumElements())) 3913 return UnableToLegalize; 3914 // %2:_(DstTy) = G_CONCAT_VECTORS %0:_(SrcTy), %1:_(SrcTy) 3915 // 3916 // %3:_(EltTy), %4, %5 = G_UNMERGE_VALUES %0:_(SrcTy) 3917 // %6:_(EltTy), %7, %8 = G_UNMERGE_VALUES %1:_(SrcTy) 3918 // %9:_(NarrowTy) = G_BUILD_VECTOR %3:_(EltTy), %4 3919 // %10:_(NarrowTy) = G_BUILD_VECTOR %5:_(EltTy), %6 3920 // %11:_(NarrowTy) = G_BUILD_VECTOR %7:_(EltTy), %8 3921 // %2:_(DstTy) = G_CONCAT_VECTORS %9:_(NarrowTy), %10, %11 3922 3923 SmallVector<Register, 8> Elts; 3924 LLT EltTy = MRI.getType(MI.getOperand(1).getReg()).getScalarType(); 3925 for (unsigned i = 1; i < MI.getNumOperands(); ++i) { 3926 auto Unmerge = MIRBuilder.buildUnmerge(EltTy, MI.getOperand(i).getReg()); 3927 for (unsigned j = 0; j < Unmerge->getNumDefs(); ++j) 3928 Elts.push_back(Unmerge.getReg(j)); 3929 } 3930 3931 SmallVector<Register, 8> NarrowTyElts; 3932 unsigned NumNarrowTyElts = NarrowTy.getNumElements(); 3933 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts; 3934 for (unsigned i = 0, Offset = 0; i < NumNarrowTyPieces; 3935 ++i, Offset += NumNarrowTyElts) { 3936 ArrayRef<Register> Pieces(&Elts[Offset], NumNarrowTyElts); 3937 NarrowTyElts.push_back(MIRBuilder.buildMerge(NarrowTy, Pieces).getReg(0)); 3938 } 3939 3940 MIRBuilder.buildMerge(DstReg, NarrowTyElts); 3941 MI.eraseFromParent(); 3942 return Legalized; 3943 } 3944 3945 assert(TypeIdx == 0 && "Bad type index"); 3946 if ((NarrowTy.getSizeInBits() % SrcTy.getSizeInBits() != 0) || 3947 (DstTy.getSizeInBits() % NarrowTy.getSizeInBits() != 0)) 3948 return UnableToLegalize; 3949 3950 // This is most likely SrcTy (smaller then register size) packed in DstTy 3951 // (larger then register size) and since merge was not combined it will be 3952 // lowered to bit sequence packing into register. Merge SrcTy to NarrowTy 3953 // (register size) pieces first. Then merge each of NarrowTy pieces to DstTy. 3954 3955 // %0:_(DstTy) = G_MERGE_VALUES %1:_(SrcTy), %2, %3, %4 3956 // 3957 // %5:_(NarrowTy) = G_MERGE_VALUES %1:_(SrcTy), %2 - sequence of bits in reg 3958 // %6:_(NarrowTy) = G_MERGE_VALUES %3:_(SrcTy), %4 3959 // %0:_(DstTy) = G_MERGE_VALUES %5:_(NarrowTy), %6 - reg sequence 3960 SmallVector<Register, 8> NarrowTyElts; 3961 unsigned NumParts = DstTy.getNumElements() / NarrowTy.getNumElements(); 3962 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1; 3963 unsigned NumElts = NarrowTy.getNumElements() / NumSrcElts; 3964 for (unsigned i = 0; i < NumParts; ++i) { 3965 SmallVector<Register, 8> Sources; 3966 for (unsigned j = 0; j < NumElts; ++j) 3967 Sources.push_back(MI.getOperand(1 + i * NumElts + j).getReg()); 3968 NarrowTyElts.push_back(MIRBuilder.buildMerge(NarrowTy, Sources).getReg(0)); 3969 } 3970 3971 MIRBuilder.buildMerge(DstReg, NarrowTyElts); 3972 MI.eraseFromParent(); 3973 return Legalized; 3974 } 3975 3976 LegalizerHelper::LegalizeResult 3977 LegalizerHelper::fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, 3978 unsigned TypeIdx, 3979 LLT NarrowVecTy) { 3980 Register DstReg = MI.getOperand(0).getReg(); 3981 Register SrcVec = MI.getOperand(1).getReg(); 3982 Register InsertVal; 3983 bool IsInsert = MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT; 3984 3985 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) && "not a vector type index"); 3986 if (IsInsert) 3987 InsertVal = MI.getOperand(2).getReg(); 3988 3989 Register Idx = MI.getOperand(MI.getNumOperands() - 1).getReg(); 3990 3991 // TODO: Handle total scalarization case. 3992 if (!NarrowVecTy.isVector()) 3993 return UnableToLegalize; 3994 3995 LLT VecTy = MRI.getType(SrcVec); 3996 3997 // If the index is a constant, we can really break this down as you would 3998 // expect, and index into the target size pieces. 3999 int64_t IdxVal; 4000 auto MaybeCst = getIConstantVRegValWithLookThrough(Idx, MRI); 4001 if (MaybeCst) { 4002 IdxVal = MaybeCst->Value.getSExtValue(); 4003 // Avoid out of bounds indexing the pieces. 4004 if (IdxVal >= VecTy.getNumElements()) { 4005 MIRBuilder.buildUndef(DstReg); 4006 MI.eraseFromParent(); 4007 return Legalized; 4008 } 4009 4010 SmallVector<Register, 8> VecParts; 4011 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec); 4012 4013 // Build a sequence of NarrowTy pieces in VecParts for this operand. 4014 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts, 4015 TargetOpcode::G_ANYEXT); 4016 4017 unsigned NewNumElts = NarrowVecTy.getNumElements(); 4018 4019 LLT IdxTy = MRI.getType(Idx); 4020 int64_t PartIdx = IdxVal / NewNumElts; 4021 auto NewIdx = 4022 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx); 4023 4024 if (IsInsert) { 4025 LLT PartTy = MRI.getType(VecParts[PartIdx]); 4026 4027 // Use the adjusted index to insert into one of the subvectors. 4028 auto InsertPart = MIRBuilder.buildInsertVectorElement( 4029 PartTy, VecParts[PartIdx], InsertVal, NewIdx); 4030 VecParts[PartIdx] = InsertPart.getReg(0); 4031 4032 // Recombine the inserted subvector with the others to reform the result 4033 // vector. 4034 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts); 4035 } else { 4036 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx); 4037 } 4038 4039 MI.eraseFromParent(); 4040 return Legalized; 4041 } 4042 4043 // With a variable index, we can't perform the operation in a smaller type, so 4044 // we're forced to expand this. 4045 // 4046 // TODO: We could emit a chain of compare/select to figure out which piece to 4047 // index. 4048 return lowerExtractInsertVectorElt(MI); 4049 } 4050 4051 LegalizerHelper::LegalizeResult 4052 LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx, 4053 LLT NarrowTy) { 4054 // FIXME: Don't know how to handle secondary types yet. 4055 if (TypeIdx != 0) 4056 return UnableToLegalize; 4057 4058 // This implementation doesn't work for atomics. Give up instead of doing 4059 // something invalid. 4060 if (LdStMI.isAtomic()) 4061 return UnableToLegalize; 4062 4063 bool IsLoad = isa<GLoad>(LdStMI); 4064 Register ValReg = LdStMI.getReg(0); 4065 Register AddrReg = LdStMI.getPointerReg(); 4066 LLT ValTy = MRI.getType(ValReg); 4067 4068 // FIXME: Do we need a distinct NarrowMemory legalize action? 4069 if (ValTy.getSizeInBits() != 8 * LdStMI.getMemSize()) { 4070 LLVM_DEBUG(dbgs() << "Can't narrow extload/truncstore\n"); 4071 return UnableToLegalize; 4072 } 4073 4074 int NumParts = -1; 4075 int NumLeftover = -1; 4076 LLT LeftoverTy; 4077 SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs; 4078 if (IsLoad) { 4079 std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy); 4080 } else { 4081 if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs, 4082 NarrowLeftoverRegs)) { 4083 NumParts = NarrowRegs.size(); 4084 NumLeftover = NarrowLeftoverRegs.size(); 4085 } 4086 } 4087 4088 if (NumParts == -1) 4089 return UnableToLegalize; 4090 4091 LLT PtrTy = MRI.getType(AddrReg); 4092 const LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits()); 4093 4094 unsigned TotalSize = ValTy.getSizeInBits(); 4095 4096 // Split the load/store into PartTy sized pieces starting at Offset. If this 4097 // is a load, return the new registers in ValRegs. For a store, each elements 4098 // of ValRegs should be PartTy. Returns the next offset that needs to be 4099 // handled. 4100 bool isBigEndian = MIRBuilder.getDataLayout().isBigEndian(); 4101 auto MMO = LdStMI.getMMO(); 4102 auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs, 4103 unsigned NumParts, unsigned Offset) -> unsigned { 4104 MachineFunction &MF = MIRBuilder.getMF(); 4105 unsigned PartSize = PartTy.getSizeInBits(); 4106 for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize; 4107 ++Idx) { 4108 unsigned ByteOffset = Offset / 8; 4109 Register NewAddrReg; 4110 4111 MIRBuilder.materializePtrAdd(NewAddrReg, AddrReg, OffsetTy, ByteOffset); 4112 4113 MachineMemOperand *NewMMO = 4114 MF.getMachineMemOperand(&MMO, ByteOffset, PartTy); 4115 4116 if (IsLoad) { 4117 Register Dst = MRI.createGenericVirtualRegister(PartTy); 4118 ValRegs.push_back(Dst); 4119 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO); 4120 } else { 4121 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO); 4122 } 4123 Offset = isBigEndian ? Offset - PartSize : Offset + PartSize; 4124 } 4125 4126 return Offset; 4127 }; 4128 4129 unsigned Offset = isBigEndian ? TotalSize - NarrowTy.getSizeInBits() : 0; 4130 unsigned HandledOffset = 4131 splitTypePieces(NarrowTy, NarrowRegs, NumParts, Offset); 4132 4133 // Handle the rest of the register if this isn't an even type breakdown. 4134 if (LeftoverTy.isValid()) 4135 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset); 4136 4137 if (IsLoad) { 4138 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs, 4139 LeftoverTy, NarrowLeftoverRegs); 4140 } 4141 4142 LdStMI.eraseFromParent(); 4143 return Legalized; 4144 } 4145 4146 LegalizerHelper::LegalizeResult 4147 LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, 4148 LLT NarrowTy) { 4149 using namespace TargetOpcode; 4150 GenericMachineInstr &GMI = cast<GenericMachineInstr>(MI); 4151 unsigned NumElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1; 4152 4153 switch (MI.getOpcode()) { 4154 case G_IMPLICIT_DEF: 4155 case G_TRUNC: 4156 case G_AND: 4157 case G_OR: 4158 case G_XOR: 4159 case G_ADD: 4160 case G_SUB: 4161 case G_MUL: 4162 case G_PTR_ADD: 4163 case G_SMULH: 4164 case G_UMULH: 4165 case G_FADD: 4166 case G_FMUL: 4167 case G_FSUB: 4168 case G_FNEG: 4169 case G_FABS: 4170 case G_FCANONICALIZE: 4171 case G_FDIV: 4172 case G_FREM: 4173 case G_FMA: 4174 case G_FMAD: 4175 case G_FPOW: 4176 case G_FEXP: 4177 case G_FEXP2: 4178 case G_FLOG: 4179 case G_FLOG2: 4180 case G_FLOG10: 4181 case G_FNEARBYINT: 4182 case G_FCEIL: 4183 case G_FFLOOR: 4184 case G_FRINT: 4185 case G_INTRINSIC_ROUND: 4186 case G_INTRINSIC_ROUNDEVEN: 4187 case G_INTRINSIC_TRUNC: 4188 case G_FCOS: 4189 case G_FSIN: 4190 case G_FSQRT: 4191 case G_BSWAP: 4192 case G_BITREVERSE: 4193 case G_SDIV: 4194 case G_UDIV: 4195 case G_SREM: 4196 case G_UREM: 4197 case G_SDIVREM: 4198 case G_UDIVREM: 4199 case G_SMIN: 4200 case G_SMAX: 4201 case G_UMIN: 4202 case G_UMAX: 4203 case G_ABS: 4204 case G_FMINNUM: 4205 case G_FMAXNUM: 4206 case G_FMINNUM_IEEE: 4207 case G_FMAXNUM_IEEE: 4208 case G_FMINIMUM: 4209 case G_FMAXIMUM: 4210 case G_FSHL: 4211 case G_FSHR: 4212 case G_ROTL: 4213 case G_ROTR: 4214 case G_FREEZE: 4215 case G_SADDSAT: 4216 case G_SSUBSAT: 4217 case G_UADDSAT: 4218 case G_USUBSAT: 4219 case G_UMULO: 4220 case G_SMULO: 4221 case G_SHL: 4222 case G_LSHR: 4223 case G_ASHR: 4224 case G_SSHLSAT: 4225 case G_USHLSAT: 4226 case G_CTLZ: 4227 case G_CTLZ_ZERO_UNDEF: 4228 case G_CTTZ: 4229 case G_CTTZ_ZERO_UNDEF: 4230 case G_CTPOP: 4231 case G_FCOPYSIGN: 4232 case G_ZEXT: 4233 case G_SEXT: 4234 case G_ANYEXT: 4235 case G_FPEXT: 4236 case G_FPTRUNC: 4237 case G_SITOFP: 4238 case G_UITOFP: 4239 case G_FPTOSI: 4240 case G_FPTOUI: 4241 case G_INTTOPTR: 4242 case G_PTRTOINT: 4243 case G_ADDRSPACE_CAST: 4244 return fewerElementsVectorMultiEltType(GMI, NumElts); 4245 case G_ICMP: 4246 case G_FCMP: 4247 return fewerElementsVectorMultiEltType(GMI, NumElts, {1 /*cpm predicate*/}); 4248 case G_SELECT: 4249 if (MRI.getType(MI.getOperand(1).getReg()).isVector()) 4250 return fewerElementsVectorMultiEltType(GMI, NumElts); 4251 return fewerElementsVectorMultiEltType(GMI, NumElts, {1 /*scalar cond*/}); 4252 case G_PHI: 4253 return fewerElementsVectorPhi(GMI, NumElts); 4254 case G_UNMERGE_VALUES: 4255 return fewerElementsVectorUnmergeValues(MI, TypeIdx, NarrowTy); 4256 case G_BUILD_VECTOR: 4257 assert(TypeIdx == 0 && "not a vector type index"); 4258 return fewerElementsVectorMerge(MI, TypeIdx, NarrowTy); 4259 case G_CONCAT_VECTORS: 4260 if (TypeIdx != 1) // TODO: This probably does work as expected already. 4261 return UnableToLegalize; 4262 return fewerElementsVectorMerge(MI, TypeIdx, NarrowTy); 4263 case G_EXTRACT_VECTOR_ELT: 4264 case G_INSERT_VECTOR_ELT: 4265 return fewerElementsVectorExtractInsertVectorElt(MI, TypeIdx, NarrowTy); 4266 case G_LOAD: 4267 case G_STORE: 4268 return reduceLoadStoreWidth(cast<GLoadStore>(MI), TypeIdx, NarrowTy); 4269 case G_SEXT_INREG: 4270 return fewerElementsVectorMultiEltType(GMI, NumElts, {2 /*imm*/}); 4271 GISEL_VECREDUCE_CASES_NONSEQ 4272 return fewerElementsVectorReductions(MI, TypeIdx, NarrowTy); 4273 case G_SHUFFLE_VECTOR: 4274 return fewerElementsVectorShuffle(MI, TypeIdx, NarrowTy); 4275 default: 4276 return UnableToLegalize; 4277 } 4278 } 4279 4280 LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorShuffle( 4281 MachineInstr &MI, unsigned int TypeIdx, LLT NarrowTy) { 4282 assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR); 4283 if (TypeIdx != 0) 4284 return UnableToLegalize; 4285 4286 Register DstReg = MI.getOperand(0).getReg(); 4287 Register Src1Reg = MI.getOperand(1).getReg(); 4288 Register Src2Reg = MI.getOperand(2).getReg(); 4289 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask(); 4290 LLT DstTy = MRI.getType(DstReg); 4291 LLT Src1Ty = MRI.getType(Src1Reg); 4292 LLT Src2Ty = MRI.getType(Src2Reg); 4293 // The shuffle should be canonicalized by now. 4294 if (DstTy != Src1Ty) 4295 return UnableToLegalize; 4296 if (DstTy != Src2Ty) 4297 return UnableToLegalize; 4298 4299 if (!isPowerOf2_32(DstTy.getNumElements())) 4300 return UnableToLegalize; 4301 4302 // We only support splitting a shuffle into 2, so adjust NarrowTy accordingly. 4303 // Further legalization attempts will be needed to do split further. 4304 NarrowTy = 4305 DstTy.changeElementCount(DstTy.getElementCount().divideCoefficientBy(2)); 4306 unsigned NewElts = NarrowTy.getNumElements(); 4307 4308 SmallVector<Register> SplitSrc1Regs, SplitSrc2Regs; 4309 extractParts(Src1Reg, NarrowTy, 2, SplitSrc1Regs); 4310 extractParts(Src2Reg, NarrowTy, 2, SplitSrc2Regs); 4311 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0], 4312 SplitSrc2Regs[1]}; 4313 4314 Register Hi, Lo; 4315 4316 // If Lo or Hi uses elements from at most two of the four input vectors, then 4317 // express it as a vector shuffle of those two inputs. Otherwise extract the 4318 // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR. 4319 SmallVector<int, 16> Ops; 4320 for (unsigned High = 0; High < 2; ++High) { 4321 Register &Output = High ? Hi : Lo; 4322 4323 // Build a shuffle mask for the output, discovering on the fly which 4324 // input vectors to use as shuffle operands (recorded in InputUsed). 4325 // If building a suitable shuffle vector proves too hard, then bail 4326 // out with useBuildVector set. 4327 unsigned InputUsed[2] = {-1U, -1U}; // Not yet discovered. 4328 unsigned FirstMaskIdx = High * NewElts; 4329 bool UseBuildVector = false; 4330 for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { 4331 // The mask element. This indexes into the input. 4332 int Idx = Mask[FirstMaskIdx + MaskOffset]; 4333 4334 // The input vector this mask element indexes into. 4335 unsigned Input = (unsigned)Idx / NewElts; 4336 4337 if (Input >= array_lengthof(Inputs)) { 4338 // The mask element does not index into any input vector. 4339 Ops.push_back(-1); 4340 continue; 4341 } 4342 4343 // Turn the index into an offset from the start of the input vector. 4344 Idx -= Input * NewElts; 4345 4346 // Find or create a shuffle vector operand to hold this input. 4347 unsigned OpNo; 4348 for (OpNo = 0; OpNo < array_lengthof(InputUsed); ++OpNo) { 4349 if (InputUsed[OpNo] == Input) { 4350 // This input vector is already an operand. 4351 break; 4352 } else if (InputUsed[OpNo] == -1U) { 4353 // Create a new operand for this input vector. 4354 InputUsed[OpNo] = Input; 4355 break; 4356 } 4357 } 4358 4359 if (OpNo >= array_lengthof(InputUsed)) { 4360 // More than two input vectors used! Give up on trying to create a 4361 // shuffle vector. Insert all elements into a BUILD_VECTOR instead. 4362 UseBuildVector = true; 4363 break; 4364 } 4365 4366 // Add the mask index for the new shuffle vector. 4367 Ops.push_back(Idx + OpNo * NewElts); 4368 } 4369 4370 if (UseBuildVector) { 4371 LLT EltTy = NarrowTy.getElementType(); 4372 SmallVector<Register, 16> SVOps; 4373 4374 // Extract the input elements by hand. 4375 for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { 4376 // The mask element. This indexes into the input. 4377 int Idx = Mask[FirstMaskIdx + MaskOffset]; 4378 4379 // The input vector this mask element indexes into. 4380 unsigned Input = (unsigned)Idx / NewElts; 4381 4382 if (Input >= array_lengthof(Inputs)) { 4383 // The mask element is "undef" or indexes off the end of the input. 4384 SVOps.push_back(MIRBuilder.buildUndef(EltTy).getReg(0)); 4385 continue; 4386 } 4387 4388 // Turn the index into an offset from the start of the input vector. 4389 Idx -= Input * NewElts; 4390 4391 // Extract the vector element by hand. 4392 SVOps.push_back(MIRBuilder 4393 .buildExtractVectorElement( 4394 EltTy, Inputs[Input], 4395 MIRBuilder.buildConstant(LLT::scalar(32), Idx)) 4396 .getReg(0)); 4397 } 4398 4399 // Construct the Lo/Hi output using a G_BUILD_VECTOR. 4400 Output = MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0); 4401 } else if (InputUsed[0] == -1U) { 4402 // No input vectors were used! The result is undefined. 4403 Output = MIRBuilder.buildUndef(NarrowTy).getReg(0); 4404 } else { 4405 Register Op0 = Inputs[InputUsed[0]]; 4406 // If only one input was used, use an undefined vector for the other. 4407 Register Op1 = InputUsed[1] == -1U 4408 ? MIRBuilder.buildUndef(NarrowTy).getReg(0) 4409 : Inputs[InputUsed[1]]; 4410 // At least one input vector was used. Create a new shuffle vector. 4411 Output = MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1, Ops).getReg(0); 4412 } 4413 4414 Ops.clear(); 4415 } 4416 4417 MIRBuilder.buildConcatVectors(DstReg, {Lo, Hi}); 4418 MI.eraseFromParent(); 4419 return Legalized; 4420 } 4421 4422 static unsigned getScalarOpcForReduction(unsigned Opc) { 4423 unsigned ScalarOpc; 4424 switch (Opc) { 4425 case TargetOpcode::G_VECREDUCE_FADD: 4426 ScalarOpc = TargetOpcode::G_FADD; 4427 break; 4428 case TargetOpcode::G_VECREDUCE_FMUL: 4429 ScalarOpc = TargetOpcode::G_FMUL; 4430 break; 4431 case TargetOpcode::G_VECREDUCE_FMAX: 4432 ScalarOpc = TargetOpcode::G_FMAXNUM; 4433 break; 4434 case TargetOpcode::G_VECREDUCE_FMIN: 4435 ScalarOpc = TargetOpcode::G_FMINNUM; 4436 break; 4437 case TargetOpcode::G_VECREDUCE_ADD: 4438 ScalarOpc = TargetOpcode::G_ADD; 4439 break; 4440 case TargetOpcode::G_VECREDUCE_MUL: 4441 ScalarOpc = TargetOpcode::G_MUL; 4442 break; 4443 case TargetOpcode::G_VECREDUCE_AND: 4444 ScalarOpc = TargetOpcode::G_AND; 4445 break; 4446 case TargetOpcode::G_VECREDUCE_OR: 4447 ScalarOpc = TargetOpcode::G_OR; 4448 break; 4449 case TargetOpcode::G_VECREDUCE_XOR: 4450 ScalarOpc = TargetOpcode::G_XOR; 4451 break; 4452 case TargetOpcode::G_VECREDUCE_SMAX: 4453 ScalarOpc = TargetOpcode::G_SMAX; 4454 break; 4455 case TargetOpcode::G_VECREDUCE_SMIN: 4456 ScalarOpc = TargetOpcode::G_SMIN; 4457 break; 4458 case TargetOpcode::G_VECREDUCE_UMAX: 4459 ScalarOpc = TargetOpcode::G_UMAX; 4460 break; 4461 case TargetOpcode::G_VECREDUCE_UMIN: 4462 ScalarOpc = TargetOpcode::G_UMIN; 4463 break; 4464 default: 4465 llvm_unreachable("Unhandled reduction"); 4466 } 4467 return ScalarOpc; 4468 } 4469 4470 LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorReductions( 4471 MachineInstr &MI, unsigned int TypeIdx, LLT NarrowTy) { 4472 unsigned Opc = MI.getOpcode(); 4473 assert(Opc != TargetOpcode::G_VECREDUCE_SEQ_FADD && 4474 Opc != TargetOpcode::G_VECREDUCE_SEQ_FMUL && 4475 "Sequential reductions not expected"); 4476 4477 if (TypeIdx != 1) 4478 return UnableToLegalize; 4479 4480 // The semantics of the normal non-sequential reductions allow us to freely 4481 // re-associate the operation. 4482 Register SrcReg = MI.getOperand(1).getReg(); 4483 LLT SrcTy = MRI.getType(SrcReg); 4484 Register DstReg = MI.getOperand(0).getReg(); 4485 LLT DstTy = MRI.getType(DstReg); 4486 4487 if (NarrowTy.isVector() && 4488 (SrcTy.getNumElements() % NarrowTy.getNumElements() != 0)) 4489 return UnableToLegalize; 4490 4491 unsigned ScalarOpc = getScalarOpcForReduction(Opc); 4492 SmallVector<Register> SplitSrcs; 4493 // If NarrowTy is a scalar then we're being asked to scalarize. 4494 const unsigned NumParts = 4495 NarrowTy.isVector() ? SrcTy.getNumElements() / NarrowTy.getNumElements() 4496 : SrcTy.getNumElements(); 4497 4498 extractParts(SrcReg, NarrowTy, NumParts, SplitSrcs); 4499 if (NarrowTy.isScalar()) { 4500 if (DstTy != NarrowTy) 4501 return UnableToLegalize; // FIXME: handle implicit extensions. 4502 4503 if (isPowerOf2_32(NumParts)) { 4504 // Generate a tree of scalar operations to reduce the critical path. 4505 SmallVector<Register> PartialResults; 4506 unsigned NumPartsLeft = NumParts; 4507 while (NumPartsLeft > 1) { 4508 for (unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) { 4509 PartialResults.emplace_back( 4510 MIRBuilder 4511 .buildInstr(ScalarOpc, {NarrowTy}, 4512 {SplitSrcs[Idx], SplitSrcs[Idx + 1]}) 4513 .getReg(0)); 4514 } 4515 SplitSrcs = PartialResults; 4516 PartialResults.clear(); 4517 NumPartsLeft = SplitSrcs.size(); 4518 } 4519 assert(SplitSrcs.size() == 1); 4520 MIRBuilder.buildCopy(DstReg, SplitSrcs[0]); 4521 MI.eraseFromParent(); 4522 return Legalized; 4523 } 4524 // If we can't generate a tree, then just do sequential operations. 4525 Register Acc = SplitSrcs[0]; 4526 for (unsigned Idx = 1; Idx < NumParts; ++Idx) 4527 Acc = MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]}) 4528 .getReg(0); 4529 MIRBuilder.buildCopy(DstReg, Acc); 4530 MI.eraseFromParent(); 4531 return Legalized; 4532 } 4533 SmallVector<Register> PartialReductions; 4534 for (unsigned Part = 0; Part < NumParts; ++Part) { 4535 PartialReductions.push_back( 4536 MIRBuilder.buildInstr(Opc, {DstTy}, {SplitSrcs[Part]}).getReg(0)); 4537 } 4538 4539 4540 // If the types involved are powers of 2, we can generate intermediate vector 4541 // ops, before generating a final reduction operation. 4542 if (isPowerOf2_32(SrcTy.getNumElements()) && 4543 isPowerOf2_32(NarrowTy.getNumElements())) { 4544 return tryNarrowPow2Reduction(MI, SrcReg, SrcTy, NarrowTy, ScalarOpc); 4545 } 4546 4547 Register Acc = PartialReductions[0]; 4548 for (unsigned Part = 1; Part < NumParts; ++Part) { 4549 if (Part == NumParts - 1) { 4550 MIRBuilder.buildInstr(ScalarOpc, {DstReg}, 4551 {Acc, PartialReductions[Part]}); 4552 } else { 4553 Acc = MIRBuilder 4554 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]}) 4555 .getReg(0); 4556 } 4557 } 4558 MI.eraseFromParent(); 4559 return Legalized; 4560 } 4561 4562 LegalizerHelper::LegalizeResult 4563 LegalizerHelper::tryNarrowPow2Reduction(MachineInstr &MI, Register SrcReg, 4564 LLT SrcTy, LLT NarrowTy, 4565 unsigned ScalarOpc) { 4566 SmallVector<Register> SplitSrcs; 4567 // Split the sources into NarrowTy size pieces. 4568 extractParts(SrcReg, NarrowTy, 4569 SrcTy.getNumElements() / NarrowTy.getNumElements(), SplitSrcs); 4570 // We're going to do a tree reduction using vector operations until we have 4571 // one NarrowTy size value left. 4572 while (SplitSrcs.size() > 1) { 4573 SmallVector<Register> PartialRdxs; 4574 for (unsigned Idx = 0; Idx < SplitSrcs.size()-1; Idx += 2) { 4575 Register LHS = SplitSrcs[Idx]; 4576 Register RHS = SplitSrcs[Idx + 1]; 4577 // Create the intermediate vector op. 4578 Register Res = 4579 MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {LHS, RHS}).getReg(0); 4580 PartialRdxs.push_back(Res); 4581 } 4582 SplitSrcs = std::move(PartialRdxs); 4583 } 4584 // Finally generate the requested NarrowTy based reduction. 4585 Observer.changingInstr(MI); 4586 MI.getOperand(1).setReg(SplitSrcs[0]); 4587 Observer.changedInstr(MI); 4588 return Legalized; 4589 } 4590 4591 LegalizerHelper::LegalizeResult 4592 LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, 4593 const LLT HalfTy, const LLT AmtTy) { 4594 4595 Register InL = MRI.createGenericVirtualRegister(HalfTy); 4596 Register InH = MRI.createGenericVirtualRegister(HalfTy); 4597 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1)); 4598 4599 if (Amt.isZero()) { 4600 MIRBuilder.buildMerge(MI.getOperand(0), {InL, InH}); 4601 MI.eraseFromParent(); 4602 return Legalized; 4603 } 4604 4605 LLT NVT = HalfTy; 4606 unsigned NVTBits = HalfTy.getSizeInBits(); 4607 unsigned VTBits = 2 * NVTBits; 4608 4609 SrcOp Lo(Register(0)), Hi(Register(0)); 4610 if (MI.getOpcode() == TargetOpcode::G_SHL) { 4611 if (Amt.ugt(VTBits)) { 4612 Lo = Hi = MIRBuilder.buildConstant(NVT, 0); 4613 } else if (Amt.ugt(NVTBits)) { 4614 Lo = MIRBuilder.buildConstant(NVT, 0); 4615 Hi = MIRBuilder.buildShl(NVT, InL, 4616 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits)); 4617 } else if (Amt == NVTBits) { 4618 Lo = MIRBuilder.buildConstant(NVT, 0); 4619 Hi = InL; 4620 } else { 4621 Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt)); 4622 auto OrLHS = 4623 MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt)); 4624 auto OrRHS = MIRBuilder.buildLShr( 4625 NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits)); 4626 Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS); 4627 } 4628 } else if (MI.getOpcode() == TargetOpcode::G_LSHR) { 4629 if (Amt.ugt(VTBits)) { 4630 Lo = Hi = MIRBuilder.buildConstant(NVT, 0); 4631 } else if (Amt.ugt(NVTBits)) { 4632 Lo = MIRBuilder.buildLShr(NVT, InH, 4633 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits)); 4634 Hi = MIRBuilder.buildConstant(NVT, 0); 4635 } else if (Amt == NVTBits) { 4636 Lo = InH; 4637 Hi = MIRBuilder.buildConstant(NVT, 0); 4638 } else { 4639 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt); 4640 4641 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst); 4642 auto OrRHS = MIRBuilder.buildShl( 4643 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits)); 4644 4645 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS); 4646 Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst); 4647 } 4648 } else { 4649 if (Amt.ugt(VTBits)) { 4650 Hi = Lo = MIRBuilder.buildAShr( 4651 NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1)); 4652 } else if (Amt.ugt(NVTBits)) { 4653 Lo = MIRBuilder.buildAShr(NVT, InH, 4654 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits)); 4655 Hi = MIRBuilder.buildAShr(NVT, InH, 4656 MIRBuilder.buildConstant(AmtTy, NVTBits - 1)); 4657 } else if (Amt == NVTBits) { 4658 Lo = InH; 4659 Hi = MIRBuilder.buildAShr(NVT, InH, 4660 MIRBuilder.buildConstant(AmtTy, NVTBits - 1)); 4661 } else { 4662 auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt); 4663 4664 auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst); 4665 auto OrRHS = MIRBuilder.buildShl( 4666 NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits)); 4667 4668 Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS); 4669 Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst); 4670 } 4671 } 4672 4673 MIRBuilder.buildMerge(MI.getOperand(0), {Lo, Hi}); 4674 MI.eraseFromParent(); 4675 4676 return Legalized; 4677 } 4678 4679 // TODO: Optimize if constant shift amount. 4680 LegalizerHelper::LegalizeResult 4681 LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, 4682 LLT RequestedTy) { 4683 if (TypeIdx == 1) { 4684 Observer.changingInstr(MI); 4685 narrowScalarSrc(MI, RequestedTy, 2); 4686 Observer.changedInstr(MI); 4687 return Legalized; 4688 } 4689 4690 Register DstReg = MI.getOperand(0).getReg(); 4691 LLT DstTy = MRI.getType(DstReg); 4692 if (DstTy.isVector()) 4693 return UnableToLegalize; 4694 4695 Register Amt = MI.getOperand(2).getReg(); 4696 LLT ShiftAmtTy = MRI.getType(Amt); 4697 const unsigned DstEltSize = DstTy.getScalarSizeInBits(); 4698 if (DstEltSize % 2 != 0) 4699 return UnableToLegalize; 4700 4701 // Ignore the input type. We can only go to exactly half the size of the 4702 // input. If that isn't small enough, the resulting pieces will be further 4703 // legalized. 4704 const unsigned NewBitSize = DstEltSize / 2; 4705 const LLT HalfTy = LLT::scalar(NewBitSize); 4706 const LLT CondTy = LLT::scalar(1); 4707 4708 if (auto VRegAndVal = getIConstantVRegValWithLookThrough(Amt, MRI)) { 4709 return narrowScalarShiftByConstant(MI, VRegAndVal->Value, HalfTy, 4710 ShiftAmtTy); 4711 } 4712 4713 // TODO: Expand with known bits. 4714 4715 // Handle the fully general expansion by an unknown amount. 4716 auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize); 4717 4718 Register InL = MRI.createGenericVirtualRegister(HalfTy); 4719 Register InH = MRI.createGenericVirtualRegister(HalfTy); 4720 MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1)); 4721 4722 auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits); 4723 auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt); 4724 4725 auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0); 4726 auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits); 4727 auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero); 4728 4729 Register ResultRegs[2]; 4730 switch (MI.getOpcode()) { 4731 case TargetOpcode::G_SHL: { 4732 // Short: ShAmt < NewBitSize 4733 auto LoS = MIRBuilder.buildShl(HalfTy, InL, Amt); 4734 4735 auto LoOr = MIRBuilder.buildLShr(HalfTy, InL, AmtLack); 4736 auto HiOr = MIRBuilder.buildShl(HalfTy, InH, Amt); 4737 auto HiS = MIRBuilder.buildOr(HalfTy, LoOr, HiOr); 4738 4739 // Long: ShAmt >= NewBitSize 4740 auto LoL = MIRBuilder.buildConstant(HalfTy, 0); // Lo part is zero. 4741 auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part. 4742 4743 auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL); 4744 auto Hi = MIRBuilder.buildSelect( 4745 HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL)); 4746 4747 ResultRegs[0] = Lo.getReg(0); 4748 ResultRegs[1] = Hi.getReg(0); 4749 break; 4750 } 4751 case TargetOpcode::G_LSHR: 4752 case TargetOpcode::G_ASHR: { 4753 // Short: ShAmt < NewBitSize 4754 auto HiS = MIRBuilder.buildInstr(MI.getOpcode(), {HalfTy}, {InH, Amt}); 4755 4756 auto LoOr = MIRBuilder.buildLShr(HalfTy, InL, Amt); 4757 auto HiOr = MIRBuilder.buildShl(HalfTy, InH, AmtLack); 4758 auto LoS = MIRBuilder.buildOr(HalfTy, LoOr, HiOr); 4759 4760 // Long: ShAmt >= NewBitSize 4761 MachineInstrBuilder HiL; 4762 if (MI.getOpcode() == TargetOpcode::G_LSHR) { 4763 HiL = MIRBuilder.buildConstant(HalfTy, 0); // Hi part is zero. 4764 } else { 4765 auto ShiftAmt = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1); 4766 HiL = MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt); // Sign of Hi part. 4767 } 4768 auto LoL = MIRBuilder.buildInstr(MI.getOpcode(), {HalfTy}, 4769 {InH, AmtExcess}); // Lo from Hi part. 4770 4771 auto Lo = MIRBuilder.buildSelect( 4772 HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL)); 4773 4774 auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL); 4775 4776 ResultRegs[0] = Lo.getReg(0); 4777 ResultRegs[1] = Hi.getReg(0); 4778 break; 4779 } 4780 default: 4781 llvm_unreachable("not a shift"); 4782 } 4783 4784 MIRBuilder.buildMerge(DstReg, ResultRegs); 4785 MI.eraseFromParent(); 4786 return Legalized; 4787 } 4788 4789 LegalizerHelper::LegalizeResult 4790 LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, 4791 LLT MoreTy) { 4792 assert(TypeIdx == 0 && "Expecting only Idx 0"); 4793 4794 Observer.changingInstr(MI); 4795 for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) { 4796 MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB(); 4797 MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator()); 4798 moreElementsVectorSrc(MI, MoreTy, I); 4799 } 4800 4801 MachineBasicBlock &MBB = *MI.getParent(); 4802 MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI()); 4803 moreElementsVectorDst(MI, MoreTy, 0); 4804 Observer.changedInstr(MI); 4805 return Legalized; 4806 } 4807 4808 LegalizerHelper::LegalizeResult 4809 LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, 4810 LLT MoreTy) { 4811 unsigned Opc = MI.getOpcode(); 4812 switch (Opc) { 4813 case TargetOpcode::G_IMPLICIT_DEF: 4814 case TargetOpcode::G_LOAD: { 4815 if (TypeIdx != 0) 4816 return UnableToLegalize; 4817 Observer.changingInstr(MI); 4818 moreElementsVectorDst(MI, MoreTy, 0); 4819 Observer.changedInstr(MI); 4820 return Legalized; 4821 } 4822 case TargetOpcode::G_STORE: 4823 if (TypeIdx != 0) 4824 return UnableToLegalize; 4825 Observer.changingInstr(MI); 4826 moreElementsVectorSrc(MI, MoreTy, 0); 4827 Observer.changedInstr(MI); 4828 return Legalized; 4829 case TargetOpcode::G_AND: 4830 case TargetOpcode::G_OR: 4831 case TargetOpcode::G_XOR: 4832 case TargetOpcode::G_ADD: 4833 case TargetOpcode::G_SUB: 4834 case TargetOpcode::G_MUL: 4835 case TargetOpcode::G_FADD: 4836 case TargetOpcode::G_FMUL: 4837 case TargetOpcode::G_UADDSAT: 4838 case TargetOpcode::G_USUBSAT: 4839 case TargetOpcode::G_SADDSAT: 4840 case TargetOpcode::G_SSUBSAT: 4841 case TargetOpcode::G_SMIN: 4842 case TargetOpcode::G_SMAX: 4843 case TargetOpcode::G_UMIN: 4844 case TargetOpcode::G_UMAX: 4845 case TargetOpcode::G_FMINNUM: 4846 case TargetOpcode::G_FMAXNUM: 4847 case TargetOpcode::G_FMINNUM_IEEE: 4848 case TargetOpcode::G_FMAXNUM_IEEE: 4849 case TargetOpcode::G_FMINIMUM: 4850 case TargetOpcode::G_FMAXIMUM: { 4851 Observer.changingInstr(MI); 4852 moreElementsVectorSrc(MI, MoreTy, 1); 4853 moreElementsVectorSrc(MI, MoreTy, 2); 4854 moreElementsVectorDst(MI, MoreTy, 0); 4855 Observer.changedInstr(MI); 4856 return Legalized; 4857 } 4858 case TargetOpcode::G_FMA: 4859 case TargetOpcode::G_FSHR: 4860 case TargetOpcode::G_FSHL: { 4861 Observer.changingInstr(MI); 4862 moreElementsVectorSrc(MI, MoreTy, 1); 4863 moreElementsVectorSrc(MI, MoreTy, 2); 4864 moreElementsVectorSrc(MI, MoreTy, 3); 4865 moreElementsVectorDst(MI, MoreTy, 0); 4866 Observer.changedInstr(MI); 4867 return Legalized; 4868 } 4869 case TargetOpcode::G_EXTRACT: 4870 if (TypeIdx != 1) 4871 return UnableToLegalize; 4872 Observer.changingInstr(MI); 4873 moreElementsVectorSrc(MI, MoreTy, 1); 4874 Observer.changedInstr(MI); 4875 return Legalized; 4876 case TargetOpcode::G_INSERT: 4877 case TargetOpcode::G_FREEZE: 4878 case TargetOpcode::G_FNEG: 4879 case TargetOpcode::G_FABS: 4880 case TargetOpcode::G_BSWAP: 4881 case TargetOpcode::G_FCANONICALIZE: 4882 case TargetOpcode::G_SEXT_INREG: 4883 if (TypeIdx != 0) 4884 return UnableToLegalize; 4885 Observer.changingInstr(MI); 4886 moreElementsVectorSrc(MI, MoreTy, 1); 4887 moreElementsVectorDst(MI, MoreTy, 0); 4888 Observer.changedInstr(MI); 4889 return Legalized; 4890 case TargetOpcode::G_SELECT: 4891 if (TypeIdx != 0) 4892 return UnableToLegalize; 4893 if (MRI.getType(MI.getOperand(1).getReg()).isVector()) 4894 return UnableToLegalize; 4895 4896 Observer.changingInstr(MI); 4897 moreElementsVectorSrc(MI, MoreTy, 2); 4898 moreElementsVectorSrc(MI, MoreTy, 3); 4899 moreElementsVectorDst(MI, MoreTy, 0); 4900 Observer.changedInstr(MI); 4901 return Legalized; 4902 case TargetOpcode::G_UNMERGE_VALUES: 4903 return UnableToLegalize; 4904 case TargetOpcode::G_PHI: 4905 return moreElementsVectorPhi(MI, TypeIdx, MoreTy); 4906 case TargetOpcode::G_SHUFFLE_VECTOR: 4907 return moreElementsVectorShuffle(MI, TypeIdx, MoreTy); 4908 case TargetOpcode::G_BUILD_VECTOR: { 4909 SmallVector<SrcOp, 8> Elts; 4910 for (auto Op : MI.uses()) { 4911 Elts.push_back(Op.getReg()); 4912 } 4913 4914 for (unsigned i = Elts.size(); i < MoreTy.getNumElements(); ++i) { 4915 Elts.push_back(MIRBuilder.buildUndef(MoreTy.getScalarType())); 4916 } 4917 4918 MIRBuilder.buildDeleteTrailingVectorElements( 4919 MI.getOperand(0).getReg(), MIRBuilder.buildInstr(Opc, {MoreTy}, Elts)); 4920 MI.eraseFromParent(); 4921 return Legalized; 4922 } 4923 case TargetOpcode::G_TRUNC: { 4924 Observer.changingInstr(MI); 4925 moreElementsVectorSrc(MI, MoreTy, 1); 4926 moreElementsVectorDst(MI, MoreTy, 0); 4927 Observer.changedInstr(MI); 4928 return Legalized; 4929 } 4930 default: 4931 return UnableToLegalize; 4932 } 4933 } 4934 4935 LegalizerHelper::LegalizeResult 4936 LegalizerHelper::moreElementsVectorShuffle(MachineInstr &MI, 4937 unsigned int TypeIdx, LLT MoreTy) { 4938 if (TypeIdx != 0) 4939 return UnableToLegalize; 4940 4941 Register DstReg = MI.getOperand(0).getReg(); 4942 Register Src1Reg = MI.getOperand(1).getReg(); 4943 Register Src2Reg = MI.getOperand(2).getReg(); 4944 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask(); 4945 LLT DstTy = MRI.getType(DstReg); 4946 LLT Src1Ty = MRI.getType(Src1Reg); 4947 LLT Src2Ty = MRI.getType(Src2Reg); 4948 unsigned NumElts = DstTy.getNumElements(); 4949 unsigned WidenNumElts = MoreTy.getNumElements(); 4950 4951 // Expect a canonicalized shuffle. 4952 if (DstTy != Src1Ty || DstTy != Src2Ty) 4953 return UnableToLegalize; 4954 4955 moreElementsVectorSrc(MI, MoreTy, 1); 4956 moreElementsVectorSrc(MI, MoreTy, 2); 4957 4958 // Adjust mask based on new input vector length. 4959 SmallVector<int, 16> NewMask; 4960 for (unsigned I = 0; I != NumElts; ++I) { 4961 int Idx = Mask[I]; 4962 if (Idx < static_cast<int>(NumElts)) 4963 NewMask.push_back(Idx); 4964 else 4965 NewMask.push_back(Idx - NumElts + WidenNumElts); 4966 } 4967 for (unsigned I = NumElts; I != WidenNumElts; ++I) 4968 NewMask.push_back(-1); 4969 moreElementsVectorDst(MI, MoreTy, 0); 4970 MIRBuilder.setInstrAndDebugLoc(MI); 4971 MIRBuilder.buildShuffleVector(MI.getOperand(0).getReg(), 4972 MI.getOperand(1).getReg(), 4973 MI.getOperand(2).getReg(), NewMask); 4974 MI.eraseFromParent(); 4975 return Legalized; 4976 } 4977 4978 void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs, 4979 ArrayRef<Register> Src1Regs, 4980 ArrayRef<Register> Src2Regs, 4981 LLT NarrowTy) { 4982 MachineIRBuilder &B = MIRBuilder; 4983 unsigned SrcParts = Src1Regs.size(); 4984 unsigned DstParts = DstRegs.size(); 4985 4986 unsigned DstIdx = 0; // Low bits of the result. 4987 Register FactorSum = 4988 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0); 4989 DstRegs[DstIdx] = FactorSum; 4990 4991 unsigned CarrySumPrevDstIdx; 4992 SmallVector<Register, 4> Factors; 4993 4994 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) { 4995 // Collect low parts of muls for DstIdx. 4996 for (unsigned i = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1; 4997 i <= std::min(DstIdx, SrcParts - 1); ++i) { 4998 MachineInstrBuilder Mul = 4999 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]); 5000 Factors.push_back(Mul.getReg(0)); 5001 } 5002 // Collect high parts of muls from previous DstIdx. 5003 for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts; 5004 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) { 5005 MachineInstrBuilder Umulh = 5006 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]); 5007 Factors.push_back(Umulh.getReg(0)); 5008 } 5009 // Add CarrySum from additions calculated for previous DstIdx. 5010 if (DstIdx != 1) { 5011 Factors.push_back(CarrySumPrevDstIdx); 5012 } 5013 5014 Register CarrySum; 5015 // Add all factors and accumulate all carries into CarrySum. 5016 if (DstIdx != DstParts - 1) { 5017 MachineInstrBuilder Uaddo = 5018 B.buildUAddo(NarrowTy, LLT::scalar(1), Factors[0], Factors[1]); 5019 FactorSum = Uaddo.getReg(0); 5020 CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0); 5021 for (unsigned i = 2; i < Factors.size(); ++i) { 5022 MachineInstrBuilder Uaddo = 5023 B.buildUAddo(NarrowTy, LLT::scalar(1), FactorSum, Factors[i]); 5024 FactorSum = Uaddo.getReg(0); 5025 MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1)); 5026 CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0); 5027 } 5028 } else { 5029 // Since value for the next index is not calculated, neither is CarrySum. 5030 FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0); 5031 for (unsigned i = 2; i < Factors.size(); ++i) 5032 FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0); 5033 } 5034 5035 CarrySumPrevDstIdx = CarrySum; 5036 DstRegs[DstIdx] = FactorSum; 5037 Factors.clear(); 5038 } 5039 } 5040 5041 LegalizerHelper::LegalizeResult 5042 LegalizerHelper::narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, 5043 LLT NarrowTy) { 5044 if (TypeIdx != 0) 5045 return UnableToLegalize; 5046 5047 Register DstReg = MI.getOperand(0).getReg(); 5048 LLT DstType = MRI.getType(DstReg); 5049 // FIXME: add support for vector types 5050 if (DstType.isVector()) 5051 return UnableToLegalize; 5052 5053 unsigned Opcode = MI.getOpcode(); 5054 unsigned OpO, OpE, OpF; 5055 switch (Opcode) { 5056 case TargetOpcode::G_SADDO: 5057 case TargetOpcode::G_SADDE: 5058 case TargetOpcode::G_UADDO: 5059 case TargetOpcode::G_UADDE: 5060 case TargetOpcode::G_ADD: 5061 OpO = TargetOpcode::G_UADDO; 5062 OpE = TargetOpcode::G_UADDE; 5063 OpF = TargetOpcode::G_UADDE; 5064 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE) 5065 OpF = TargetOpcode::G_SADDE; 5066 break; 5067 case TargetOpcode::G_SSUBO: 5068 case TargetOpcode::G_SSUBE: 5069 case TargetOpcode::G_USUBO: 5070 case TargetOpcode::G_USUBE: 5071 case TargetOpcode::G_SUB: 5072 OpO = TargetOpcode::G_USUBO; 5073 OpE = TargetOpcode::G_USUBE; 5074 OpF = TargetOpcode::G_USUBE; 5075 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE) 5076 OpF = TargetOpcode::G_SSUBE; 5077 break; 5078 default: 5079 llvm_unreachable("Unexpected add/sub opcode!"); 5080 } 5081 5082 // 1 for a plain add/sub, 2 if this is an operation with a carry-out. 5083 unsigned NumDefs = MI.getNumExplicitDefs(); 5084 Register Src1 = MI.getOperand(NumDefs).getReg(); 5085 Register Src2 = MI.getOperand(NumDefs + 1).getReg(); 5086 Register CarryDst, CarryIn; 5087 if (NumDefs == 2) 5088 CarryDst = MI.getOperand(1).getReg(); 5089 if (MI.getNumOperands() == NumDefs + 3) 5090 CarryIn = MI.getOperand(NumDefs + 2).getReg(); 5091 5092 LLT RegTy = MRI.getType(MI.getOperand(0).getReg()); 5093 LLT LeftoverTy, DummyTy; 5094 SmallVector<Register, 2> Src1Regs, Src2Regs, Src1Left, Src2Left, DstRegs; 5095 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left); 5096 extractParts(Src2, RegTy, NarrowTy, DummyTy, Src2Regs, Src2Left); 5097 5098 int NarrowParts = Src1Regs.size(); 5099 for (int I = 0, E = Src1Left.size(); I != E; ++I) { 5100 Src1Regs.push_back(Src1Left[I]); 5101 Src2Regs.push_back(Src2Left[I]); 5102 } 5103 DstRegs.reserve(Src1Regs.size()); 5104 5105 for (int i = 0, e = Src1Regs.size(); i != e; ++i) { 5106 Register DstReg = 5107 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i])); 5108 Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); 5109 // Forward the final carry-out to the destination register 5110 if (i == e - 1 && CarryDst) 5111 CarryOut = CarryDst; 5112 5113 if (!CarryIn) { 5114 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut}, 5115 {Src1Regs[i], Src2Regs[i]}); 5116 } else if (i == e - 1) { 5117 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut}, 5118 {Src1Regs[i], Src2Regs[i], CarryIn}); 5119 } else { 5120 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut}, 5121 {Src1Regs[i], Src2Regs[i], CarryIn}); 5122 } 5123 5124 DstRegs.push_back(DstReg); 5125 CarryIn = CarryOut; 5126 } 5127 insertParts(MI.getOperand(0).getReg(), RegTy, NarrowTy, 5128 makeArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy, 5129 makeArrayRef(DstRegs).drop_front(NarrowParts)); 5130 5131 MI.eraseFromParent(); 5132 return Legalized; 5133 } 5134 5135 LegalizerHelper::LegalizeResult 5136 LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) { 5137 Register DstReg = MI.getOperand(0).getReg(); 5138 Register Src1 = MI.getOperand(1).getReg(); 5139 Register Src2 = MI.getOperand(2).getReg(); 5140 5141 LLT Ty = MRI.getType(DstReg); 5142 if (Ty.isVector()) 5143 return UnableToLegalize; 5144 5145 unsigned Size = Ty.getSizeInBits(); 5146 unsigned NarrowSize = NarrowTy.getSizeInBits(); 5147 if (Size % NarrowSize != 0) 5148 return UnableToLegalize; 5149 5150 unsigned NumParts = Size / NarrowSize; 5151 bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH; 5152 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1); 5153 5154 SmallVector<Register, 2> Src1Parts, Src2Parts; 5155 SmallVector<Register, 2> DstTmpRegs(DstTmpParts); 5156 extractParts(Src1, NarrowTy, NumParts, Src1Parts); 5157 extractParts(Src2, NarrowTy, NumParts, Src2Parts); 5158 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy); 5159 5160 // Take only high half of registers if this is high mul. 5161 ArrayRef<Register> DstRegs(&DstTmpRegs[DstTmpParts - NumParts], NumParts); 5162 MIRBuilder.buildMerge(DstReg, DstRegs); 5163 MI.eraseFromParent(); 5164 return Legalized; 5165 } 5166 5167 LegalizerHelper::LegalizeResult 5168 LegalizerHelper::narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, 5169 LLT NarrowTy) { 5170 if (TypeIdx != 0) 5171 return UnableToLegalize; 5172 5173 bool IsSigned = MI.getOpcode() == TargetOpcode::G_FPTOSI; 5174 5175 Register Src = MI.getOperand(1).getReg(); 5176 LLT SrcTy = MRI.getType(Src); 5177 5178 // If all finite floats fit into the narrowed integer type, we can just swap 5179 // out the result type. This is practically only useful for conversions from 5180 // half to at least 16-bits, so just handle the one case. 5181 if (SrcTy.getScalarType() != LLT::scalar(16) || 5182 NarrowTy.getScalarSizeInBits() < (IsSigned ? 17u : 16u)) 5183 return UnableToLegalize; 5184 5185 Observer.changingInstr(MI); 5186 narrowScalarDst(MI, NarrowTy, 0, 5187 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT); 5188 Observer.changedInstr(MI); 5189 return Legalized; 5190 } 5191 5192 LegalizerHelper::LegalizeResult 5193 LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, 5194 LLT NarrowTy) { 5195 if (TypeIdx != 1) 5196 return UnableToLegalize; 5197 5198 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 5199 5200 int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 5201 // FIXME: add support for when SizeOp1 isn't an exact multiple of 5202 // NarrowSize. 5203 if (SizeOp1 % NarrowSize != 0) 5204 return UnableToLegalize; 5205 int NumParts = SizeOp1 / NarrowSize; 5206 5207 SmallVector<Register, 2> SrcRegs, DstRegs; 5208 SmallVector<uint64_t, 2> Indexes; 5209 extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs); 5210 5211 Register OpReg = MI.getOperand(0).getReg(); 5212 uint64_t OpStart = MI.getOperand(2).getImm(); 5213 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 5214 for (int i = 0; i < NumParts; ++i) { 5215 unsigned SrcStart = i * NarrowSize; 5216 5217 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) { 5218 // No part of the extract uses this subregister, ignore it. 5219 continue; 5220 } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 5221 // The entire subregister is extracted, forward the value. 5222 DstRegs.push_back(SrcRegs[i]); 5223 continue; 5224 } 5225 5226 // OpSegStart is where this destination segment would start in OpReg if it 5227 // extended infinitely in both directions. 5228 int64_t ExtractOffset; 5229 uint64_t SegSize; 5230 if (OpStart < SrcStart) { 5231 ExtractOffset = 0; 5232 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart); 5233 } else { 5234 ExtractOffset = OpStart - SrcStart; 5235 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize); 5236 } 5237 5238 Register SegReg = SrcRegs[i]; 5239 if (ExtractOffset != 0 || SegSize != NarrowSize) { 5240 // A genuine extract is needed. 5241 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 5242 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset); 5243 } 5244 5245 DstRegs.push_back(SegReg); 5246 } 5247 5248 Register DstReg = MI.getOperand(0).getReg(); 5249 if (MRI.getType(DstReg).isVector()) 5250 MIRBuilder.buildBuildVector(DstReg, DstRegs); 5251 else if (DstRegs.size() > 1) 5252 MIRBuilder.buildMerge(DstReg, DstRegs); 5253 else 5254 MIRBuilder.buildCopy(DstReg, DstRegs[0]); 5255 MI.eraseFromParent(); 5256 return Legalized; 5257 } 5258 5259 LegalizerHelper::LegalizeResult 5260 LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, 5261 LLT NarrowTy) { 5262 // FIXME: Don't know how to handle secondary types yet. 5263 if (TypeIdx != 0) 5264 return UnableToLegalize; 5265 5266 SmallVector<Register, 2> SrcRegs, LeftoverRegs, DstRegs; 5267 SmallVector<uint64_t, 2> Indexes; 5268 LLT RegTy = MRI.getType(MI.getOperand(0).getReg()); 5269 LLT LeftoverTy; 5270 extractParts(MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs, 5271 LeftoverRegs); 5272 5273 for (Register Reg : LeftoverRegs) 5274 SrcRegs.push_back(Reg); 5275 5276 uint64_t NarrowSize = NarrowTy.getSizeInBits(); 5277 Register OpReg = MI.getOperand(2).getReg(); 5278 uint64_t OpStart = MI.getOperand(3).getImm(); 5279 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits(); 5280 for (int I = 0, E = SrcRegs.size(); I != E; ++I) { 5281 unsigned DstStart = I * NarrowSize; 5282 5283 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) { 5284 // The entire subregister is defined by this insert, forward the new 5285 // value. 5286 DstRegs.push_back(OpReg); 5287 continue; 5288 } 5289 5290 Register SrcReg = SrcRegs[I]; 5291 if (MRI.getType(SrcRegs[I]) == LeftoverTy) { 5292 // The leftover reg is smaller than NarrowTy, so we need to extend it. 5293 SrcReg = MRI.createGenericVirtualRegister(NarrowTy); 5294 MIRBuilder.buildAnyExt(SrcReg, SrcRegs[I]); 5295 } 5296 5297 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) { 5298 // No part of the insert affects this subregister, forward the original. 5299 DstRegs.push_back(SrcReg); 5300 continue; 5301 } 5302 5303 // OpSegStart is where this destination segment would start in OpReg if it 5304 // extended infinitely in both directions. 5305 int64_t ExtractOffset, InsertOffset; 5306 uint64_t SegSize; 5307 if (OpStart < DstStart) { 5308 InsertOffset = 0; 5309 ExtractOffset = DstStart - OpStart; 5310 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart); 5311 } else { 5312 InsertOffset = OpStart - DstStart; 5313 ExtractOffset = 0; 5314 SegSize = 5315 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart); 5316 } 5317 5318 Register SegReg = OpReg; 5319 if (ExtractOffset != 0 || SegSize != OpSize) { 5320 // A genuine extract is needed. 5321 SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize)); 5322 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset); 5323 } 5324 5325 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); 5326 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset); 5327 DstRegs.push_back(DstReg); 5328 } 5329 5330 uint64_t WideSize = DstRegs.size() * NarrowSize; 5331 Register DstReg = MI.getOperand(0).getReg(); 5332 if (WideSize > RegTy.getSizeInBits()) { 5333 Register MergeReg = MRI.createGenericVirtualRegister(LLT::scalar(WideSize)); 5334 MIRBuilder.buildMerge(MergeReg, DstRegs); 5335 MIRBuilder.buildTrunc(DstReg, MergeReg); 5336 } else 5337 MIRBuilder.buildMerge(DstReg, DstRegs); 5338 5339 MI.eraseFromParent(); 5340 return Legalized; 5341 } 5342 5343 LegalizerHelper::LegalizeResult 5344 LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, 5345 LLT NarrowTy) { 5346 Register DstReg = MI.getOperand(0).getReg(); 5347 LLT DstTy = MRI.getType(DstReg); 5348 5349 assert(MI.getNumOperands() == 3 && TypeIdx == 0); 5350 5351 SmallVector<Register, 4> DstRegs, DstLeftoverRegs; 5352 SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs; 5353 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs; 5354 LLT LeftoverTy; 5355 if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy, 5356 Src0Regs, Src0LeftoverRegs)) 5357 return UnableToLegalize; 5358 5359 LLT Unused; 5360 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused, 5361 Src1Regs, Src1LeftoverRegs)) 5362 llvm_unreachable("inconsistent extractParts result"); 5363 5364 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) { 5365 auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy}, 5366 {Src0Regs[I], Src1Regs[I]}); 5367 DstRegs.push_back(Inst.getReg(0)); 5368 } 5369 5370 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) { 5371 auto Inst = MIRBuilder.buildInstr( 5372 MI.getOpcode(), 5373 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]}); 5374 DstLeftoverRegs.push_back(Inst.getReg(0)); 5375 } 5376 5377 insertParts(DstReg, DstTy, NarrowTy, DstRegs, 5378 LeftoverTy, DstLeftoverRegs); 5379 5380 MI.eraseFromParent(); 5381 return Legalized; 5382 } 5383 5384 LegalizerHelper::LegalizeResult 5385 LegalizerHelper::narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, 5386 LLT NarrowTy) { 5387 if (TypeIdx != 0) 5388 return UnableToLegalize; 5389 5390 Register DstReg = MI.getOperand(0).getReg(); 5391 Register SrcReg = MI.getOperand(1).getReg(); 5392 5393 LLT DstTy = MRI.getType(DstReg); 5394 if (DstTy.isVector()) 5395 return UnableToLegalize; 5396 5397 SmallVector<Register, 8> Parts; 5398 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg); 5399 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts, MI.getOpcode()); 5400 buildWidenedRemergeToDst(DstReg, LCMTy, Parts); 5401 5402 MI.eraseFromParent(); 5403 return Legalized; 5404 } 5405 5406 LegalizerHelper::LegalizeResult 5407 LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, 5408 LLT NarrowTy) { 5409 if (TypeIdx != 0) 5410 return UnableToLegalize; 5411 5412 Register CondReg = MI.getOperand(1).getReg(); 5413 LLT CondTy = MRI.getType(CondReg); 5414 if (CondTy.isVector()) // TODO: Handle vselect 5415 return UnableToLegalize; 5416 5417 Register DstReg = MI.getOperand(0).getReg(); 5418 LLT DstTy = MRI.getType(DstReg); 5419 5420 SmallVector<Register, 4> DstRegs, DstLeftoverRegs; 5421 SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs; 5422 SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs; 5423 LLT LeftoverTy; 5424 if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy, 5425 Src1Regs, Src1LeftoverRegs)) 5426 return UnableToLegalize; 5427 5428 LLT Unused; 5429 if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused, 5430 Src2Regs, Src2LeftoverRegs)) 5431 llvm_unreachable("inconsistent extractParts result"); 5432 5433 for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) { 5434 auto Select = MIRBuilder.buildSelect(NarrowTy, 5435 CondReg, Src1Regs[I], Src2Regs[I]); 5436 DstRegs.push_back(Select.getReg(0)); 5437 } 5438 5439 for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) { 5440 auto Select = MIRBuilder.buildSelect( 5441 LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]); 5442 DstLeftoverRegs.push_back(Select.getReg(0)); 5443 } 5444 5445 insertParts(DstReg, DstTy, NarrowTy, DstRegs, 5446 LeftoverTy, DstLeftoverRegs); 5447 5448 MI.eraseFromParent(); 5449 return Legalized; 5450 } 5451 5452 LegalizerHelper::LegalizeResult 5453 LegalizerHelper::narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, 5454 LLT NarrowTy) { 5455 if (TypeIdx != 1) 5456 return UnableToLegalize; 5457 5458 Register DstReg = MI.getOperand(0).getReg(); 5459 Register SrcReg = MI.getOperand(1).getReg(); 5460 LLT DstTy = MRI.getType(DstReg); 5461 LLT SrcTy = MRI.getType(SrcReg); 5462 unsigned NarrowSize = NarrowTy.getSizeInBits(); 5463 5464 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) { 5465 const bool IsUndef = MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_UNDEF; 5466 5467 MachineIRBuilder &B = MIRBuilder; 5468 auto UnmergeSrc = B.buildUnmerge(NarrowTy, SrcReg); 5469 // ctlz(Hi:Lo) -> Hi == 0 ? (NarrowSize + ctlz(Lo)) : ctlz(Hi) 5470 auto C_0 = B.buildConstant(NarrowTy, 0); 5471 auto HiIsZero = B.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), 5472 UnmergeSrc.getReg(1), C_0); 5473 auto LoCTLZ = IsUndef ? 5474 B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)) : 5475 B.buildCTLZ(DstTy, UnmergeSrc.getReg(0)); 5476 auto C_NarrowSize = B.buildConstant(DstTy, NarrowSize); 5477 auto HiIsZeroCTLZ = B.buildAdd(DstTy, LoCTLZ, C_NarrowSize); 5478 auto HiCTLZ = B.buildCTLZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)); 5479 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ); 5480 5481 MI.eraseFromParent(); 5482 return Legalized; 5483 } 5484 5485 return UnableToLegalize; 5486 } 5487 5488 LegalizerHelper::LegalizeResult 5489 LegalizerHelper::narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, 5490 LLT NarrowTy) { 5491 if (TypeIdx != 1) 5492 return UnableToLegalize; 5493 5494 Register DstReg = MI.getOperand(0).getReg(); 5495 Register SrcReg = MI.getOperand(1).getReg(); 5496 LLT DstTy = MRI.getType(DstReg); 5497 LLT SrcTy = MRI.getType(SrcReg); 5498 unsigned NarrowSize = NarrowTy.getSizeInBits(); 5499 5500 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) { 5501 const bool IsUndef = MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_UNDEF; 5502 5503 MachineIRBuilder &B = MIRBuilder; 5504 auto UnmergeSrc = B.buildUnmerge(NarrowTy, SrcReg); 5505 // cttz(Hi:Lo) -> Lo == 0 ? (cttz(Hi) + NarrowSize) : cttz(Lo) 5506 auto C_0 = B.buildConstant(NarrowTy, 0); 5507 auto LoIsZero = B.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), 5508 UnmergeSrc.getReg(0), C_0); 5509 auto HiCTTZ = IsUndef ? 5510 B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(1)) : 5511 B.buildCTTZ(DstTy, UnmergeSrc.getReg(1)); 5512 auto C_NarrowSize = B.buildConstant(DstTy, NarrowSize); 5513 auto LoIsZeroCTTZ = B.buildAdd(DstTy, HiCTTZ, C_NarrowSize); 5514 auto LoCTTZ = B.buildCTTZ_ZERO_UNDEF(DstTy, UnmergeSrc.getReg(0)); 5515 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ); 5516 5517 MI.eraseFromParent(); 5518 return Legalized; 5519 } 5520 5521 return UnableToLegalize; 5522 } 5523 5524 LegalizerHelper::LegalizeResult 5525 LegalizerHelper::narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, 5526 LLT NarrowTy) { 5527 if (TypeIdx != 1) 5528 return UnableToLegalize; 5529 5530 Register DstReg = MI.getOperand(0).getReg(); 5531 LLT DstTy = MRI.getType(DstReg); 5532 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 5533 unsigned NarrowSize = NarrowTy.getSizeInBits(); 5534 5535 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) { 5536 auto UnmergeSrc = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1)); 5537 5538 auto LoCTPOP = MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0)); 5539 auto HiCTPOP = MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1)); 5540 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP); 5541 5542 MI.eraseFromParent(); 5543 return Legalized; 5544 } 5545 5546 return UnableToLegalize; 5547 } 5548 5549 LegalizerHelper::LegalizeResult 5550 LegalizerHelper::lowerBitCount(MachineInstr &MI) { 5551 unsigned Opc = MI.getOpcode(); 5552 const auto &TII = MIRBuilder.getTII(); 5553 auto isSupported = [this](const LegalityQuery &Q) { 5554 auto QAction = LI.getAction(Q).Action; 5555 return QAction == Legal || QAction == Libcall || QAction == Custom; 5556 }; 5557 switch (Opc) { 5558 default: 5559 return UnableToLegalize; 5560 case TargetOpcode::G_CTLZ_ZERO_UNDEF: { 5561 // This trivially expands to CTLZ. 5562 Observer.changingInstr(MI); 5563 MI.setDesc(TII.get(TargetOpcode::G_CTLZ)); 5564 Observer.changedInstr(MI); 5565 return Legalized; 5566 } 5567 case TargetOpcode::G_CTLZ: { 5568 Register DstReg = MI.getOperand(0).getReg(); 5569 Register SrcReg = MI.getOperand(1).getReg(); 5570 LLT DstTy = MRI.getType(DstReg); 5571 LLT SrcTy = MRI.getType(SrcReg); 5572 unsigned Len = SrcTy.getSizeInBits(); 5573 5574 if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) { 5575 // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero. 5576 auto CtlzZU = MIRBuilder.buildCTLZ_ZERO_UNDEF(DstTy, SrcReg); 5577 auto ZeroSrc = MIRBuilder.buildConstant(SrcTy, 0); 5578 auto ICmp = MIRBuilder.buildICmp( 5579 CmpInst::ICMP_EQ, SrcTy.changeElementSize(1), SrcReg, ZeroSrc); 5580 auto LenConst = MIRBuilder.buildConstant(DstTy, Len); 5581 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU); 5582 MI.eraseFromParent(); 5583 return Legalized; 5584 } 5585 // for now, we do this: 5586 // NewLen = NextPowerOf2(Len); 5587 // x = x | (x >> 1); 5588 // x = x | (x >> 2); 5589 // ... 5590 // x = x | (x >>16); 5591 // x = x | (x >>32); // for 64-bit input 5592 // Upto NewLen/2 5593 // return Len - popcount(x); 5594 // 5595 // Ref: "Hacker's Delight" by Henry Warren 5596 Register Op = SrcReg; 5597 unsigned NewLen = PowerOf2Ceil(Len); 5598 for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) { 5599 auto MIBShiftAmt = MIRBuilder.buildConstant(SrcTy, 1ULL << i); 5600 auto MIBOp = MIRBuilder.buildOr( 5601 SrcTy, Op, MIRBuilder.buildLShr(SrcTy, Op, MIBShiftAmt)); 5602 Op = MIBOp.getReg(0); 5603 } 5604 auto MIBPop = MIRBuilder.buildCTPOP(DstTy, Op); 5605 MIRBuilder.buildSub(MI.getOperand(0), MIRBuilder.buildConstant(DstTy, Len), 5606 MIBPop); 5607 MI.eraseFromParent(); 5608 return Legalized; 5609 } 5610 case TargetOpcode::G_CTTZ_ZERO_UNDEF: { 5611 // This trivially expands to CTTZ. 5612 Observer.changingInstr(MI); 5613 MI.setDesc(TII.get(TargetOpcode::G_CTTZ)); 5614 Observer.changedInstr(MI); 5615 return Legalized; 5616 } 5617 case TargetOpcode::G_CTTZ: { 5618 Register DstReg = MI.getOperand(0).getReg(); 5619 Register SrcReg = MI.getOperand(1).getReg(); 5620 LLT DstTy = MRI.getType(DstReg); 5621 LLT SrcTy = MRI.getType(SrcReg); 5622 5623 unsigned Len = SrcTy.getSizeInBits(); 5624 if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) { 5625 // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with 5626 // zero. 5627 auto CttzZU = MIRBuilder.buildCTTZ_ZERO_UNDEF(DstTy, SrcReg); 5628 auto Zero = MIRBuilder.buildConstant(SrcTy, 0); 5629 auto ICmp = MIRBuilder.buildICmp( 5630 CmpInst::ICMP_EQ, DstTy.changeElementSize(1), SrcReg, Zero); 5631 auto LenConst = MIRBuilder.buildConstant(DstTy, Len); 5632 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU); 5633 MI.eraseFromParent(); 5634 return Legalized; 5635 } 5636 // for now, we use: { return popcount(~x & (x - 1)); } 5637 // unless the target has ctlz but not ctpop, in which case we use: 5638 // { return 32 - nlz(~x & (x-1)); } 5639 // Ref: "Hacker's Delight" by Henry Warren 5640 auto MIBCstNeg1 = MIRBuilder.buildConstant(SrcTy, -1); 5641 auto MIBNot = MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1); 5642 auto MIBTmp = MIRBuilder.buildAnd( 5643 SrcTy, MIBNot, MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1)); 5644 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) && 5645 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) { 5646 auto MIBCstLen = MIRBuilder.buildConstant(SrcTy, Len); 5647 MIRBuilder.buildSub(MI.getOperand(0), MIBCstLen, 5648 MIRBuilder.buildCTLZ(SrcTy, MIBTmp)); 5649 MI.eraseFromParent(); 5650 return Legalized; 5651 } 5652 MI.setDesc(TII.get(TargetOpcode::G_CTPOP)); 5653 MI.getOperand(1).setReg(MIBTmp.getReg(0)); 5654 return Legalized; 5655 } 5656 case TargetOpcode::G_CTPOP: { 5657 Register SrcReg = MI.getOperand(1).getReg(); 5658 LLT Ty = MRI.getType(SrcReg); 5659 unsigned Size = Ty.getSizeInBits(); 5660 MachineIRBuilder &B = MIRBuilder; 5661 5662 // Count set bits in blocks of 2 bits. Default approach would be 5663 // B2Count = { val & 0x55555555 } + { (val >> 1) & 0x55555555 } 5664 // We use following formula instead: 5665 // B2Count = val - { (val >> 1) & 0x55555555 } 5666 // since it gives same result in blocks of 2 with one instruction less. 5667 auto C_1 = B.buildConstant(Ty, 1); 5668 auto B2Set1LoTo1Hi = B.buildLShr(Ty, SrcReg, C_1); 5669 APInt B2Mask1HiTo0 = APInt::getSplat(Size, APInt(8, 0x55)); 5670 auto C_B2Mask1HiTo0 = B.buildConstant(Ty, B2Mask1HiTo0); 5671 auto B2Count1Hi = B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0); 5672 auto B2Count = B.buildSub(Ty, SrcReg, B2Count1Hi); 5673 5674 // In order to get count in blocks of 4 add values from adjacent block of 2. 5675 // B4Count = { B2Count & 0x33333333 } + { (B2Count >> 2) & 0x33333333 } 5676 auto C_2 = B.buildConstant(Ty, 2); 5677 auto B4Set2LoTo2Hi = B.buildLShr(Ty, B2Count, C_2); 5678 APInt B4Mask2HiTo0 = APInt::getSplat(Size, APInt(8, 0x33)); 5679 auto C_B4Mask2HiTo0 = B.buildConstant(Ty, B4Mask2HiTo0); 5680 auto B4HiB2Count = B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0); 5681 auto B4LoB2Count = B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0); 5682 auto B4Count = B.buildAdd(Ty, B4HiB2Count, B4LoB2Count); 5683 5684 // For count in blocks of 8 bits we don't have to mask high 4 bits before 5685 // addition since count value sits in range {0,...,8} and 4 bits are enough 5686 // to hold such binary values. After addition high 4 bits still hold count 5687 // of set bits in high 4 bit block, set them to zero and get 8 bit result. 5688 // B8Count = { B4Count + (B4Count >> 4) } & 0x0F0F0F0F 5689 auto C_4 = B.buildConstant(Ty, 4); 5690 auto B8HiB4Count = B.buildLShr(Ty, B4Count, C_4); 5691 auto B8CountDirty4Hi = B.buildAdd(Ty, B8HiB4Count, B4Count); 5692 APInt B8Mask4HiTo0 = APInt::getSplat(Size, APInt(8, 0x0F)); 5693 auto C_B8Mask4HiTo0 = B.buildConstant(Ty, B8Mask4HiTo0); 5694 auto B8Count = B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0); 5695 5696 assert(Size<=128 && "Scalar size is too large for CTPOP lower algorithm"); 5697 // 8 bits can hold CTPOP result of 128 bit int or smaller. Mul with this 5698 // bitmask will set 8 msb in ResTmp to sum of all B8Counts in 8 bit blocks. 5699 auto MulMask = B.buildConstant(Ty, APInt::getSplat(Size, APInt(8, 0x01))); 5700 auto ResTmp = B.buildMul(Ty, B8Count, MulMask); 5701 5702 // Shift count result from 8 high bits to low bits. 5703 auto C_SizeM8 = B.buildConstant(Ty, Size - 8); 5704 B.buildLShr(MI.getOperand(0).getReg(), ResTmp, C_SizeM8); 5705 5706 MI.eraseFromParent(); 5707 return Legalized; 5708 } 5709 } 5710 } 5711 5712 // Check that (every element of) Reg is undef or not an exact multiple of BW. 5713 static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, 5714 Register Reg, unsigned BW) { 5715 return matchUnaryPredicate( 5716 MRI, Reg, 5717 [=](const Constant *C) { 5718 // Null constant here means an undef. 5719 const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C); 5720 return !CI || CI->getValue().urem(BW) != 0; 5721 }, 5722 /*AllowUndefs*/ true); 5723 } 5724 5725 LegalizerHelper::LegalizeResult 5726 LegalizerHelper::lowerFunnelShiftWithInverse(MachineInstr &MI) { 5727 Register Dst = MI.getOperand(0).getReg(); 5728 Register X = MI.getOperand(1).getReg(); 5729 Register Y = MI.getOperand(2).getReg(); 5730 Register Z = MI.getOperand(3).getReg(); 5731 LLT Ty = MRI.getType(Dst); 5732 LLT ShTy = MRI.getType(Z); 5733 5734 unsigned BW = Ty.getScalarSizeInBits(); 5735 5736 if (!isPowerOf2_32(BW)) 5737 return UnableToLegalize; 5738 5739 const bool IsFSHL = MI.getOpcode() == TargetOpcode::G_FSHL; 5740 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL; 5741 5742 if (isNonZeroModBitWidthOrUndef(MRI, Z, BW)) { 5743 // fshl X, Y, Z -> fshr X, Y, -Z 5744 // fshr X, Y, Z -> fshl X, Y, -Z 5745 auto Zero = MIRBuilder.buildConstant(ShTy, 0); 5746 Z = MIRBuilder.buildSub(Ty, Zero, Z).getReg(0); 5747 } else { 5748 // fshl X, Y, Z -> fshr (srl X, 1), (fshr X, Y, 1), ~Z 5749 // fshr X, Y, Z -> fshl (fshl X, Y, 1), (shl Y, 1), ~Z 5750 auto One = MIRBuilder.buildConstant(ShTy, 1); 5751 if (IsFSHL) { 5752 Y = MIRBuilder.buildInstr(RevOpcode, {Ty}, {X, Y, One}).getReg(0); 5753 X = MIRBuilder.buildLShr(Ty, X, One).getReg(0); 5754 } else { 5755 X = MIRBuilder.buildInstr(RevOpcode, {Ty}, {X, Y, One}).getReg(0); 5756 Y = MIRBuilder.buildShl(Ty, Y, One).getReg(0); 5757 } 5758 5759 Z = MIRBuilder.buildNot(ShTy, Z).getReg(0); 5760 } 5761 5762 MIRBuilder.buildInstr(RevOpcode, {Dst}, {X, Y, Z}); 5763 MI.eraseFromParent(); 5764 return Legalized; 5765 } 5766 5767 LegalizerHelper::LegalizeResult 5768 LegalizerHelper::lowerFunnelShiftAsShifts(MachineInstr &MI) { 5769 Register Dst = MI.getOperand(0).getReg(); 5770 Register X = MI.getOperand(1).getReg(); 5771 Register Y = MI.getOperand(2).getReg(); 5772 Register Z = MI.getOperand(3).getReg(); 5773 LLT Ty = MRI.getType(Dst); 5774 LLT ShTy = MRI.getType(Z); 5775 5776 const unsigned BW = Ty.getScalarSizeInBits(); 5777 const bool IsFSHL = MI.getOpcode() == TargetOpcode::G_FSHL; 5778 5779 Register ShX, ShY; 5780 Register ShAmt, InvShAmt; 5781 5782 // FIXME: Emit optimized urem by constant instead of letting it expand later. 5783 if (isNonZeroModBitWidthOrUndef(MRI, Z, BW)) { 5784 // fshl: X << C | Y >> (BW - C) 5785 // fshr: X << (BW - C) | Y >> C 5786 // where C = Z % BW is not zero 5787 auto BitWidthC = MIRBuilder.buildConstant(ShTy, BW); 5788 ShAmt = MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0); 5789 InvShAmt = MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0); 5790 ShX = MIRBuilder.buildShl(Ty, X, IsFSHL ? ShAmt : InvShAmt).getReg(0); 5791 ShY = MIRBuilder.buildLShr(Ty, Y, IsFSHL ? InvShAmt : ShAmt).getReg(0); 5792 } else { 5793 // fshl: X << (Z % BW) | Y >> 1 >> (BW - 1 - (Z % BW)) 5794 // fshr: X << 1 << (BW - 1 - (Z % BW)) | Y >> (Z % BW) 5795 auto Mask = MIRBuilder.buildConstant(ShTy, BW - 1); 5796 if (isPowerOf2_32(BW)) { 5797 // Z % BW -> Z & (BW - 1) 5798 ShAmt = MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0); 5799 // (BW - 1) - (Z % BW) -> ~Z & (BW - 1) 5800 auto NotZ = MIRBuilder.buildNot(ShTy, Z); 5801 InvShAmt = MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0); 5802 } else { 5803 auto BitWidthC = MIRBuilder.buildConstant(ShTy, BW); 5804 ShAmt = MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0); 5805 InvShAmt = MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0); 5806 } 5807 5808 auto One = MIRBuilder.buildConstant(ShTy, 1); 5809 if (IsFSHL) { 5810 ShX = MIRBuilder.buildShl(Ty, X, ShAmt).getReg(0); 5811 auto ShY1 = MIRBuilder.buildLShr(Ty, Y, One); 5812 ShY = MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0); 5813 } else { 5814 auto ShX1 = MIRBuilder.buildShl(Ty, X, One); 5815 ShX = MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0); 5816 ShY = MIRBuilder.buildLShr(Ty, Y, ShAmt).getReg(0); 5817 } 5818 } 5819 5820 MIRBuilder.buildOr(Dst, ShX, ShY); 5821 MI.eraseFromParent(); 5822 return Legalized; 5823 } 5824 5825 LegalizerHelper::LegalizeResult 5826 LegalizerHelper::lowerFunnelShift(MachineInstr &MI) { 5827 // These operations approximately do the following (while avoiding undefined 5828 // shifts by BW): 5829 // G_FSHL: (X << (Z % BW)) | (Y >> (BW - (Z % BW))) 5830 // G_FSHR: (X << (BW - (Z % BW))) | (Y >> (Z % BW)) 5831 Register Dst = MI.getOperand(0).getReg(); 5832 LLT Ty = MRI.getType(Dst); 5833 LLT ShTy = MRI.getType(MI.getOperand(3).getReg()); 5834 5835 bool IsFSHL = MI.getOpcode() == TargetOpcode::G_FSHL; 5836 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL; 5837 5838 // TODO: Use smarter heuristic that accounts for vector legalization. 5839 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action == Lower) 5840 return lowerFunnelShiftAsShifts(MI); 5841 5842 // This only works for powers of 2, fallback to shifts if it fails. 5843 LegalizerHelper::LegalizeResult Result = lowerFunnelShiftWithInverse(MI); 5844 if (Result == UnableToLegalize) 5845 return lowerFunnelShiftAsShifts(MI); 5846 return Result; 5847 } 5848 5849 LegalizerHelper::LegalizeResult 5850 LegalizerHelper::lowerRotateWithReverseRotate(MachineInstr &MI) { 5851 Register Dst = MI.getOperand(0).getReg(); 5852 Register Src = MI.getOperand(1).getReg(); 5853 Register Amt = MI.getOperand(2).getReg(); 5854 LLT AmtTy = MRI.getType(Amt); 5855 auto Zero = MIRBuilder.buildConstant(AmtTy, 0); 5856 bool IsLeft = MI.getOpcode() == TargetOpcode::G_ROTL; 5857 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL; 5858 auto Neg = MIRBuilder.buildSub(AmtTy, Zero, Amt); 5859 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg}); 5860 MI.eraseFromParent(); 5861 return Legalized; 5862 } 5863 5864 LegalizerHelper::LegalizeResult LegalizerHelper::lowerRotate(MachineInstr &MI) { 5865 Register Dst = MI.getOperand(0).getReg(); 5866 Register Src = MI.getOperand(1).getReg(); 5867 Register Amt = MI.getOperand(2).getReg(); 5868 LLT DstTy = MRI.getType(Dst); 5869 LLT SrcTy = MRI.getType(Src); 5870 LLT AmtTy = MRI.getType(Amt); 5871 5872 unsigned EltSizeInBits = DstTy.getScalarSizeInBits(); 5873 bool IsLeft = MI.getOpcode() == TargetOpcode::G_ROTL; 5874 5875 MIRBuilder.setInstrAndDebugLoc(MI); 5876 5877 // If a rotate in the other direction is supported, use it. 5878 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL; 5879 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) && 5880 isPowerOf2_32(EltSizeInBits)) 5881 return lowerRotateWithReverseRotate(MI); 5882 5883 // If a funnel shift is supported, use it. 5884 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR; 5885 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR; 5886 bool IsFShLegal = false; 5887 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) || 5888 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) { 5889 auto buildFunnelShift = [&](unsigned Opc, Register R1, Register R2, 5890 Register R3) { 5891 MIRBuilder.buildInstr(Opc, {R1}, {R2, R2, R3}); 5892 MI.eraseFromParent(); 5893 return Legalized; 5894 }; 5895 // If a funnel shift in the other direction is supported, use it. 5896 if (IsFShLegal) { 5897 return buildFunnelShift(FShOpc, Dst, Src, Amt); 5898 } else if (isPowerOf2_32(EltSizeInBits)) { 5899 Amt = MIRBuilder.buildNeg(DstTy, Amt).getReg(0); 5900 return buildFunnelShift(RevFsh, Dst, Src, Amt); 5901 } 5902 } 5903 5904 auto Zero = MIRBuilder.buildConstant(AmtTy, 0); 5905 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR; 5906 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL; 5907 auto BitWidthMinusOneC = MIRBuilder.buildConstant(AmtTy, EltSizeInBits - 1); 5908 Register ShVal; 5909 Register RevShiftVal; 5910 if (isPowerOf2_32(EltSizeInBits)) { 5911 // (rotl x, c) -> x << (c & (w - 1)) | x >> (-c & (w - 1)) 5912 // (rotr x, c) -> x >> (c & (w - 1)) | x << (-c & (w - 1)) 5913 auto NegAmt = MIRBuilder.buildSub(AmtTy, Zero, Amt); 5914 auto ShAmt = MIRBuilder.buildAnd(AmtTy, Amt, BitWidthMinusOneC); 5915 ShVal = MIRBuilder.buildInstr(ShOpc, {DstTy}, {Src, ShAmt}).getReg(0); 5916 auto RevAmt = MIRBuilder.buildAnd(AmtTy, NegAmt, BitWidthMinusOneC); 5917 RevShiftVal = 5918 MIRBuilder.buildInstr(RevShiftOpc, {DstTy}, {Src, RevAmt}).getReg(0); 5919 } else { 5920 // (rotl x, c) -> x << (c % w) | x >> 1 >> (w - 1 - (c % w)) 5921 // (rotr x, c) -> x >> (c % w) | x << 1 << (w - 1 - (c % w)) 5922 auto BitWidthC = MIRBuilder.buildConstant(AmtTy, EltSizeInBits); 5923 auto ShAmt = MIRBuilder.buildURem(AmtTy, Amt, BitWidthC); 5924 ShVal = MIRBuilder.buildInstr(ShOpc, {DstTy}, {Src, ShAmt}).getReg(0); 5925 auto RevAmt = MIRBuilder.buildSub(AmtTy, BitWidthMinusOneC, ShAmt); 5926 auto One = MIRBuilder.buildConstant(AmtTy, 1); 5927 auto Inner = MIRBuilder.buildInstr(RevShiftOpc, {DstTy}, {Src, One}); 5928 RevShiftVal = 5929 MIRBuilder.buildInstr(RevShiftOpc, {DstTy}, {Inner, RevAmt}).getReg(0); 5930 } 5931 MIRBuilder.buildOr(Dst, ShVal, RevShiftVal); 5932 MI.eraseFromParent(); 5933 return Legalized; 5934 } 5935 5936 // Expand s32 = G_UITOFP s64 using bit operations to an IEEE float 5937 // representation. 5938 LegalizerHelper::LegalizeResult 5939 LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) { 5940 Register Dst = MI.getOperand(0).getReg(); 5941 Register Src = MI.getOperand(1).getReg(); 5942 const LLT S64 = LLT::scalar(64); 5943 const LLT S32 = LLT::scalar(32); 5944 const LLT S1 = LLT::scalar(1); 5945 5946 assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32); 5947 5948 // unsigned cul2f(ulong u) { 5949 // uint lz = clz(u); 5950 // uint e = (u != 0) ? 127U + 63U - lz : 0; 5951 // u = (u << lz) & 0x7fffffffffffffffUL; 5952 // ulong t = u & 0xffffffffffUL; 5953 // uint v = (e << 23) | (uint)(u >> 40); 5954 // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U); 5955 // return as_float(v + r); 5956 // } 5957 5958 auto Zero32 = MIRBuilder.buildConstant(S32, 0); 5959 auto Zero64 = MIRBuilder.buildConstant(S64, 0); 5960 5961 auto LZ = MIRBuilder.buildCTLZ_ZERO_UNDEF(S32, Src); 5962 5963 auto K = MIRBuilder.buildConstant(S32, 127U + 63U); 5964 auto Sub = MIRBuilder.buildSub(S32, K, LZ); 5965 5966 auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64); 5967 auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32); 5968 5969 auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1); 5970 auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ); 5971 5972 auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0); 5973 5974 auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL); 5975 auto T = MIRBuilder.buildAnd(S64, U, Mask1); 5976 5977 auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40)); 5978 auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23)); 5979 auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl)); 5980 5981 auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL); 5982 auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C); 5983 auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C); 5984 auto One = MIRBuilder.buildConstant(S32, 1); 5985 5986 auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One); 5987 auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32); 5988 auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0); 5989 MIRBuilder.buildAdd(Dst, V, R); 5990 5991 MI.eraseFromParent(); 5992 return Legalized; 5993 } 5994 5995 LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) { 5996 Register Dst = MI.getOperand(0).getReg(); 5997 Register Src = MI.getOperand(1).getReg(); 5998 LLT DstTy = MRI.getType(Dst); 5999 LLT SrcTy = MRI.getType(Src); 6000 6001 if (SrcTy == LLT::scalar(1)) { 6002 auto True = MIRBuilder.buildFConstant(DstTy, 1.0); 6003 auto False = MIRBuilder.buildFConstant(DstTy, 0.0); 6004 MIRBuilder.buildSelect(Dst, Src, True, False); 6005 MI.eraseFromParent(); 6006 return Legalized; 6007 } 6008 6009 if (SrcTy != LLT::scalar(64)) 6010 return UnableToLegalize; 6011 6012 if (DstTy == LLT::scalar(32)) { 6013 // TODO: SelectionDAG has several alternative expansions to port which may 6014 // be more reasonble depending on the available instructions. If a target 6015 // has sitofp, does not have CTLZ, or can efficiently use f64 as an 6016 // intermediate type, this is probably worse. 6017 return lowerU64ToF32BitOps(MI); 6018 } 6019 6020 return UnableToLegalize; 6021 } 6022 6023 LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) { 6024 Register Dst = MI.getOperand(0).getReg(); 6025 Register Src = MI.getOperand(1).getReg(); 6026 LLT DstTy = MRI.getType(Dst); 6027 LLT SrcTy = MRI.getType(Src); 6028 6029 const LLT S64 = LLT::scalar(64); 6030 const LLT S32 = LLT::scalar(32); 6031 const LLT S1 = LLT::scalar(1); 6032 6033 if (SrcTy == S1) { 6034 auto True = MIRBuilder.buildFConstant(DstTy, -1.0); 6035 auto False = MIRBuilder.buildFConstant(DstTy, 0.0); 6036 MIRBuilder.buildSelect(Dst, Src, True, False); 6037 MI.eraseFromParent(); 6038 return Legalized; 6039 } 6040 6041 if (SrcTy != S64) 6042 return UnableToLegalize; 6043 6044 if (DstTy == S32) { 6045 // signed cl2f(long l) { 6046 // long s = l >> 63; 6047 // float r = cul2f((l + s) ^ s); 6048 // return s ? -r : r; 6049 // } 6050 Register L = Src; 6051 auto SignBit = MIRBuilder.buildConstant(S64, 63); 6052 auto S = MIRBuilder.buildAShr(S64, L, SignBit); 6053 6054 auto LPlusS = MIRBuilder.buildAdd(S64, L, S); 6055 auto Xor = MIRBuilder.buildXor(S64, LPlusS, S); 6056 auto R = MIRBuilder.buildUITOFP(S32, Xor); 6057 6058 auto RNeg = MIRBuilder.buildFNeg(S32, R); 6059 auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S, 6060 MIRBuilder.buildConstant(S64, 0)); 6061 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R); 6062 MI.eraseFromParent(); 6063 return Legalized; 6064 } 6065 6066 return UnableToLegalize; 6067 } 6068 6069 LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPTOUI(MachineInstr &MI) { 6070 Register Dst = MI.getOperand(0).getReg(); 6071 Register Src = MI.getOperand(1).getReg(); 6072 LLT DstTy = MRI.getType(Dst); 6073 LLT SrcTy = MRI.getType(Src); 6074 const LLT S64 = LLT::scalar(64); 6075 const LLT S32 = LLT::scalar(32); 6076 6077 if (SrcTy != S64 && SrcTy != S32) 6078 return UnableToLegalize; 6079 if (DstTy != S32 && DstTy != S64) 6080 return UnableToLegalize; 6081 6082 // FPTOSI gives same result as FPTOUI for positive signed integers. 6083 // FPTOUI needs to deal with fp values that convert to unsigned integers 6084 // greater or equal to 2^31 for float or 2^63 for double. For brevity 2^Exp. 6085 6086 APInt TwoPExpInt = APInt::getSignMask(DstTy.getSizeInBits()); 6087 APFloat TwoPExpFP(SrcTy.getSizeInBits() == 32 ? APFloat::IEEEsingle() 6088 : APFloat::IEEEdouble(), 6089 APInt::getZero(SrcTy.getSizeInBits())); 6090 TwoPExpFP.convertFromAPInt(TwoPExpInt, false, APFloat::rmNearestTiesToEven); 6091 6092 MachineInstrBuilder FPTOSI = MIRBuilder.buildFPTOSI(DstTy, Src); 6093 6094 MachineInstrBuilder Threshold = MIRBuilder.buildFConstant(SrcTy, TwoPExpFP); 6095 // For fp Value greater or equal to Threshold(2^Exp), we use FPTOSI on 6096 // (Value - 2^Exp) and add 2^Exp by setting highest bit in result to 1. 6097 MachineInstrBuilder FSub = MIRBuilder.buildFSub(SrcTy, Src, Threshold); 6098 MachineInstrBuilder ResLowBits = MIRBuilder.buildFPTOSI(DstTy, FSub); 6099 MachineInstrBuilder ResHighBit = MIRBuilder.buildConstant(DstTy, TwoPExpInt); 6100 MachineInstrBuilder Res = MIRBuilder.buildXor(DstTy, ResLowBits, ResHighBit); 6101 6102 const LLT S1 = LLT::scalar(1); 6103 6104 MachineInstrBuilder FCMP = 6105 MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, S1, Src, Threshold); 6106 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res); 6107 6108 MI.eraseFromParent(); 6109 return Legalized; 6110 } 6111 6112 LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPTOSI(MachineInstr &MI) { 6113 Register Dst = MI.getOperand(0).getReg(); 6114 Register Src = MI.getOperand(1).getReg(); 6115 LLT DstTy = MRI.getType(Dst); 6116 LLT SrcTy = MRI.getType(Src); 6117 const LLT S64 = LLT::scalar(64); 6118 const LLT S32 = LLT::scalar(32); 6119 6120 // FIXME: Only f32 to i64 conversions are supported. 6121 if (SrcTy.getScalarType() != S32 || DstTy.getScalarType() != S64) 6122 return UnableToLegalize; 6123 6124 // Expand f32 -> i64 conversion 6125 // This algorithm comes from compiler-rt's implementation of fixsfdi: 6126 // https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/fixsfdi.c 6127 6128 unsigned SrcEltBits = SrcTy.getScalarSizeInBits(); 6129 6130 auto ExponentMask = MIRBuilder.buildConstant(SrcTy, 0x7F800000); 6131 auto ExponentLoBit = MIRBuilder.buildConstant(SrcTy, 23); 6132 6133 auto AndExpMask = MIRBuilder.buildAnd(SrcTy, Src, ExponentMask); 6134 auto ExponentBits = MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit); 6135 6136 auto SignMask = MIRBuilder.buildConstant(SrcTy, 6137 APInt::getSignMask(SrcEltBits)); 6138 auto AndSignMask = MIRBuilder.buildAnd(SrcTy, Src, SignMask); 6139 auto SignLowBit = MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1); 6140 auto Sign = MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit); 6141 Sign = MIRBuilder.buildSExt(DstTy, Sign); 6142 6143 auto MantissaMask = MIRBuilder.buildConstant(SrcTy, 0x007FFFFF); 6144 auto AndMantissaMask = MIRBuilder.buildAnd(SrcTy, Src, MantissaMask); 6145 auto K = MIRBuilder.buildConstant(SrcTy, 0x00800000); 6146 6147 auto R = MIRBuilder.buildOr(SrcTy, AndMantissaMask, K); 6148 R = MIRBuilder.buildZExt(DstTy, R); 6149 6150 auto Bias = MIRBuilder.buildConstant(SrcTy, 127); 6151 auto Exponent = MIRBuilder.buildSub(SrcTy, ExponentBits, Bias); 6152 auto SubExponent = MIRBuilder.buildSub(SrcTy, Exponent, ExponentLoBit); 6153 auto ExponentSub = MIRBuilder.buildSub(SrcTy, ExponentLoBit, Exponent); 6154 6155 auto Shl = MIRBuilder.buildShl(DstTy, R, SubExponent); 6156 auto Srl = MIRBuilder.buildLShr(DstTy, R, ExponentSub); 6157 6158 const LLT S1 = LLT::scalar(1); 6159 auto CmpGt = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, 6160 S1, Exponent, ExponentLoBit); 6161 6162 R = MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl); 6163 6164 auto XorSign = MIRBuilder.buildXor(DstTy, R, Sign); 6165 auto Ret = MIRBuilder.buildSub(DstTy, XorSign, Sign); 6166 6167 auto ZeroSrcTy = MIRBuilder.buildConstant(SrcTy, 0); 6168 6169 auto ExponentLt0 = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, 6170 S1, Exponent, ZeroSrcTy); 6171 6172 auto ZeroDstTy = MIRBuilder.buildConstant(DstTy, 0); 6173 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret); 6174 6175 MI.eraseFromParent(); 6176 return Legalized; 6177 } 6178 6179 // f64 -> f16 conversion using round-to-nearest-even rounding mode. 6180 LegalizerHelper::LegalizeResult 6181 LegalizerHelper::lowerFPTRUNC_F64_TO_F16(MachineInstr &MI) { 6182 Register Dst = MI.getOperand(0).getReg(); 6183 Register Src = MI.getOperand(1).getReg(); 6184 6185 if (MRI.getType(Src).isVector()) // TODO: Handle vectors directly. 6186 return UnableToLegalize; 6187 6188 const unsigned ExpMask = 0x7ff; 6189 const unsigned ExpBiasf64 = 1023; 6190 const unsigned ExpBiasf16 = 15; 6191 const LLT S32 = LLT::scalar(32); 6192 const LLT S1 = LLT::scalar(1); 6193 6194 auto Unmerge = MIRBuilder.buildUnmerge(S32, Src); 6195 Register U = Unmerge.getReg(0); 6196 Register UH = Unmerge.getReg(1); 6197 6198 auto E = MIRBuilder.buildLShr(S32, UH, MIRBuilder.buildConstant(S32, 20)); 6199 E = MIRBuilder.buildAnd(S32, E, MIRBuilder.buildConstant(S32, ExpMask)); 6200 6201 // Subtract the fp64 exponent bias (1023) to get the real exponent and 6202 // add the f16 bias (15) to get the biased exponent for the f16 format. 6203 E = MIRBuilder.buildAdd( 6204 S32, E, MIRBuilder.buildConstant(S32, -ExpBiasf64 + ExpBiasf16)); 6205 6206 auto M = MIRBuilder.buildLShr(S32, UH, MIRBuilder.buildConstant(S32, 8)); 6207 M = MIRBuilder.buildAnd(S32, M, MIRBuilder.buildConstant(S32, 0xffe)); 6208 6209 auto MaskedSig = MIRBuilder.buildAnd(S32, UH, 6210 MIRBuilder.buildConstant(S32, 0x1ff)); 6211 MaskedSig = MIRBuilder.buildOr(S32, MaskedSig, U); 6212 6213 auto Zero = MIRBuilder.buildConstant(S32, 0); 6214 auto SigCmpNE0 = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, MaskedSig, Zero); 6215 auto Lo40Set = MIRBuilder.buildZExt(S32, SigCmpNE0); 6216 M = MIRBuilder.buildOr(S32, M, Lo40Set); 6217 6218 // (M != 0 ? 0x0200 : 0) | 0x7c00; 6219 auto Bits0x200 = MIRBuilder.buildConstant(S32, 0x0200); 6220 auto CmpM_NE0 = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, M, Zero); 6221 auto SelectCC = MIRBuilder.buildSelect(S32, CmpM_NE0, Bits0x200, Zero); 6222 6223 auto Bits0x7c00 = MIRBuilder.buildConstant(S32, 0x7c00); 6224 auto I = MIRBuilder.buildOr(S32, SelectCC, Bits0x7c00); 6225 6226 // N = M | (E << 12); 6227 auto EShl12 = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 12)); 6228 auto N = MIRBuilder.buildOr(S32, M, EShl12); 6229 6230 // B = clamp(1-E, 0, 13); 6231 auto One = MIRBuilder.buildConstant(S32, 1); 6232 auto OneSubExp = MIRBuilder.buildSub(S32, One, E); 6233 auto B = MIRBuilder.buildSMax(S32, OneSubExp, Zero); 6234 B = MIRBuilder.buildSMin(S32, B, MIRBuilder.buildConstant(S32, 13)); 6235 6236 auto SigSetHigh = MIRBuilder.buildOr(S32, M, 6237 MIRBuilder.buildConstant(S32, 0x1000)); 6238 6239 auto D = MIRBuilder.buildLShr(S32, SigSetHigh, B); 6240 auto D0 = MIRBuilder.buildShl(S32, D, B); 6241 6242 auto D0_NE_SigSetHigh = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, 6243 D0, SigSetHigh); 6244 auto D1 = MIRBuilder.buildZExt(S32, D0_NE_SigSetHigh); 6245 D = MIRBuilder.buildOr(S32, D, D1); 6246 6247 auto CmpELtOne = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, S1, E, One); 6248 auto V = MIRBuilder.buildSelect(S32, CmpELtOne, D, N); 6249 6250 auto VLow3 = MIRBuilder.buildAnd(S32, V, MIRBuilder.buildConstant(S32, 7)); 6251 V = MIRBuilder.buildLShr(S32, V, MIRBuilder.buildConstant(S32, 2)); 6252 6253 auto VLow3Eq3 = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, VLow3, 6254 MIRBuilder.buildConstant(S32, 3)); 6255 auto V0 = MIRBuilder.buildZExt(S32, VLow3Eq3); 6256 6257 auto VLow3Gt5 = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, S1, VLow3, 6258 MIRBuilder.buildConstant(S32, 5)); 6259 auto V1 = MIRBuilder.buildZExt(S32, VLow3Gt5); 6260 6261 V1 = MIRBuilder.buildOr(S32, V0, V1); 6262 V = MIRBuilder.buildAdd(S32, V, V1); 6263 6264 auto CmpEGt30 = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, S1, 6265 E, MIRBuilder.buildConstant(S32, 30)); 6266 V = MIRBuilder.buildSelect(S32, CmpEGt30, 6267 MIRBuilder.buildConstant(S32, 0x7c00), V); 6268 6269 auto CmpEGt1039 = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, 6270 E, MIRBuilder.buildConstant(S32, 1039)); 6271 V = MIRBuilder.buildSelect(S32, CmpEGt1039, I, V); 6272 6273 // Extract the sign bit. 6274 auto Sign = MIRBuilder.buildLShr(S32, UH, MIRBuilder.buildConstant(S32, 16)); 6275 Sign = MIRBuilder.buildAnd(S32, Sign, MIRBuilder.buildConstant(S32, 0x8000)); 6276 6277 // Insert the sign bit 6278 V = MIRBuilder.buildOr(S32, Sign, V); 6279 6280 MIRBuilder.buildTrunc(Dst, V); 6281 MI.eraseFromParent(); 6282 return Legalized; 6283 } 6284 6285 LegalizerHelper::LegalizeResult 6286 LegalizerHelper::lowerFPTRUNC(MachineInstr &MI) { 6287 Register Dst = MI.getOperand(0).getReg(); 6288 Register Src = MI.getOperand(1).getReg(); 6289 6290 LLT DstTy = MRI.getType(Dst); 6291 LLT SrcTy = MRI.getType(Src); 6292 const LLT S64 = LLT::scalar(64); 6293 const LLT S16 = LLT::scalar(16); 6294 6295 if (DstTy.getScalarType() == S16 && SrcTy.getScalarType() == S64) 6296 return lowerFPTRUNC_F64_TO_F16(MI); 6297 6298 return UnableToLegalize; 6299 } 6300 6301 // TODO: If RHS is a constant SelectionDAGBuilder expands this into a 6302 // multiplication tree. 6303 LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPOWI(MachineInstr &MI) { 6304 Register Dst = MI.getOperand(0).getReg(); 6305 Register Src0 = MI.getOperand(1).getReg(); 6306 Register Src1 = MI.getOperand(2).getReg(); 6307 LLT Ty = MRI.getType(Dst); 6308 6309 auto CvtSrc1 = MIRBuilder.buildSITOFP(Ty, Src1); 6310 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1, MI.getFlags()); 6311 MI.eraseFromParent(); 6312 return Legalized; 6313 } 6314 6315 static CmpInst::Predicate minMaxToCompare(unsigned Opc) { 6316 switch (Opc) { 6317 case TargetOpcode::G_SMIN: 6318 return CmpInst::ICMP_SLT; 6319 case TargetOpcode::G_SMAX: 6320 return CmpInst::ICMP_SGT; 6321 case TargetOpcode::G_UMIN: 6322 return CmpInst::ICMP_ULT; 6323 case TargetOpcode::G_UMAX: 6324 return CmpInst::ICMP_UGT; 6325 default: 6326 llvm_unreachable("not in integer min/max"); 6327 } 6328 } 6329 6330 LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) { 6331 Register Dst = MI.getOperand(0).getReg(); 6332 Register Src0 = MI.getOperand(1).getReg(); 6333 Register Src1 = MI.getOperand(2).getReg(); 6334 6335 const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode()); 6336 LLT CmpType = MRI.getType(Dst).changeElementSize(1); 6337 6338 auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1); 6339 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1); 6340 6341 MI.eraseFromParent(); 6342 return Legalized; 6343 } 6344 6345 LegalizerHelper::LegalizeResult 6346 LegalizerHelper::lowerFCopySign(MachineInstr &MI) { 6347 Register Dst = MI.getOperand(0).getReg(); 6348 Register Src0 = MI.getOperand(1).getReg(); 6349 Register Src1 = MI.getOperand(2).getReg(); 6350 6351 const LLT Src0Ty = MRI.getType(Src0); 6352 const LLT Src1Ty = MRI.getType(Src1); 6353 6354 const int Src0Size = Src0Ty.getScalarSizeInBits(); 6355 const int Src1Size = Src1Ty.getScalarSizeInBits(); 6356 6357 auto SignBitMask = MIRBuilder.buildConstant( 6358 Src0Ty, APInt::getSignMask(Src0Size)); 6359 6360 auto NotSignBitMask = MIRBuilder.buildConstant( 6361 Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1)); 6362 6363 Register And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask).getReg(0); 6364 Register And1; 6365 if (Src0Ty == Src1Ty) { 6366 And1 = MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0); 6367 } else if (Src0Size > Src1Size) { 6368 auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size); 6369 auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1); 6370 auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt); 6371 And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0); 6372 } else { 6373 auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size); 6374 auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt); 6375 auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift); 6376 And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0); 6377 } 6378 6379 // Be careful about setting nsz/nnan/ninf on every instruction, since the 6380 // constants are a nan and -0.0, but the final result should preserve 6381 // everything. 6382 unsigned Flags = MI.getFlags(); 6383 MIRBuilder.buildOr(Dst, And0, And1, Flags); 6384 6385 MI.eraseFromParent(); 6386 return Legalized; 6387 } 6388 6389 LegalizerHelper::LegalizeResult 6390 LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) { 6391 unsigned NewOp = MI.getOpcode() == TargetOpcode::G_FMINNUM ? 6392 TargetOpcode::G_FMINNUM_IEEE : TargetOpcode::G_FMAXNUM_IEEE; 6393 6394 Register Dst = MI.getOperand(0).getReg(); 6395 Register Src0 = MI.getOperand(1).getReg(); 6396 Register Src1 = MI.getOperand(2).getReg(); 6397 LLT Ty = MRI.getType(Dst); 6398 6399 if (!MI.getFlag(MachineInstr::FmNoNans)) { 6400 // Insert canonicalizes if it's possible we need to quiet to get correct 6401 // sNaN behavior. 6402 6403 // Note this must be done here, and not as an optimization combine in the 6404 // absence of a dedicate quiet-snan instruction as we're using an 6405 // omni-purpose G_FCANONICALIZE. 6406 if (!isKnownNeverSNaN(Src0, MRI)) 6407 Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0); 6408 6409 if (!isKnownNeverSNaN(Src1, MRI)) 6410 Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0); 6411 } 6412 6413 // If there are no nans, it's safe to simply replace this with the non-IEEE 6414 // version. 6415 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags()); 6416 MI.eraseFromParent(); 6417 return Legalized; 6418 } 6419 6420 LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMad(MachineInstr &MI) { 6421 // Expand G_FMAD a, b, c -> G_FADD (G_FMUL a, b), c 6422 Register DstReg = MI.getOperand(0).getReg(); 6423 LLT Ty = MRI.getType(DstReg); 6424 unsigned Flags = MI.getFlags(); 6425 6426 auto Mul = MIRBuilder.buildFMul(Ty, MI.getOperand(1), MI.getOperand(2), 6427 Flags); 6428 MIRBuilder.buildFAdd(DstReg, Mul, MI.getOperand(3), Flags); 6429 MI.eraseFromParent(); 6430 return Legalized; 6431 } 6432 6433 LegalizerHelper::LegalizeResult 6434 LegalizerHelper::lowerIntrinsicRound(MachineInstr &MI) { 6435 Register DstReg = MI.getOperand(0).getReg(); 6436 Register X = MI.getOperand(1).getReg(); 6437 const unsigned Flags = MI.getFlags(); 6438 const LLT Ty = MRI.getType(DstReg); 6439 const LLT CondTy = Ty.changeElementSize(1); 6440 6441 // round(x) => 6442 // t = trunc(x); 6443 // d = fabs(x - t); 6444 // o = copysign(1.0f, x); 6445 // return t + (d >= 0.5 ? o : 0.0); 6446 6447 auto T = MIRBuilder.buildIntrinsicTrunc(Ty, X, Flags); 6448 6449 auto Diff = MIRBuilder.buildFSub(Ty, X, T, Flags); 6450 auto AbsDiff = MIRBuilder.buildFAbs(Ty, Diff, Flags); 6451 auto Zero = MIRBuilder.buildFConstant(Ty, 0.0); 6452 auto One = MIRBuilder.buildFConstant(Ty, 1.0); 6453 auto Half = MIRBuilder.buildFConstant(Ty, 0.5); 6454 auto SignOne = MIRBuilder.buildFCopysign(Ty, One, X); 6455 6456 auto Cmp = MIRBuilder.buildFCmp(CmpInst::FCMP_OGE, CondTy, AbsDiff, Half, 6457 Flags); 6458 auto Sel = MIRBuilder.buildSelect(Ty, Cmp, SignOne, Zero, Flags); 6459 6460 MIRBuilder.buildFAdd(DstReg, T, Sel, Flags); 6461 6462 MI.eraseFromParent(); 6463 return Legalized; 6464 } 6465 6466 LegalizerHelper::LegalizeResult 6467 LegalizerHelper::lowerFFloor(MachineInstr &MI) { 6468 Register DstReg = MI.getOperand(0).getReg(); 6469 Register SrcReg = MI.getOperand(1).getReg(); 6470 unsigned Flags = MI.getFlags(); 6471 LLT Ty = MRI.getType(DstReg); 6472 const LLT CondTy = Ty.changeElementSize(1); 6473 6474 // result = trunc(src); 6475 // if (src < 0.0 && src != result) 6476 // result += -1.0. 6477 6478 auto Trunc = MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags); 6479 auto Zero = MIRBuilder.buildFConstant(Ty, 0.0); 6480 6481 auto Lt0 = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, CondTy, 6482 SrcReg, Zero, Flags); 6483 auto NeTrunc = MIRBuilder.buildFCmp(CmpInst::FCMP_ONE, CondTy, 6484 SrcReg, Trunc, Flags); 6485 auto And = MIRBuilder.buildAnd(CondTy, Lt0, NeTrunc); 6486 auto AddVal = MIRBuilder.buildSITOFP(Ty, And); 6487 6488 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags); 6489 MI.eraseFromParent(); 6490 return Legalized; 6491 } 6492 6493 LegalizerHelper::LegalizeResult 6494 LegalizerHelper::lowerMergeValues(MachineInstr &MI) { 6495 const unsigned NumOps = MI.getNumOperands(); 6496 Register DstReg = MI.getOperand(0).getReg(); 6497 Register Src0Reg = MI.getOperand(1).getReg(); 6498 LLT DstTy = MRI.getType(DstReg); 6499 LLT SrcTy = MRI.getType(Src0Reg); 6500 unsigned PartSize = SrcTy.getSizeInBits(); 6501 6502 LLT WideTy = LLT::scalar(DstTy.getSizeInBits()); 6503 Register ResultReg = MIRBuilder.buildZExt(WideTy, Src0Reg).getReg(0); 6504 6505 for (unsigned I = 2; I != NumOps; ++I) { 6506 const unsigned Offset = (I - 1) * PartSize; 6507 6508 Register SrcReg = MI.getOperand(I).getReg(); 6509 auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg); 6510 6511 Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg : 6512 MRI.createGenericVirtualRegister(WideTy); 6513 6514 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset); 6515 auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt); 6516 MIRBuilder.buildOr(NextResult, ResultReg, Shl); 6517 ResultReg = NextResult; 6518 } 6519 6520 if (DstTy.isPointer()) { 6521 if (MIRBuilder.getDataLayout().isNonIntegralAddressSpace( 6522 DstTy.getAddressSpace())) { 6523 LLVM_DEBUG(dbgs() << "Not casting nonintegral address space\n"); 6524 return UnableToLegalize; 6525 } 6526 6527 MIRBuilder.buildIntToPtr(DstReg, ResultReg); 6528 } 6529 6530 MI.eraseFromParent(); 6531 return Legalized; 6532 } 6533 6534 LegalizerHelper::LegalizeResult 6535 LegalizerHelper::lowerUnmergeValues(MachineInstr &MI) { 6536 const unsigned NumDst = MI.getNumOperands() - 1; 6537 Register SrcReg = MI.getOperand(NumDst).getReg(); 6538 Register Dst0Reg = MI.getOperand(0).getReg(); 6539 LLT DstTy = MRI.getType(Dst0Reg); 6540 if (DstTy.isPointer()) 6541 return UnableToLegalize; // TODO 6542 6543 SrcReg = coerceToScalar(SrcReg); 6544 if (!SrcReg) 6545 return UnableToLegalize; 6546 6547 // Expand scalarizing unmerge as bitcast to integer and shift. 6548 LLT IntTy = MRI.getType(SrcReg); 6549 6550 MIRBuilder.buildTrunc(Dst0Reg, SrcReg); 6551 6552 const unsigned DstSize = DstTy.getSizeInBits(); 6553 unsigned Offset = DstSize; 6554 for (unsigned I = 1; I != NumDst; ++I, Offset += DstSize) { 6555 auto ShiftAmt = MIRBuilder.buildConstant(IntTy, Offset); 6556 auto Shift = MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt); 6557 MIRBuilder.buildTrunc(MI.getOperand(I), Shift); 6558 } 6559 6560 MI.eraseFromParent(); 6561 return Legalized; 6562 } 6563 6564 /// Lower a vector extract or insert by writing the vector to a stack temporary 6565 /// and reloading the element or vector. 6566 /// 6567 /// %dst = G_EXTRACT_VECTOR_ELT %vec, %idx 6568 /// => 6569 /// %stack_temp = G_FRAME_INDEX 6570 /// G_STORE %vec, %stack_temp 6571 /// %idx = clamp(%idx, %vec.getNumElements()) 6572 /// %element_ptr = G_PTR_ADD %stack_temp, %idx 6573 /// %dst = G_LOAD %element_ptr 6574 LegalizerHelper::LegalizeResult 6575 LegalizerHelper::lowerExtractInsertVectorElt(MachineInstr &MI) { 6576 Register DstReg = MI.getOperand(0).getReg(); 6577 Register SrcVec = MI.getOperand(1).getReg(); 6578 Register InsertVal; 6579 if (MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT) 6580 InsertVal = MI.getOperand(2).getReg(); 6581 6582 Register Idx = MI.getOperand(MI.getNumOperands() - 1).getReg(); 6583 6584 LLT VecTy = MRI.getType(SrcVec); 6585 LLT EltTy = VecTy.getElementType(); 6586 unsigned NumElts = VecTy.getNumElements(); 6587 6588 int64_t IdxVal; 6589 if (mi_match(Idx, MRI, m_ICst(IdxVal)) && IdxVal <= NumElts) { 6590 SmallVector<Register, 8> SrcRegs; 6591 extractParts(SrcVec, EltTy, NumElts, SrcRegs); 6592 6593 if (InsertVal) { 6594 SrcRegs[IdxVal] = MI.getOperand(2).getReg(); 6595 MIRBuilder.buildMerge(DstReg, SrcRegs); 6596 } else { 6597 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]); 6598 } 6599 6600 MI.eraseFromParent(); 6601 return Legalized; 6602 } 6603 6604 if (!EltTy.isByteSized()) { // Not implemented. 6605 LLVM_DEBUG(dbgs() << "Can't handle non-byte element vectors yet\n"); 6606 return UnableToLegalize; 6607 } 6608 6609 unsigned EltBytes = EltTy.getSizeInBytes(); 6610 Align VecAlign = getStackTemporaryAlignment(VecTy); 6611 Align EltAlign; 6612 6613 MachinePointerInfo PtrInfo; 6614 auto StackTemp = createStackTemporary(TypeSize::Fixed(VecTy.getSizeInBytes()), 6615 VecAlign, PtrInfo); 6616 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign); 6617 6618 // Get the pointer to the element, and be sure not to hit undefined behavior 6619 // if the index is out of bounds. 6620 Register EltPtr = getVectorElementPointer(StackTemp.getReg(0), VecTy, Idx); 6621 6622 if (mi_match(Idx, MRI, m_ICst(IdxVal))) { 6623 int64_t Offset = IdxVal * EltBytes; 6624 PtrInfo = PtrInfo.getWithOffset(Offset); 6625 EltAlign = commonAlignment(VecAlign, Offset); 6626 } else { 6627 // We lose information with a variable offset. 6628 EltAlign = getStackTemporaryAlignment(EltTy); 6629 PtrInfo = MachinePointerInfo(MRI.getType(EltPtr).getAddressSpace()); 6630 } 6631 6632 if (InsertVal) { 6633 // Write the inserted element 6634 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign); 6635 6636 // Reload the whole vector. 6637 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign); 6638 } else { 6639 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign); 6640 } 6641 6642 MI.eraseFromParent(); 6643 return Legalized; 6644 } 6645 6646 LegalizerHelper::LegalizeResult 6647 LegalizerHelper::lowerShuffleVector(MachineInstr &MI) { 6648 Register DstReg = MI.getOperand(0).getReg(); 6649 Register Src0Reg = MI.getOperand(1).getReg(); 6650 Register Src1Reg = MI.getOperand(2).getReg(); 6651 LLT Src0Ty = MRI.getType(Src0Reg); 6652 LLT DstTy = MRI.getType(DstReg); 6653 LLT IdxTy = LLT::scalar(32); 6654 6655 ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask(); 6656 6657 if (DstTy.isScalar()) { 6658 if (Src0Ty.isVector()) 6659 return UnableToLegalize; 6660 6661 // This is just a SELECT. 6662 assert(Mask.size() == 1 && "Expected a single mask element"); 6663 Register Val; 6664 if (Mask[0] < 0 || Mask[0] > 1) 6665 Val = MIRBuilder.buildUndef(DstTy).getReg(0); 6666 else 6667 Val = Mask[0] == 0 ? Src0Reg : Src1Reg; 6668 MIRBuilder.buildCopy(DstReg, Val); 6669 MI.eraseFromParent(); 6670 return Legalized; 6671 } 6672 6673 Register Undef; 6674 SmallVector<Register, 32> BuildVec; 6675 LLT EltTy = DstTy.getElementType(); 6676 6677 for (int Idx : Mask) { 6678 if (Idx < 0) { 6679 if (!Undef.isValid()) 6680 Undef = MIRBuilder.buildUndef(EltTy).getReg(0); 6681 BuildVec.push_back(Undef); 6682 continue; 6683 } 6684 6685 if (Src0Ty.isScalar()) { 6686 BuildVec.push_back(Idx == 0 ? Src0Reg : Src1Reg); 6687 } else { 6688 int NumElts = Src0Ty.getNumElements(); 6689 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg; 6690 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts; 6691 auto IdxK = MIRBuilder.buildConstant(IdxTy, ExtractIdx); 6692 auto Extract = MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK); 6693 BuildVec.push_back(Extract.getReg(0)); 6694 } 6695 } 6696 6697 MIRBuilder.buildBuildVector(DstReg, BuildVec); 6698 MI.eraseFromParent(); 6699 return Legalized; 6700 } 6701 6702 LegalizerHelper::LegalizeResult 6703 LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) { 6704 const auto &MF = *MI.getMF(); 6705 const auto &TFI = *MF.getSubtarget().getFrameLowering(); 6706 if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp) 6707 return UnableToLegalize; 6708 6709 Register Dst = MI.getOperand(0).getReg(); 6710 Register AllocSize = MI.getOperand(1).getReg(); 6711 Align Alignment = assumeAligned(MI.getOperand(2).getImm()); 6712 6713 LLT PtrTy = MRI.getType(Dst); 6714 LLT IntPtrTy = LLT::scalar(PtrTy.getSizeInBits()); 6715 6716 Register SPReg = TLI.getStackPointerRegisterToSaveRestore(); 6717 auto SPTmp = MIRBuilder.buildCopy(PtrTy, SPReg); 6718 SPTmp = MIRBuilder.buildCast(IntPtrTy, SPTmp); 6719 6720 // Subtract the final alloc from the SP. We use G_PTRTOINT here so we don't 6721 // have to generate an extra instruction to negate the alloc and then use 6722 // G_PTR_ADD to add the negative offset. 6723 auto Alloc = MIRBuilder.buildSub(IntPtrTy, SPTmp, AllocSize); 6724 if (Alignment > Align(1)) { 6725 APInt AlignMask(IntPtrTy.getSizeInBits(), Alignment.value(), true); 6726 AlignMask.negate(); 6727 auto AlignCst = MIRBuilder.buildConstant(IntPtrTy, AlignMask); 6728 Alloc = MIRBuilder.buildAnd(IntPtrTy, Alloc, AlignCst); 6729 } 6730 6731 SPTmp = MIRBuilder.buildCast(PtrTy, Alloc); 6732 MIRBuilder.buildCopy(SPReg, SPTmp); 6733 MIRBuilder.buildCopy(Dst, SPTmp); 6734 6735 MI.eraseFromParent(); 6736 return Legalized; 6737 } 6738 6739 LegalizerHelper::LegalizeResult 6740 LegalizerHelper::lowerExtract(MachineInstr &MI) { 6741 Register Dst = MI.getOperand(0).getReg(); 6742 Register Src = MI.getOperand(1).getReg(); 6743 unsigned Offset = MI.getOperand(2).getImm(); 6744 6745 LLT DstTy = MRI.getType(Dst); 6746 LLT SrcTy = MRI.getType(Src); 6747 6748 // Extract sub-vector or one element 6749 if (SrcTy.isVector()) { 6750 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits(); 6751 unsigned DstSize = DstTy.getSizeInBits(); 6752 6753 if ((Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) && 6754 (Offset + DstSize <= SrcTy.getSizeInBits())) { 6755 // Unmerge and allow access to each Src element for the artifact combiner. 6756 auto Unmerge = MIRBuilder.buildUnmerge(SrcTy.getElementType(), Src); 6757 6758 // Take element(s) we need to extract and copy it (merge them). 6759 SmallVector<Register, 8> SubVectorElts; 6760 for (unsigned Idx = Offset / SrcEltSize; 6761 Idx < (Offset + DstSize) / SrcEltSize; ++Idx) { 6762 SubVectorElts.push_back(Unmerge.getReg(Idx)); 6763 } 6764 if (SubVectorElts.size() == 1) 6765 MIRBuilder.buildCopy(Dst, SubVectorElts[0]); 6766 else 6767 MIRBuilder.buildMerge(Dst, SubVectorElts); 6768 6769 MI.eraseFromParent(); 6770 return Legalized; 6771 } 6772 } 6773 6774 if (DstTy.isScalar() && 6775 (SrcTy.isScalar() || 6776 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) { 6777 LLT SrcIntTy = SrcTy; 6778 if (!SrcTy.isScalar()) { 6779 SrcIntTy = LLT::scalar(SrcTy.getSizeInBits()); 6780 Src = MIRBuilder.buildBitcast(SrcIntTy, Src).getReg(0); 6781 } 6782 6783 if (Offset == 0) 6784 MIRBuilder.buildTrunc(Dst, Src); 6785 else { 6786 auto ShiftAmt = MIRBuilder.buildConstant(SrcIntTy, Offset); 6787 auto Shr = MIRBuilder.buildLShr(SrcIntTy, Src, ShiftAmt); 6788 MIRBuilder.buildTrunc(Dst, Shr); 6789 } 6790 6791 MI.eraseFromParent(); 6792 return Legalized; 6793 } 6794 6795 return UnableToLegalize; 6796 } 6797 6798 LegalizerHelper::LegalizeResult LegalizerHelper::lowerInsert(MachineInstr &MI) { 6799 Register Dst = MI.getOperand(0).getReg(); 6800 Register Src = MI.getOperand(1).getReg(); 6801 Register InsertSrc = MI.getOperand(2).getReg(); 6802 uint64_t Offset = MI.getOperand(3).getImm(); 6803 6804 LLT DstTy = MRI.getType(Src); 6805 LLT InsertTy = MRI.getType(InsertSrc); 6806 6807 // Insert sub-vector or one element 6808 if (DstTy.isVector() && !InsertTy.isPointer()) { 6809 LLT EltTy = DstTy.getElementType(); 6810 unsigned EltSize = EltTy.getSizeInBits(); 6811 unsigned InsertSize = InsertTy.getSizeInBits(); 6812 6813 if ((Offset % EltSize == 0) && (InsertSize % EltSize == 0) && 6814 (Offset + InsertSize <= DstTy.getSizeInBits())) { 6815 auto UnmergeSrc = MIRBuilder.buildUnmerge(EltTy, Src); 6816 SmallVector<Register, 8> DstElts; 6817 unsigned Idx = 0; 6818 // Elements from Src before insert start Offset 6819 for (; Idx < Offset / EltSize; ++Idx) { 6820 DstElts.push_back(UnmergeSrc.getReg(Idx)); 6821 } 6822 6823 // Replace elements in Src with elements from InsertSrc 6824 if (InsertTy.getSizeInBits() > EltSize) { 6825 auto UnmergeInsertSrc = MIRBuilder.buildUnmerge(EltTy, InsertSrc); 6826 for (unsigned i = 0; Idx < (Offset + InsertSize) / EltSize; 6827 ++Idx, ++i) { 6828 DstElts.push_back(UnmergeInsertSrc.getReg(i)); 6829 } 6830 } else { 6831 DstElts.push_back(InsertSrc); 6832 ++Idx; 6833 } 6834 6835 // Remaining elements from Src after insert 6836 for (; Idx < DstTy.getNumElements(); ++Idx) { 6837 DstElts.push_back(UnmergeSrc.getReg(Idx)); 6838 } 6839 6840 MIRBuilder.buildMerge(Dst, DstElts); 6841 MI.eraseFromParent(); 6842 return Legalized; 6843 } 6844 } 6845 6846 if (InsertTy.isVector() || 6847 (DstTy.isVector() && DstTy.getElementType() != InsertTy)) 6848 return UnableToLegalize; 6849 6850 const DataLayout &DL = MIRBuilder.getDataLayout(); 6851 if ((DstTy.isPointer() && 6852 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace())) || 6853 (InsertTy.isPointer() && 6854 DL.isNonIntegralAddressSpace(InsertTy.getAddressSpace()))) { 6855 LLVM_DEBUG(dbgs() << "Not casting non-integral address space integer\n"); 6856 return UnableToLegalize; 6857 } 6858 6859 LLT IntDstTy = DstTy; 6860 6861 if (!DstTy.isScalar()) { 6862 IntDstTy = LLT::scalar(DstTy.getSizeInBits()); 6863 Src = MIRBuilder.buildCast(IntDstTy, Src).getReg(0); 6864 } 6865 6866 if (!InsertTy.isScalar()) { 6867 const LLT IntInsertTy = LLT::scalar(InsertTy.getSizeInBits()); 6868 InsertSrc = MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0); 6869 } 6870 6871 Register ExtInsSrc = MIRBuilder.buildZExt(IntDstTy, InsertSrc).getReg(0); 6872 if (Offset != 0) { 6873 auto ShiftAmt = MIRBuilder.buildConstant(IntDstTy, Offset); 6874 ExtInsSrc = MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0); 6875 } 6876 6877 APInt MaskVal = APInt::getBitsSetWithWrap( 6878 DstTy.getSizeInBits(), Offset + InsertTy.getSizeInBits(), Offset); 6879 6880 auto Mask = MIRBuilder.buildConstant(IntDstTy, MaskVal); 6881 auto MaskedSrc = MIRBuilder.buildAnd(IntDstTy, Src, Mask); 6882 auto Or = MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc); 6883 6884 MIRBuilder.buildCast(Dst, Or); 6885 MI.eraseFromParent(); 6886 return Legalized; 6887 } 6888 6889 LegalizerHelper::LegalizeResult 6890 LegalizerHelper::lowerSADDO_SSUBO(MachineInstr &MI) { 6891 Register Dst0 = MI.getOperand(0).getReg(); 6892 Register Dst1 = MI.getOperand(1).getReg(); 6893 Register LHS = MI.getOperand(2).getReg(); 6894 Register RHS = MI.getOperand(3).getReg(); 6895 const bool IsAdd = MI.getOpcode() == TargetOpcode::G_SADDO; 6896 6897 LLT Ty = MRI.getType(Dst0); 6898 LLT BoolTy = MRI.getType(Dst1); 6899 6900 if (IsAdd) 6901 MIRBuilder.buildAdd(Dst0, LHS, RHS); 6902 else 6903 MIRBuilder.buildSub(Dst0, LHS, RHS); 6904 6905 // TODO: If SADDSAT/SSUBSAT is legal, compare results to detect overflow. 6906 6907 auto Zero = MIRBuilder.buildConstant(Ty, 0); 6908 6909 // For an addition, the result should be less than one of the operands (LHS) 6910 // if and only if the other operand (RHS) is negative, otherwise there will 6911 // be overflow. 6912 // For a subtraction, the result should be less than one of the operands 6913 // (LHS) if and only if the other operand (RHS) is (non-zero) positive, 6914 // otherwise there will be overflow. 6915 auto ResultLowerThanLHS = 6916 MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, Dst0, LHS); 6917 auto ConditionRHS = MIRBuilder.buildICmp( 6918 IsAdd ? CmpInst::ICMP_SLT : CmpInst::ICMP_SGT, BoolTy, RHS, Zero); 6919 6920 MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS); 6921 MI.eraseFromParent(); 6922 return Legalized; 6923 } 6924 6925 LegalizerHelper::LegalizeResult 6926 LegalizerHelper::lowerAddSubSatToMinMax(MachineInstr &MI) { 6927 Register Res = MI.getOperand(0).getReg(); 6928 Register LHS = MI.getOperand(1).getReg(); 6929 Register RHS = MI.getOperand(2).getReg(); 6930 LLT Ty = MRI.getType(Res); 6931 bool IsSigned; 6932 bool IsAdd; 6933 unsigned BaseOp; 6934 switch (MI.getOpcode()) { 6935 default: 6936 llvm_unreachable("unexpected addsat/subsat opcode"); 6937 case TargetOpcode::G_UADDSAT: 6938 IsSigned = false; 6939 IsAdd = true; 6940 BaseOp = TargetOpcode::G_ADD; 6941 break; 6942 case TargetOpcode::G_SADDSAT: 6943 IsSigned = true; 6944 IsAdd = true; 6945 BaseOp = TargetOpcode::G_ADD; 6946 break; 6947 case TargetOpcode::G_USUBSAT: 6948 IsSigned = false; 6949 IsAdd = false; 6950 BaseOp = TargetOpcode::G_SUB; 6951 break; 6952 case TargetOpcode::G_SSUBSAT: 6953 IsSigned = true; 6954 IsAdd = false; 6955 BaseOp = TargetOpcode::G_SUB; 6956 break; 6957 } 6958 6959 if (IsSigned) { 6960 // sadd.sat(a, b) -> 6961 // hi = 0x7fffffff - smax(a, 0) 6962 // lo = 0x80000000 - smin(a, 0) 6963 // a + smin(smax(lo, b), hi) 6964 // ssub.sat(a, b) -> 6965 // lo = smax(a, -1) - 0x7fffffff 6966 // hi = smin(a, -1) - 0x80000000 6967 // a - smin(smax(lo, b), hi) 6968 // TODO: AMDGPU can use a "median of 3" instruction here: 6969 // a +/- med3(lo, b, hi) 6970 uint64_t NumBits = Ty.getScalarSizeInBits(); 6971 auto MaxVal = 6972 MIRBuilder.buildConstant(Ty, APInt::getSignedMaxValue(NumBits)); 6973 auto MinVal = 6974 MIRBuilder.buildConstant(Ty, APInt::getSignedMinValue(NumBits)); 6975 MachineInstrBuilder Hi, Lo; 6976 if (IsAdd) { 6977 auto Zero = MIRBuilder.buildConstant(Ty, 0); 6978 Hi = MIRBuilder.buildSub(Ty, MaxVal, MIRBuilder.buildSMax(Ty, LHS, Zero)); 6979 Lo = MIRBuilder.buildSub(Ty, MinVal, MIRBuilder.buildSMin(Ty, LHS, Zero)); 6980 } else { 6981 auto NegOne = MIRBuilder.buildConstant(Ty, -1); 6982 Lo = MIRBuilder.buildSub(Ty, MIRBuilder.buildSMax(Ty, LHS, NegOne), 6983 MaxVal); 6984 Hi = MIRBuilder.buildSub(Ty, MIRBuilder.buildSMin(Ty, LHS, NegOne), 6985 MinVal); 6986 } 6987 auto RHSClamped = 6988 MIRBuilder.buildSMin(Ty, MIRBuilder.buildSMax(Ty, Lo, RHS), Hi); 6989 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped}); 6990 } else { 6991 // uadd.sat(a, b) -> a + umin(~a, b) 6992 // usub.sat(a, b) -> a - umin(a, b) 6993 Register Not = IsAdd ? MIRBuilder.buildNot(Ty, LHS).getReg(0) : LHS; 6994 auto Min = MIRBuilder.buildUMin(Ty, Not, RHS); 6995 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min}); 6996 } 6997 6998 MI.eraseFromParent(); 6999 return Legalized; 7000 } 7001 7002 LegalizerHelper::LegalizeResult 7003 LegalizerHelper::lowerAddSubSatToAddoSubo(MachineInstr &MI) { 7004 Register Res = MI.getOperand(0).getReg(); 7005 Register LHS = MI.getOperand(1).getReg(); 7006 Register RHS = MI.getOperand(2).getReg(); 7007 LLT Ty = MRI.getType(Res); 7008 LLT BoolTy = Ty.changeElementSize(1); 7009 bool IsSigned; 7010 bool IsAdd; 7011 unsigned OverflowOp; 7012 switch (MI.getOpcode()) { 7013 default: 7014 llvm_unreachable("unexpected addsat/subsat opcode"); 7015 case TargetOpcode::G_UADDSAT: 7016 IsSigned = false; 7017 IsAdd = true; 7018 OverflowOp = TargetOpcode::G_UADDO; 7019 break; 7020 case TargetOpcode::G_SADDSAT: 7021 IsSigned = true; 7022 IsAdd = true; 7023 OverflowOp = TargetOpcode::G_SADDO; 7024 break; 7025 case TargetOpcode::G_USUBSAT: 7026 IsSigned = false; 7027 IsAdd = false; 7028 OverflowOp = TargetOpcode::G_USUBO; 7029 break; 7030 case TargetOpcode::G_SSUBSAT: 7031 IsSigned = true; 7032 IsAdd = false; 7033 OverflowOp = TargetOpcode::G_SSUBO; 7034 break; 7035 } 7036 7037 auto OverflowRes = 7038 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS}); 7039 Register Tmp = OverflowRes.getReg(0); 7040 Register Ov = OverflowRes.getReg(1); 7041 MachineInstrBuilder Clamp; 7042 if (IsSigned) { 7043 // sadd.sat(a, b) -> 7044 // {tmp, ov} = saddo(a, b) 7045 // ov ? (tmp >>s 31) + 0x80000000 : r 7046 // ssub.sat(a, b) -> 7047 // {tmp, ov} = ssubo(a, b) 7048 // ov ? (tmp >>s 31) + 0x80000000 : r 7049 uint64_t NumBits = Ty.getScalarSizeInBits(); 7050 auto ShiftAmount = MIRBuilder.buildConstant(Ty, NumBits - 1); 7051 auto Sign = MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount); 7052 auto MinVal = 7053 MIRBuilder.buildConstant(Ty, APInt::getSignedMinValue(NumBits)); 7054 Clamp = MIRBuilder.buildAdd(Ty, Sign, MinVal); 7055 } else { 7056 // uadd.sat(a, b) -> 7057 // {tmp, ov} = uaddo(a, b) 7058 // ov ? 0xffffffff : tmp 7059 // usub.sat(a, b) -> 7060 // {tmp, ov} = usubo(a, b) 7061 // ov ? 0 : tmp 7062 Clamp = MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0); 7063 } 7064 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp); 7065 7066 MI.eraseFromParent(); 7067 return Legalized; 7068 } 7069 7070 LegalizerHelper::LegalizeResult 7071 LegalizerHelper::lowerShlSat(MachineInstr &MI) { 7072 assert((MI.getOpcode() == TargetOpcode::G_SSHLSAT || 7073 MI.getOpcode() == TargetOpcode::G_USHLSAT) && 7074 "Expected shlsat opcode!"); 7075 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SSHLSAT; 7076 Register Res = MI.getOperand(0).getReg(); 7077 Register LHS = MI.getOperand(1).getReg(); 7078 Register RHS = MI.getOperand(2).getReg(); 7079 LLT Ty = MRI.getType(Res); 7080 LLT BoolTy = Ty.changeElementSize(1); 7081 7082 unsigned BW = Ty.getScalarSizeInBits(); 7083 auto Result = MIRBuilder.buildShl(Ty, LHS, RHS); 7084 auto Orig = IsSigned ? MIRBuilder.buildAShr(Ty, Result, RHS) 7085 : MIRBuilder.buildLShr(Ty, Result, RHS); 7086 7087 MachineInstrBuilder SatVal; 7088 if (IsSigned) { 7089 auto SatMin = MIRBuilder.buildConstant(Ty, APInt::getSignedMinValue(BW)); 7090 auto SatMax = MIRBuilder.buildConstant(Ty, APInt::getSignedMaxValue(BW)); 7091 auto Cmp = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, LHS, 7092 MIRBuilder.buildConstant(Ty, 0)); 7093 SatVal = MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax); 7094 } else { 7095 SatVal = MIRBuilder.buildConstant(Ty, APInt::getMaxValue(BW)); 7096 } 7097 auto Ov = MIRBuilder.buildICmp(CmpInst::ICMP_NE, BoolTy, LHS, Orig); 7098 MIRBuilder.buildSelect(Res, Ov, SatVal, Result); 7099 7100 MI.eraseFromParent(); 7101 return Legalized; 7102 } 7103 7104 LegalizerHelper::LegalizeResult 7105 LegalizerHelper::lowerBswap(MachineInstr &MI) { 7106 Register Dst = MI.getOperand(0).getReg(); 7107 Register Src = MI.getOperand(1).getReg(); 7108 const LLT Ty = MRI.getType(Src); 7109 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8; 7110 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8; 7111 7112 // Swap most and least significant byte, set remaining bytes in Res to zero. 7113 auto ShiftAmt = MIRBuilder.buildConstant(Ty, BaseShiftAmt); 7114 auto LSByteShiftedLeft = MIRBuilder.buildShl(Ty, Src, ShiftAmt); 7115 auto MSByteShiftedRight = MIRBuilder.buildLShr(Ty, Src, ShiftAmt); 7116 auto Res = MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft); 7117 7118 // Set i-th high/low byte in Res to i-th low/high byte from Src. 7119 for (unsigned i = 1; i < SizeInBytes / 2; ++i) { 7120 // AND with Mask leaves byte i unchanged and sets remaining bytes to 0. 7121 APInt APMask(SizeInBytes * 8, 0xFF << (i * 8)); 7122 auto Mask = MIRBuilder.buildConstant(Ty, APMask); 7123 auto ShiftAmt = MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i); 7124 // Low byte shifted left to place of high byte: (Src & Mask) << ShiftAmt. 7125 auto LoByte = MIRBuilder.buildAnd(Ty, Src, Mask); 7126 auto LoShiftedLeft = MIRBuilder.buildShl(Ty, LoByte, ShiftAmt); 7127 Res = MIRBuilder.buildOr(Ty, Res, LoShiftedLeft); 7128 // High byte shifted right to place of low byte: (Src >> ShiftAmt) & Mask. 7129 auto SrcShiftedRight = MIRBuilder.buildLShr(Ty, Src, ShiftAmt); 7130 auto HiShiftedRight = MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask); 7131 Res = MIRBuilder.buildOr(Ty, Res, HiShiftedRight); 7132 } 7133 Res.getInstr()->getOperand(0).setReg(Dst); 7134 7135 MI.eraseFromParent(); 7136 return Legalized; 7137 } 7138 7139 //{ (Src & Mask) >> N } | { (Src << N) & Mask } 7140 static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, 7141 MachineInstrBuilder Src, APInt Mask) { 7142 const LLT Ty = Dst.getLLTTy(*B.getMRI()); 7143 MachineInstrBuilder C_N = B.buildConstant(Ty, N); 7144 MachineInstrBuilder MaskLoNTo0 = B.buildConstant(Ty, Mask); 7145 auto LHS = B.buildLShr(Ty, B.buildAnd(Ty, Src, MaskLoNTo0), C_N); 7146 auto RHS = B.buildAnd(Ty, B.buildShl(Ty, Src, C_N), MaskLoNTo0); 7147 return B.buildOr(Dst, LHS, RHS); 7148 } 7149 7150 LegalizerHelper::LegalizeResult 7151 LegalizerHelper::lowerBitreverse(MachineInstr &MI) { 7152 Register Dst = MI.getOperand(0).getReg(); 7153 Register Src = MI.getOperand(1).getReg(); 7154 const LLT Ty = MRI.getType(Src); 7155 unsigned Size = Ty.getSizeInBits(); 7156 7157 MachineInstrBuilder BSWAP = 7158 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {Ty}, {Src}); 7159 7160 // swap high and low 4 bits in 8 bit blocks 7654|3210 -> 3210|7654 7161 // [(val & 0xF0F0F0F0) >> 4] | [(val & 0x0F0F0F0F) << 4] 7162 // -> [(val & 0xF0F0F0F0) >> 4] | [(val << 4) & 0xF0F0F0F0] 7163 MachineInstrBuilder Swap4 = 7164 SwapN(4, Ty, MIRBuilder, BSWAP, APInt::getSplat(Size, APInt(8, 0xF0))); 7165 7166 // swap high and low 2 bits in 4 bit blocks 32|10 76|54 -> 10|32 54|76 7167 // [(val & 0xCCCCCCCC) >> 2] & [(val & 0x33333333) << 2] 7168 // -> [(val & 0xCCCCCCCC) >> 2] & [(val << 2) & 0xCCCCCCCC] 7169 MachineInstrBuilder Swap2 = 7170 SwapN(2, Ty, MIRBuilder, Swap4, APInt::getSplat(Size, APInt(8, 0xCC))); 7171 7172 // swap high and low 1 bit in 2 bit blocks 1|0 3|2 5|4 7|6 -> 0|1 2|3 4|5 6|7 7173 // [(val & 0xAAAAAAAA) >> 1] & [(val & 0x55555555) << 1] 7174 // -> [(val & 0xAAAAAAAA) >> 1] & [(val << 1) & 0xAAAAAAAA] 7175 SwapN(1, Dst, MIRBuilder, Swap2, APInt::getSplat(Size, APInt(8, 0xAA))); 7176 7177 MI.eraseFromParent(); 7178 return Legalized; 7179 } 7180 7181 LegalizerHelper::LegalizeResult 7182 LegalizerHelper::lowerReadWriteRegister(MachineInstr &MI) { 7183 MachineFunction &MF = MIRBuilder.getMF(); 7184 7185 bool IsRead = MI.getOpcode() == TargetOpcode::G_READ_REGISTER; 7186 int NameOpIdx = IsRead ? 1 : 0; 7187 int ValRegIndex = IsRead ? 0 : 1; 7188 7189 Register ValReg = MI.getOperand(ValRegIndex).getReg(); 7190 const LLT Ty = MRI.getType(ValReg); 7191 const MDString *RegStr = cast<MDString>( 7192 cast<MDNode>(MI.getOperand(NameOpIdx).getMetadata())->getOperand(0)); 7193 7194 Register PhysReg = TLI.getRegisterByName(RegStr->getString().data(), Ty, MF); 7195 if (!PhysReg.isValid()) 7196 return UnableToLegalize; 7197 7198 if (IsRead) 7199 MIRBuilder.buildCopy(ValReg, PhysReg); 7200 else 7201 MIRBuilder.buildCopy(PhysReg, ValReg); 7202 7203 MI.eraseFromParent(); 7204 return Legalized; 7205 } 7206 7207 LegalizerHelper::LegalizeResult 7208 LegalizerHelper::lowerSMULH_UMULH(MachineInstr &MI) { 7209 bool IsSigned = MI.getOpcode() == TargetOpcode::G_SMULH; 7210 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT; 7211 Register Result = MI.getOperand(0).getReg(); 7212 LLT OrigTy = MRI.getType(Result); 7213 auto SizeInBits = OrigTy.getScalarSizeInBits(); 7214 LLT WideTy = OrigTy.changeElementSize(SizeInBits * 2); 7215 7216 auto LHS = MIRBuilder.buildInstr(ExtOp, {WideTy}, {MI.getOperand(1)}); 7217 auto RHS = MIRBuilder.buildInstr(ExtOp, {WideTy}, {MI.getOperand(2)}); 7218 auto Mul = MIRBuilder.buildMul(WideTy, LHS, RHS); 7219 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR; 7220 7221 auto ShiftAmt = MIRBuilder.buildConstant(WideTy, SizeInBits); 7222 auto Shifted = MIRBuilder.buildInstr(ShiftOp, {WideTy}, {Mul, ShiftAmt}); 7223 MIRBuilder.buildTrunc(Result, Shifted); 7224 7225 MI.eraseFromParent(); 7226 return Legalized; 7227 } 7228 7229 LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) { 7230 // Implement vector G_SELECT in terms of XOR, AND, OR. 7231 Register DstReg = MI.getOperand(0).getReg(); 7232 Register MaskReg = MI.getOperand(1).getReg(); 7233 Register Op1Reg = MI.getOperand(2).getReg(); 7234 Register Op2Reg = MI.getOperand(3).getReg(); 7235 LLT DstTy = MRI.getType(DstReg); 7236 LLT MaskTy = MRI.getType(MaskReg); 7237 LLT Op1Ty = MRI.getType(Op1Reg); 7238 if (!DstTy.isVector()) 7239 return UnableToLegalize; 7240 7241 // Vector selects can have a scalar predicate. If so, splat into a vector and 7242 // finish for later legalization attempts to try again. 7243 if (MaskTy.isScalar()) { 7244 Register MaskElt = MaskReg; 7245 if (MaskTy.getSizeInBits() < DstTy.getScalarSizeInBits()) 7246 MaskElt = MIRBuilder.buildSExt(DstTy.getElementType(), MaskElt).getReg(0); 7247 // Generate a vector splat idiom to be pattern matched later. 7248 auto ShufSplat = MIRBuilder.buildShuffleSplat(DstTy, MaskElt); 7249 Observer.changingInstr(MI); 7250 MI.getOperand(1).setReg(ShufSplat.getReg(0)); 7251 Observer.changedInstr(MI); 7252 return Legalized; 7253 } 7254 7255 if (MaskTy.getSizeInBits() != Op1Ty.getSizeInBits()) { 7256 return UnableToLegalize; 7257 } 7258 7259 auto NotMask = MIRBuilder.buildNot(MaskTy, MaskReg); 7260 auto NewOp1 = MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg); 7261 auto NewOp2 = MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask); 7262 MIRBuilder.buildOr(DstReg, NewOp1, NewOp2); 7263 MI.eraseFromParent(); 7264 return Legalized; 7265 } 7266 7267 LegalizerHelper::LegalizeResult LegalizerHelper::lowerDIVREM(MachineInstr &MI) { 7268 // Split DIVREM into individual instructions. 7269 unsigned Opcode = MI.getOpcode(); 7270 7271 MIRBuilder.buildInstr( 7272 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV 7273 : TargetOpcode::G_UDIV, 7274 {MI.getOperand(0).getReg()}, {MI.getOperand(2), MI.getOperand(3)}); 7275 MIRBuilder.buildInstr( 7276 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM 7277 : TargetOpcode::G_UREM, 7278 {MI.getOperand(1).getReg()}, {MI.getOperand(2), MI.getOperand(3)}); 7279 MI.eraseFromParent(); 7280 return Legalized; 7281 } 7282 7283 LegalizerHelper::LegalizeResult 7284 LegalizerHelper::lowerAbsToAddXor(MachineInstr &MI) { 7285 // Expand %res = G_ABS %a into: 7286 // %v1 = G_ASHR %a, scalar_size-1 7287 // %v2 = G_ADD %a, %v1 7288 // %res = G_XOR %v2, %v1 7289 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 7290 Register OpReg = MI.getOperand(1).getReg(); 7291 auto ShiftAmt = 7292 MIRBuilder.buildConstant(DstTy, DstTy.getScalarSizeInBits() - 1); 7293 auto Shift = MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt); 7294 auto Add = MIRBuilder.buildAdd(DstTy, OpReg, Shift); 7295 MIRBuilder.buildXor(MI.getOperand(0).getReg(), Add, Shift); 7296 MI.eraseFromParent(); 7297 return Legalized; 7298 } 7299 7300 LegalizerHelper::LegalizeResult 7301 LegalizerHelper::lowerAbsToMaxNeg(MachineInstr &MI) { 7302 // Expand %res = G_ABS %a into: 7303 // %v1 = G_CONSTANT 0 7304 // %v2 = G_SUB %v1, %a 7305 // %res = G_SMAX %a, %v2 7306 Register SrcReg = MI.getOperand(1).getReg(); 7307 LLT Ty = MRI.getType(SrcReg); 7308 auto Zero = MIRBuilder.buildConstant(Ty, 0).getReg(0); 7309 auto Sub = MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0); 7310 MIRBuilder.buildSMax(MI.getOperand(0), SrcReg, Sub); 7311 MI.eraseFromParent(); 7312 return Legalized; 7313 } 7314 7315 LegalizerHelper::LegalizeResult 7316 LegalizerHelper::lowerVectorReduction(MachineInstr &MI) { 7317 Register SrcReg = MI.getOperand(1).getReg(); 7318 LLT SrcTy = MRI.getType(SrcReg); 7319 LLT DstTy = MRI.getType(SrcReg); 7320 7321 // The source could be a scalar if the IR type was <1 x sN>. 7322 if (SrcTy.isScalar()) { 7323 if (DstTy.getSizeInBits() > SrcTy.getSizeInBits()) 7324 return UnableToLegalize; // FIXME: handle extension. 7325 // This can be just a plain copy. 7326 Observer.changingInstr(MI); 7327 MI.setDesc(MIRBuilder.getTII().get(TargetOpcode::COPY)); 7328 Observer.changedInstr(MI); 7329 return Legalized; 7330 } 7331 return UnableToLegalize;; 7332 } 7333 7334 static bool shouldLowerMemFuncForSize(const MachineFunction &MF) { 7335 // On Darwin, -Os means optimize for size without hurting performance, so 7336 // only really optimize for size when -Oz (MinSize) is used. 7337 if (MF.getTarget().getTargetTriple().isOSDarwin()) 7338 return MF.getFunction().hasMinSize(); 7339 return MF.getFunction().hasOptSize(); 7340 } 7341 7342 // Returns a list of types to use for memory op lowering in MemOps. A partial 7343 // port of findOptimalMemOpLowering in TargetLowering. 7344 static bool findGISelOptimalMemOpLowering(std::vector<LLT> &MemOps, 7345 unsigned Limit, const MemOp &Op, 7346 unsigned DstAS, unsigned SrcAS, 7347 const AttributeList &FuncAttributes, 7348 const TargetLowering &TLI) { 7349 if (Op.isMemcpyWithFixedDstAlign() && Op.getSrcAlign() < Op.getDstAlign()) 7350 return false; 7351 7352 LLT Ty = TLI.getOptimalMemOpLLT(Op, FuncAttributes); 7353 7354 if (Ty == LLT()) { 7355 // Use the largest scalar type whose alignment constraints are satisfied. 7356 // We only need to check DstAlign here as SrcAlign is always greater or 7357 // equal to DstAlign (or zero). 7358 Ty = LLT::scalar(64); 7359 if (Op.isFixedDstAlign()) 7360 while (Op.getDstAlign() < Ty.getSizeInBytes() && 7361 !TLI.allowsMisalignedMemoryAccesses(Ty, DstAS, Op.getDstAlign())) 7362 Ty = LLT::scalar(Ty.getSizeInBytes()); 7363 assert(Ty.getSizeInBits() > 0 && "Could not find valid type"); 7364 // FIXME: check for the largest legal type we can load/store to. 7365 } 7366 7367 unsigned NumMemOps = 0; 7368 uint64_t Size = Op.size(); 7369 while (Size) { 7370 unsigned TySize = Ty.getSizeInBytes(); 7371 while (TySize > Size) { 7372 // For now, only use non-vector load / store's for the left-over pieces. 7373 LLT NewTy = Ty; 7374 // FIXME: check for mem op safety and legality of the types. Not all of 7375 // SDAGisms map cleanly to GISel concepts. 7376 if (NewTy.isVector()) 7377 NewTy = NewTy.getSizeInBits() > 64 ? LLT::scalar(64) : LLT::scalar(32); 7378 NewTy = LLT::scalar(PowerOf2Floor(NewTy.getSizeInBits() - 1)); 7379 unsigned NewTySize = NewTy.getSizeInBytes(); 7380 assert(NewTySize > 0 && "Could not find appropriate type"); 7381 7382 // If the new LLT cannot cover all of the remaining bits, then consider 7383 // issuing a (or a pair of) unaligned and overlapping load / store. 7384 bool Fast; 7385 // Need to get a VT equivalent for allowMisalignedMemoryAccesses(). 7386 MVT VT = getMVTForLLT(Ty); 7387 if (NumMemOps && Op.allowOverlap() && NewTySize < Size && 7388 TLI.allowsMisalignedMemoryAccesses( 7389 VT, DstAS, Op.isFixedDstAlign() ? Op.getDstAlign() : Align(1), 7390 MachineMemOperand::MONone, &Fast) && 7391 Fast) 7392 TySize = Size; 7393 else { 7394 Ty = NewTy; 7395 TySize = NewTySize; 7396 } 7397 } 7398 7399 if (++NumMemOps > Limit) 7400 return false; 7401 7402 MemOps.push_back(Ty); 7403 Size -= TySize; 7404 } 7405 7406 return true; 7407 } 7408 7409 static Type *getTypeForLLT(LLT Ty, LLVMContext &C) { 7410 if (Ty.isVector()) 7411 return FixedVectorType::get(IntegerType::get(C, Ty.getScalarSizeInBits()), 7412 Ty.getNumElements()); 7413 return IntegerType::get(C, Ty.getSizeInBits()); 7414 } 7415 7416 // Get a vectorized representation of the memset value operand, GISel edition. 7417 static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB) { 7418 MachineRegisterInfo &MRI = *MIB.getMRI(); 7419 unsigned NumBits = Ty.getScalarSizeInBits(); 7420 auto ValVRegAndVal = getIConstantVRegValWithLookThrough(Val, MRI); 7421 if (!Ty.isVector() && ValVRegAndVal) { 7422 APInt Scalar = ValVRegAndVal->Value.truncOrSelf(8); 7423 APInt SplatVal = APInt::getSplat(NumBits, Scalar); 7424 return MIB.buildConstant(Ty, SplatVal).getReg(0); 7425 } 7426 7427 // Extend the byte value to the larger type, and then multiply by a magic 7428 // value 0x010101... in order to replicate it across every byte. 7429 // Unless it's zero, in which case just emit a larger G_CONSTANT 0. 7430 if (ValVRegAndVal && ValVRegAndVal->Value == 0) { 7431 return MIB.buildConstant(Ty, 0).getReg(0); 7432 } 7433 7434 LLT ExtType = Ty.getScalarType(); 7435 auto ZExt = MIB.buildZExtOrTrunc(ExtType, Val); 7436 if (NumBits > 8) { 7437 APInt Magic = APInt::getSplat(NumBits, APInt(8, 0x01)); 7438 auto MagicMI = MIB.buildConstant(ExtType, Magic); 7439 Val = MIB.buildMul(ExtType, ZExt, MagicMI).getReg(0); 7440 } 7441 7442 // For vector types create a G_BUILD_VECTOR. 7443 if (Ty.isVector()) 7444 Val = MIB.buildSplatVector(Ty, Val).getReg(0); 7445 7446 return Val; 7447 } 7448 7449 LegalizerHelper::LegalizeResult 7450 LegalizerHelper::lowerMemset(MachineInstr &MI, Register Dst, Register Val, 7451 uint64_t KnownLen, Align Alignment, 7452 bool IsVolatile) { 7453 auto &MF = *MI.getParent()->getParent(); 7454 const auto &TLI = *MF.getSubtarget().getTargetLowering(); 7455 auto &DL = MF.getDataLayout(); 7456 LLVMContext &C = MF.getFunction().getContext(); 7457 7458 assert(KnownLen != 0 && "Have a zero length memset length!"); 7459 7460 bool DstAlignCanChange = false; 7461 MachineFrameInfo &MFI = MF.getFrameInfo(); 7462 bool OptSize = shouldLowerMemFuncForSize(MF); 7463 7464 MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI); 7465 if (FIDef && !MFI.isFixedObjectIndex(FIDef->getOperand(1).getIndex())) 7466 DstAlignCanChange = true; 7467 7468 unsigned Limit = TLI.getMaxStoresPerMemset(OptSize); 7469 std::vector<LLT> MemOps; 7470 7471 const auto &DstMMO = **MI.memoperands_begin(); 7472 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo(); 7473 7474 auto ValVRegAndVal = getIConstantVRegValWithLookThrough(Val, MRI); 7475 bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0; 7476 7477 if (!findGISelOptimalMemOpLowering(MemOps, Limit, 7478 MemOp::Set(KnownLen, DstAlignCanChange, 7479 Alignment, 7480 /*IsZeroMemset=*/IsZeroVal, 7481 /*IsVolatile=*/IsVolatile), 7482 DstPtrInfo.getAddrSpace(), ~0u, 7483 MF.getFunction().getAttributes(), TLI)) 7484 return UnableToLegalize; 7485 7486 if (DstAlignCanChange) { 7487 // Get an estimate of the type from the LLT. 7488 Type *IRTy = getTypeForLLT(MemOps[0], C); 7489 Align NewAlign = DL.getABITypeAlign(IRTy); 7490 if (NewAlign > Alignment) { 7491 Alignment = NewAlign; 7492 unsigned FI = FIDef->getOperand(1).getIndex(); 7493 // Give the stack frame object a larger alignment if needed. 7494 if (MFI.getObjectAlign(FI) < Alignment) 7495 MFI.setObjectAlignment(FI, Alignment); 7496 } 7497 } 7498 7499 MachineIRBuilder MIB(MI); 7500 // Find the largest store and generate the bit pattern for it. 7501 LLT LargestTy = MemOps[0]; 7502 for (unsigned i = 1; i < MemOps.size(); i++) 7503 if (MemOps[i].getSizeInBits() > LargestTy.getSizeInBits()) 7504 LargestTy = MemOps[i]; 7505 7506 // The memset stored value is always defined as an s8, so in order to make it 7507 // work with larger store types we need to repeat the bit pattern across the 7508 // wider type. 7509 Register MemSetValue = getMemsetValue(Val, LargestTy, MIB); 7510 7511 if (!MemSetValue) 7512 return UnableToLegalize; 7513 7514 // Generate the stores. For each store type in the list, we generate the 7515 // matching store of that type to the destination address. 7516 LLT PtrTy = MRI.getType(Dst); 7517 unsigned DstOff = 0; 7518 unsigned Size = KnownLen; 7519 for (unsigned I = 0; I < MemOps.size(); I++) { 7520 LLT Ty = MemOps[I]; 7521 unsigned TySize = Ty.getSizeInBytes(); 7522 if (TySize > Size) { 7523 // Issuing an unaligned load / store pair that overlaps with the previous 7524 // pair. Adjust the offset accordingly. 7525 assert(I == MemOps.size() - 1 && I != 0); 7526 DstOff -= TySize - Size; 7527 } 7528 7529 // If this store is smaller than the largest store see whether we can get 7530 // the smaller value for free with a truncate. 7531 Register Value = MemSetValue; 7532 if (Ty.getSizeInBits() < LargestTy.getSizeInBits()) { 7533 MVT VT = getMVTForLLT(Ty); 7534 MVT LargestVT = getMVTForLLT(LargestTy); 7535 if (!LargestTy.isVector() && !Ty.isVector() && 7536 TLI.isTruncateFree(LargestVT, VT)) 7537 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0); 7538 else 7539 Value = getMemsetValue(Val, Ty, MIB); 7540 if (!Value) 7541 return UnableToLegalize; 7542 } 7543 7544 auto *StoreMMO = MF.getMachineMemOperand(&DstMMO, DstOff, Ty); 7545 7546 Register Ptr = Dst; 7547 if (DstOff != 0) { 7548 auto Offset = 7549 MIB.buildConstant(LLT::scalar(PtrTy.getSizeInBits()), DstOff); 7550 Ptr = MIB.buildPtrAdd(PtrTy, Dst, Offset).getReg(0); 7551 } 7552 7553 MIB.buildStore(Value, Ptr, *StoreMMO); 7554 DstOff += Ty.getSizeInBytes(); 7555 Size -= TySize; 7556 } 7557 7558 MI.eraseFromParent(); 7559 return Legalized; 7560 } 7561 7562 LegalizerHelper::LegalizeResult 7563 LegalizerHelper::lowerMemcpyInline(MachineInstr &MI) { 7564 assert(MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE); 7565 7566 Register Dst = MI.getOperand(0).getReg(); 7567 Register Src = MI.getOperand(1).getReg(); 7568 Register Len = MI.getOperand(2).getReg(); 7569 7570 const auto *MMOIt = MI.memoperands_begin(); 7571 const MachineMemOperand *MemOp = *MMOIt; 7572 bool IsVolatile = MemOp->isVolatile(); 7573 7574 // See if this is a constant length copy 7575 auto LenVRegAndVal = getIConstantVRegValWithLookThrough(Len, MRI); 7576 // FIXME: support dynamically sized G_MEMCPY_INLINE 7577 assert(LenVRegAndVal.hasValue() && 7578 "inline memcpy with dynamic size is not yet supported"); 7579 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue(); 7580 if (KnownLen == 0) { 7581 MI.eraseFromParent(); 7582 return Legalized; 7583 } 7584 7585 const auto &DstMMO = **MI.memoperands_begin(); 7586 const auto &SrcMMO = **std::next(MI.memoperands_begin()); 7587 Align DstAlign = DstMMO.getBaseAlign(); 7588 Align SrcAlign = SrcMMO.getBaseAlign(); 7589 7590 return lowerMemcpyInline(MI, Dst, Src, KnownLen, DstAlign, SrcAlign, 7591 IsVolatile); 7592 } 7593 7594 LegalizerHelper::LegalizeResult 7595 LegalizerHelper::lowerMemcpyInline(MachineInstr &MI, Register Dst, Register Src, 7596 uint64_t KnownLen, Align DstAlign, 7597 Align SrcAlign, bool IsVolatile) { 7598 assert(MI.getOpcode() == TargetOpcode::G_MEMCPY_INLINE); 7599 return lowerMemcpy(MI, Dst, Src, KnownLen, 7600 std::numeric_limits<uint64_t>::max(), DstAlign, SrcAlign, 7601 IsVolatile); 7602 } 7603 7604 LegalizerHelper::LegalizeResult 7605 LegalizerHelper::lowerMemcpy(MachineInstr &MI, Register Dst, Register Src, 7606 uint64_t KnownLen, uint64_t Limit, Align DstAlign, 7607 Align SrcAlign, bool IsVolatile) { 7608 auto &MF = *MI.getParent()->getParent(); 7609 const auto &TLI = *MF.getSubtarget().getTargetLowering(); 7610 auto &DL = MF.getDataLayout(); 7611 LLVMContext &C = MF.getFunction().getContext(); 7612 7613 assert(KnownLen != 0 && "Have a zero length memcpy length!"); 7614 7615 bool DstAlignCanChange = false; 7616 MachineFrameInfo &MFI = MF.getFrameInfo(); 7617 Align Alignment = commonAlignment(DstAlign, SrcAlign); 7618 7619 MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI); 7620 if (FIDef && !MFI.isFixedObjectIndex(FIDef->getOperand(1).getIndex())) 7621 DstAlignCanChange = true; 7622 7623 // FIXME: infer better src pointer alignment like SelectionDAG does here. 7624 // FIXME: also use the equivalent of isMemSrcFromConstant and alwaysinlining 7625 // if the memcpy is in a tail call position. 7626 7627 std::vector<LLT> MemOps; 7628 7629 const auto &DstMMO = **MI.memoperands_begin(); 7630 const auto &SrcMMO = **std::next(MI.memoperands_begin()); 7631 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo(); 7632 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo(); 7633 7634 if (!findGISelOptimalMemOpLowering( 7635 MemOps, Limit, 7636 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign, 7637 IsVolatile), 7638 DstPtrInfo.getAddrSpace(), SrcPtrInfo.getAddrSpace(), 7639 MF.getFunction().getAttributes(), TLI)) 7640 return UnableToLegalize; 7641 7642 if (DstAlignCanChange) { 7643 // Get an estimate of the type from the LLT. 7644 Type *IRTy = getTypeForLLT(MemOps[0], C); 7645 Align NewAlign = DL.getABITypeAlign(IRTy); 7646 7647 // Don't promote to an alignment that would require dynamic stack 7648 // realignment. 7649 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 7650 if (!TRI->hasStackRealignment(MF)) 7651 while (NewAlign > Alignment && DL.exceedsNaturalStackAlignment(NewAlign)) 7652 NewAlign = NewAlign / 2; 7653 7654 if (NewAlign > Alignment) { 7655 Alignment = NewAlign; 7656 unsigned FI = FIDef->getOperand(1).getIndex(); 7657 // Give the stack frame object a larger alignment if needed. 7658 if (MFI.getObjectAlign(FI) < Alignment) 7659 MFI.setObjectAlignment(FI, Alignment); 7660 } 7661 } 7662 7663 LLVM_DEBUG(dbgs() << "Inlining memcpy: " << MI << " into loads & stores\n"); 7664 7665 MachineIRBuilder MIB(MI); 7666 // Now we need to emit a pair of load and stores for each of the types we've 7667 // collected. I.e. for each type, generate a load from the source pointer of 7668 // that type width, and then generate a corresponding store to the dest buffer 7669 // of that value loaded. This can result in a sequence of loads and stores 7670 // mixed types, depending on what the target specifies as good types to use. 7671 unsigned CurrOffset = 0; 7672 unsigned Size = KnownLen; 7673 for (auto CopyTy : MemOps) { 7674 // Issuing an unaligned load / store pair that overlaps with the previous 7675 // pair. Adjust the offset accordingly. 7676 if (CopyTy.getSizeInBytes() > Size) 7677 CurrOffset -= CopyTy.getSizeInBytes() - Size; 7678 7679 // Construct MMOs for the accesses. 7680 auto *LoadMMO = 7681 MF.getMachineMemOperand(&SrcMMO, CurrOffset, CopyTy.getSizeInBytes()); 7682 auto *StoreMMO = 7683 MF.getMachineMemOperand(&DstMMO, CurrOffset, CopyTy.getSizeInBytes()); 7684 7685 // Create the load. 7686 Register LoadPtr = Src; 7687 Register Offset; 7688 if (CurrOffset != 0) { 7689 LLT SrcTy = MRI.getType(Src); 7690 Offset = MIB.buildConstant(LLT::scalar(SrcTy.getSizeInBits()), CurrOffset) 7691 .getReg(0); 7692 LoadPtr = MIB.buildPtrAdd(SrcTy, Src, Offset).getReg(0); 7693 } 7694 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO); 7695 7696 // Create the store. 7697 Register StorePtr = Dst; 7698 if (CurrOffset != 0) { 7699 LLT DstTy = MRI.getType(Dst); 7700 StorePtr = MIB.buildPtrAdd(DstTy, Dst, Offset).getReg(0); 7701 } 7702 MIB.buildStore(LdVal, StorePtr, *StoreMMO); 7703 CurrOffset += CopyTy.getSizeInBytes(); 7704 Size -= CopyTy.getSizeInBytes(); 7705 } 7706 7707 MI.eraseFromParent(); 7708 return Legalized; 7709 } 7710 7711 LegalizerHelper::LegalizeResult 7712 LegalizerHelper::lowerMemmove(MachineInstr &MI, Register Dst, Register Src, 7713 uint64_t KnownLen, Align DstAlign, Align SrcAlign, 7714 bool IsVolatile) { 7715 auto &MF = *MI.getParent()->getParent(); 7716 const auto &TLI = *MF.getSubtarget().getTargetLowering(); 7717 auto &DL = MF.getDataLayout(); 7718 LLVMContext &C = MF.getFunction().getContext(); 7719 7720 assert(KnownLen != 0 && "Have a zero length memmove length!"); 7721 7722 bool DstAlignCanChange = false; 7723 MachineFrameInfo &MFI = MF.getFrameInfo(); 7724 bool OptSize = shouldLowerMemFuncForSize(MF); 7725 Align Alignment = commonAlignment(DstAlign, SrcAlign); 7726 7727 MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI); 7728 if (FIDef && !MFI.isFixedObjectIndex(FIDef->getOperand(1).getIndex())) 7729 DstAlignCanChange = true; 7730 7731 unsigned Limit = TLI.getMaxStoresPerMemmove(OptSize); 7732 std::vector<LLT> MemOps; 7733 7734 const auto &DstMMO = **MI.memoperands_begin(); 7735 const auto &SrcMMO = **std::next(MI.memoperands_begin()); 7736 MachinePointerInfo DstPtrInfo = DstMMO.getPointerInfo(); 7737 MachinePointerInfo SrcPtrInfo = SrcMMO.getPointerInfo(); 7738 7739 // FIXME: SelectionDAG always passes false for 'AllowOverlap', apparently due 7740 // to a bug in it's findOptimalMemOpLowering implementation. For now do the 7741 // same thing here. 7742 if (!findGISelOptimalMemOpLowering( 7743 MemOps, Limit, 7744 MemOp::Copy(KnownLen, DstAlignCanChange, Alignment, SrcAlign, 7745 /*IsVolatile*/ true), 7746 DstPtrInfo.getAddrSpace(), SrcPtrInfo.getAddrSpace(), 7747 MF.getFunction().getAttributes(), TLI)) 7748 return UnableToLegalize; 7749 7750 if (DstAlignCanChange) { 7751 // Get an estimate of the type from the LLT. 7752 Type *IRTy = getTypeForLLT(MemOps[0], C); 7753 Align NewAlign = DL.getABITypeAlign(IRTy); 7754 7755 // Don't promote to an alignment that would require dynamic stack 7756 // realignment. 7757 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 7758 if (!TRI->hasStackRealignment(MF)) 7759 while (NewAlign > Alignment && DL.exceedsNaturalStackAlignment(NewAlign)) 7760 NewAlign = NewAlign / 2; 7761 7762 if (NewAlign > Alignment) { 7763 Alignment = NewAlign; 7764 unsigned FI = FIDef->getOperand(1).getIndex(); 7765 // Give the stack frame object a larger alignment if needed. 7766 if (MFI.getObjectAlign(FI) < Alignment) 7767 MFI.setObjectAlignment(FI, Alignment); 7768 } 7769 } 7770 7771 LLVM_DEBUG(dbgs() << "Inlining memmove: " << MI << " into loads & stores\n"); 7772 7773 MachineIRBuilder MIB(MI); 7774 // Memmove requires that we perform the loads first before issuing the stores. 7775 // Apart from that, this loop is pretty much doing the same thing as the 7776 // memcpy codegen function. 7777 unsigned CurrOffset = 0; 7778 SmallVector<Register, 16> LoadVals; 7779 for (auto CopyTy : MemOps) { 7780 // Construct MMO for the load. 7781 auto *LoadMMO = 7782 MF.getMachineMemOperand(&SrcMMO, CurrOffset, CopyTy.getSizeInBytes()); 7783 7784 // Create the load. 7785 Register LoadPtr = Src; 7786 if (CurrOffset != 0) { 7787 LLT SrcTy = MRI.getType(Src); 7788 auto Offset = 7789 MIB.buildConstant(LLT::scalar(SrcTy.getSizeInBits()), CurrOffset); 7790 LoadPtr = MIB.buildPtrAdd(SrcTy, Src, Offset).getReg(0); 7791 } 7792 LoadVals.push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0)); 7793 CurrOffset += CopyTy.getSizeInBytes(); 7794 } 7795 7796 CurrOffset = 0; 7797 for (unsigned I = 0; I < MemOps.size(); ++I) { 7798 LLT CopyTy = MemOps[I]; 7799 // Now store the values loaded. 7800 auto *StoreMMO = 7801 MF.getMachineMemOperand(&DstMMO, CurrOffset, CopyTy.getSizeInBytes()); 7802 7803 Register StorePtr = Dst; 7804 if (CurrOffset != 0) { 7805 LLT DstTy = MRI.getType(Dst); 7806 auto Offset = 7807 MIB.buildConstant(LLT::scalar(DstTy.getSizeInBits()), CurrOffset); 7808 StorePtr = MIB.buildPtrAdd(DstTy, Dst, Offset).getReg(0); 7809 } 7810 MIB.buildStore(LoadVals[I], StorePtr, *StoreMMO); 7811 CurrOffset += CopyTy.getSizeInBytes(); 7812 } 7813 MI.eraseFromParent(); 7814 return Legalized; 7815 } 7816 7817 LegalizerHelper::LegalizeResult 7818 LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) { 7819 const unsigned Opc = MI.getOpcode(); 7820 // This combine is fairly complex so it's not written with a separate 7821 // matcher function. 7822 assert((Opc == TargetOpcode::G_MEMCPY || Opc == TargetOpcode::G_MEMMOVE || 7823 Opc == TargetOpcode::G_MEMSET) && 7824 "Expected memcpy like instruction"); 7825 7826 auto MMOIt = MI.memoperands_begin(); 7827 const MachineMemOperand *MemOp = *MMOIt; 7828 7829 Align DstAlign = MemOp->getBaseAlign(); 7830 Align SrcAlign; 7831 Register Dst = MI.getOperand(0).getReg(); 7832 Register Src = MI.getOperand(1).getReg(); 7833 Register Len = MI.getOperand(2).getReg(); 7834 7835 if (Opc != TargetOpcode::G_MEMSET) { 7836 assert(MMOIt != MI.memoperands_end() && "Expected a second MMO on MI"); 7837 MemOp = *(++MMOIt); 7838 SrcAlign = MemOp->getBaseAlign(); 7839 } 7840 7841 // See if this is a constant length copy 7842 auto LenVRegAndVal = getIConstantVRegValWithLookThrough(Len, MRI); 7843 if (!LenVRegAndVal) 7844 return UnableToLegalize; 7845 uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue(); 7846 7847 if (KnownLen == 0) { 7848 MI.eraseFromParent(); 7849 return Legalized; 7850 } 7851 7852 bool IsVolatile = MemOp->isVolatile(); 7853 if (Opc == TargetOpcode::G_MEMCPY_INLINE) 7854 return lowerMemcpyInline(MI, Dst, Src, KnownLen, DstAlign, SrcAlign, 7855 IsVolatile); 7856 7857 // Don't try to optimize volatile. 7858 if (IsVolatile) 7859 return UnableToLegalize; 7860 7861 if (MaxLen && KnownLen > MaxLen) 7862 return UnableToLegalize; 7863 7864 if (Opc == TargetOpcode::G_MEMCPY) { 7865 auto &MF = *MI.getParent()->getParent(); 7866 const auto &TLI = *MF.getSubtarget().getTargetLowering(); 7867 bool OptSize = shouldLowerMemFuncForSize(MF); 7868 uint64_t Limit = TLI.getMaxStoresPerMemcpy(OptSize); 7869 return lowerMemcpy(MI, Dst, Src, KnownLen, Limit, DstAlign, SrcAlign, 7870 IsVolatile); 7871 } 7872 if (Opc == TargetOpcode::G_MEMMOVE) 7873 return lowerMemmove(MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile); 7874 if (Opc == TargetOpcode::G_MEMSET) 7875 return lowerMemset(MI, Dst, Src, KnownLen, DstAlign, IsVolatile); 7876 return UnableToLegalize; 7877 } 7878