44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
63 unsigned NumParts =
Size / NarrowSize;
64 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
67 if (LeftoverSize == 0)
72 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
130 auto Step = LI.getAction(
MI, MRI);
131 switch (Step.Action) {
146 return bitcast(
MI, Step.TypeIdx, Step.NewType);
149 return lower(
MI, Step.TypeIdx, Step.NewType);
158 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
166void LegalizerHelper::insertParts(
Register DstReg,
188 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
190 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
191 return mergeMixedSubvectors(DstReg, AllRegs);
197 extractGCDType(GCDRegs, GCDTy, PartReg);
198 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
199 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
204 LLT Ty = MRI.getType(
Reg);
212void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
215 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
216 appendVectorElts(AllElts, PartRegs[i]);
219 if (!MRI.getType(Leftover).isVector())
222 appendVectorElts(AllElts, Leftover);
224 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
230 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
232 const int StartIdx = Regs.
size();
233 const int NumResults =
MI.getNumOperands() - 1;
235 for (
int I = 0;
I != NumResults; ++
I)
236 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
241 LLT SrcTy = MRI.getType(SrcReg);
242 if (SrcTy == GCDTy) {
248 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
255 LLT SrcTy = MRI.getType(SrcReg);
257 extractGCDType(Parts, GCDTy, SrcReg);
261LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
263 unsigned PadStrategy) {
268 int NumOrigSrc = VRegs.
size();
274 if (NumOrigSrc < NumParts * NumSubParts) {
275 if (PadStrategy == TargetOpcode::G_ZEXT)
276 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
277 else if (PadStrategy == TargetOpcode::G_ANYEXT)
278 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
280 assert(PadStrategy == TargetOpcode::G_SEXT);
285 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
301 for (
int I = 0;
I != NumParts; ++
I) {
302 bool AllMergePartsArePadding =
true;
305 for (
int J = 0; J != NumSubParts; ++J) {
306 int Idx =
I * NumSubParts + J;
307 if (Idx >= NumOrigSrc) {
308 SubMerge[J] = PadReg;
312 SubMerge[J] = VRegs[Idx];
315 AllMergePartsArePadding =
false;
321 if (AllMergePartsArePadding && !AllPadReg) {
322 if (PadStrategy == TargetOpcode::G_ANYEXT)
323 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
324 else if (PadStrategy == TargetOpcode::G_ZEXT)
325 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
334 Remerge[
I] = AllPadReg;
338 if (NumSubParts == 1)
339 Remerge[
I] = SubMerge[0];
341 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
344 if (AllMergePartsArePadding && !AllPadReg)
345 AllPadReg = Remerge[
I];
348 VRegs = std::move(Remerge);
352void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
354 LLT DstTy = MRI.getType(DstReg);
359 if (DstTy == LCMTy) {
360 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
364 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
373 UnmergeDefs[0] = DstReg;
374 for (
unsigned I = 1;
I != NumDefs; ++
I)
375 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
378 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
386#define RTLIBCASE_INT(LibcallPrefix) \
390 return RTLIB::LibcallPrefix##32; \
392 return RTLIB::LibcallPrefix##64; \
394 return RTLIB::LibcallPrefix##128; \
396 llvm_unreachable("unexpected size"); \
400#define RTLIBCASE(LibcallPrefix) \
404 return RTLIB::LibcallPrefix##32; \
406 return RTLIB::LibcallPrefix##64; \
408 return RTLIB::LibcallPrefix##80; \
410 return RTLIB::LibcallPrefix##128; \
412 llvm_unreachable("unexpected size"); \
417 case TargetOpcode::G_LROUND:
419 case TargetOpcode::G_LLROUND:
421 case TargetOpcode::G_MUL:
423 case TargetOpcode::G_SDIV:
425 case TargetOpcode::G_UDIV:
427 case TargetOpcode::G_SREM:
429 case TargetOpcode::G_UREM:
431 case TargetOpcode::G_CTLZ_ZERO_POISON:
433 case TargetOpcode::G_FADD:
435 case TargetOpcode::G_FSUB:
437 case TargetOpcode::G_FMUL:
439 case TargetOpcode::G_FDIV:
441 case TargetOpcode::G_FEXP:
443 case TargetOpcode::G_FEXP2:
445 case TargetOpcode::G_FEXP10:
447 case TargetOpcode::G_FREM:
449 case TargetOpcode::G_FPOW:
451 case TargetOpcode::G_FPOWI:
453 case TargetOpcode::G_FMA:
455 case TargetOpcode::G_FSIN:
457 case TargetOpcode::G_FCOS:
459 case TargetOpcode::G_FTAN:
461 case TargetOpcode::G_FASIN:
463 case TargetOpcode::G_FACOS:
465 case TargetOpcode::G_FATAN:
467 case TargetOpcode::G_FATAN2:
469 case TargetOpcode::G_FSINH:
471 case TargetOpcode::G_FCOSH:
473 case TargetOpcode::G_FTANH:
475 case TargetOpcode::G_FSINCOS:
477 case TargetOpcode::G_FMODF:
479 case TargetOpcode::G_FLOG10:
481 case TargetOpcode::G_FLOG:
483 case TargetOpcode::G_FLOG2:
485 case TargetOpcode::G_FLDEXP:
487 case TargetOpcode::G_FCEIL:
489 case TargetOpcode::G_FFLOOR:
491 case TargetOpcode::G_FMINNUM:
493 case TargetOpcode::G_FMAXNUM:
495 case TargetOpcode::G_FMINIMUMNUM:
497 case TargetOpcode::G_FMAXIMUMNUM:
499 case TargetOpcode::G_FSQRT:
501 case TargetOpcode::G_FRINT:
503 case TargetOpcode::G_FNEARBYINT:
505 case TargetOpcode::G_INTRINSIC_TRUNC:
507 case TargetOpcode::G_INTRINSIC_ROUND:
509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
511 case TargetOpcode::G_INTRINSIC_LRINT:
513 case TargetOpcode::G_INTRINSIC_LLRINT:
525 Attribute::SwiftError);
540 AttributeList CallerAttrs =
F.getAttributes();
541 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
542 .removeAttribute(Attribute::NoAlias)
543 .removeAttribute(Attribute::NonNull)
548 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
549 CallerAttrs.hasRetAttr(Attribute::SExt))
560 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
567 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
575 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
578 if (Ret->getNumImplicitOperands() != 1)
581 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
598 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
603 Info.OrigRet = Result;
606 (Result.Ty->isVoidTy() ||
607 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
618 if (
MI && Info.LoweredTailCall) {
619 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
629 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
630 "Expected instr following MI to be return or debug inst?");
633 Next->eraseFromParent();
634 }
while (
MI->getNextNode());
649 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
650 if (LibcallImpl == RTLIB::Unsupported)
654 const CallingConv::ID CC = Libcalls->getLibcallImplCallingConv(LibcallImpl);
668 Args.push_back({MO.getReg(), OpType, 0});
687 unsigned AddrSpace =
DL.getAllocaAddrSpace();
705 if (LibcallResult != LegalizeResult::Legalized)
713 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
714 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
715 MI.eraseFromParent();
730 LLT DstTy = MRI.getType(DstFrac);
735 unsigned AddrSpace =
DL.getAllocaAddrSpace();
736 MachinePointerInfo PtrInfo;
745 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
748 if (LibcallResult != LegalizeResult::Legalized)
754 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
755 MI.eraseFromParent();
766 case TargetOpcode::G_FPEXT:
768 case TargetOpcode::G_FPTRUNC:
770 case TargetOpcode::G_FPTOSI:
772 case TargetOpcode::G_FPTOUI:
774 case TargetOpcode::G_SITOFP:
776 case TargetOpcode::G_UITOFP:
786 if (FromType->isIntegerTy()) {
787 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
788 Arg.
Flags[0].setSExt();
790 Arg.
Flags[0].setZExt();
801 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
805 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
809 LLT OpLLT = MRI.getType(Reg);
815 Args.push_back({Reg,
OpTy, 0});
818 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
819 RTLIB::Libcall RTLibcall;
820 unsigned Opc =
MI.getOpcode();
822 case TargetOpcode::G_BZERO:
823 RTLibcall = RTLIB::BZERO;
825 case TargetOpcode::G_MEMCPY:
826 RTLibcall = RTLIB::MEMCPY;
827 Args[0].Flags[0].setReturned();
829 case TargetOpcode::G_MEMMOVE:
830 RTLibcall = RTLIB::MEMMOVE;
831 Args[0].Flags[0].setReturned();
833 case TargetOpcode::G_MEMSET:
834 RTLibcall = RTLIB::MEMSET;
835 Args[0].Flags[0].setReturned();
844 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
847 if (RTLibcallImpl == RTLIB::Unsupported) {
854 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
861 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
871 if (Info.LoweredTailCall) {
872 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
882 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
883 "Expected instr following MI to be return or debug inst?");
886 Next->eraseFromParent();
887 }
while (
MI.getNextNode());
897 unsigned Opc =
MI.getOpcode();
899 auto &MMO = AtomicMI.getMMO();
900 auto Ordering = MMO.getMergedOrdering();
901 LLT MemType = MMO.getMemoryType();
904 return RTLIB::UNKNOWN_LIBCALL;
906#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
908 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
910 case TargetOpcode::G_ATOMIC_CMPXCHG:
911 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
912 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
913 return getOutlineAtomicHelper(LC, Ordering, MemSize);
915 case TargetOpcode::G_ATOMICRMW_XCHG: {
916 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
917 return getOutlineAtomicHelper(LC, Ordering, MemSize);
919 case TargetOpcode::G_ATOMICRMW_ADD:
920 case TargetOpcode::G_ATOMICRMW_SUB: {
921 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
922 return getOutlineAtomicHelper(LC, Ordering, MemSize);
924 case TargetOpcode::G_ATOMICRMW_AND: {
925 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
926 return getOutlineAtomicHelper(LC, Ordering, MemSize);
928 case TargetOpcode::G_ATOMICRMW_OR: {
929 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
930 return getOutlineAtomicHelper(LC, Ordering, MemSize);
932 case TargetOpcode::G_ATOMICRMW_XOR: {
933 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
934 return getOutlineAtomicHelper(LC, Ordering, MemSize);
937 return RTLIB::UNKNOWN_LIBCALL;
950 unsigned Opc =
MI.getOpcode();
952 case TargetOpcode::G_ATOMIC_CMPXCHG:
953 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
956 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
957 MI.getFirst4RegLLTs();
960 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
961 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
962 NewLLT) =
MI.getFirst5RegLLTs();
972 case TargetOpcode::G_ATOMICRMW_XCHG:
973 case TargetOpcode::G_ATOMICRMW_ADD:
974 case TargetOpcode::G_ATOMICRMW_SUB:
975 case TargetOpcode::G_ATOMICRMW_AND:
976 case TargetOpcode::G_ATOMICRMW_OR:
977 case TargetOpcode::G_ATOMICRMW_XOR: {
978 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
981 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
985 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
1000 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
1002 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
1005 if (RTLibcallImpl == RTLIB::Unsupported) {
1012 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
1026static RTLIB::Libcall
1028 RTLIB::Libcall RTLibcall;
1029 switch (
MI.getOpcode()) {
1030 case TargetOpcode::G_GET_FPENV:
1031 RTLibcall = RTLIB::FEGETENV;
1033 case TargetOpcode::G_SET_FPENV:
1034 case TargetOpcode::G_RESET_FPENV:
1035 RTLibcall = RTLIB::FESETENV;
1037 case TargetOpcode::G_GET_FPMODE:
1038 RTLibcall = RTLIB::FEGETMODE;
1040 case TargetOpcode::G_SET_FPMODE:
1041 case TargetOpcode::G_RESET_FPMODE:
1042 RTLibcall = RTLIB::FESETMODE;
1074 LLT StateTy = MRI.getType(Dst);
1077 MachinePointerInfo TempPtrInfo;
1081 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1086 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1094 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1112 LLT StateTy = MRI.getType(Src);
1115 MachinePointerInfo TempPtrInfo;
1124 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1129 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1130 LocObserver,
nullptr);
1136static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1138#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1142 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1144 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1146 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1148 llvm_unreachable("unexpected size"); \
1181 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1184 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1191 LLT DstTy = MRI.getType(DstReg);
1192 const auto Cond =
Cmp->getCond();
1197 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1202 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1206 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1213 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1219 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1221 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1234 const auto [OeqLibcall, OeqPred] =
1236 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1238 const auto [UnoLibcall, UnoPred] =
1240 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1255 const auto [OeqLibcall, OeqPred] =
1260 const auto [UnoLibcall, UnoPred] =
1265 if (NotOeq && NotUno)
1284 const auto [InversedLibcall, InversedPred] =
1286 if (!BuildLibcall(InversedLibcall,
1311 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1313 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1316 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1322 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1327 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1329 switch (
MI.getOpcode()) {
1332 case TargetOpcode::G_MUL:
1333 case TargetOpcode::G_SDIV:
1334 case TargetOpcode::G_UDIV:
1335 case TargetOpcode::G_SREM:
1336 case TargetOpcode::G_UREM:
1337 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1338 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1346 case TargetOpcode::G_FADD:
1347 case TargetOpcode::G_FSUB:
1348 case TargetOpcode::G_FMUL:
1349 case TargetOpcode::G_FDIV:
1350 case TargetOpcode::G_FMA:
1351 case TargetOpcode::G_FPOW:
1352 case TargetOpcode::G_FREM:
1353 case TargetOpcode::G_FCOS:
1354 case TargetOpcode::G_FSIN:
1355 case TargetOpcode::G_FTAN:
1356 case TargetOpcode::G_FACOS:
1357 case TargetOpcode::G_FASIN:
1358 case TargetOpcode::G_FATAN:
1359 case TargetOpcode::G_FATAN2:
1360 case TargetOpcode::G_FCOSH:
1361 case TargetOpcode::G_FSINH:
1362 case TargetOpcode::G_FTANH:
1363 case TargetOpcode::G_FLOG10:
1364 case TargetOpcode::G_FLOG:
1365 case TargetOpcode::G_FLOG2:
1366 case TargetOpcode::G_FEXP:
1367 case TargetOpcode::G_FEXP2:
1368 case TargetOpcode::G_FEXP10:
1369 case TargetOpcode::G_FCEIL:
1370 case TargetOpcode::G_FFLOOR:
1371 case TargetOpcode::G_FMINNUM:
1372 case TargetOpcode::G_FMAXNUM:
1373 case TargetOpcode::G_FMINIMUMNUM:
1374 case TargetOpcode::G_FMAXIMUMNUM:
1375 case TargetOpcode::G_FSQRT:
1376 case TargetOpcode::G_FRINT:
1377 case TargetOpcode::G_FNEARBYINT:
1378 case TargetOpcode::G_INTRINSIC_TRUNC:
1379 case TargetOpcode::G_INTRINSIC_ROUND:
1380 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1381 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1385 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1393 case TargetOpcode::G_FSINCOS: {
1394 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1398 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1403 case TargetOpcode::G_FMODF: {
1404 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1408 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1413 case TargetOpcode::G_LROUND:
1414 case TargetOpcode::G_LLROUND:
1415 case TargetOpcode::G_INTRINSIC_LRINT:
1416 case TargetOpcode::G_INTRINSIC_LLRINT: {
1417 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1421 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1423 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1429 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1432 MI.eraseFromParent();
1435 case TargetOpcode::G_FPOWI:
1436 case TargetOpcode::G_FLDEXP: {
1437 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1441 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1443 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1448 {
MI.getOperand(1).getReg(), HLTy, 0},
1449 {
MI.getOperand(2).getReg(), ITy, 1}};
1450 Args[1].Flags[0].setSExt();
1452 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1457 case TargetOpcode::G_FPEXT:
1458 case TargetOpcode::G_FPTRUNC: {
1461 if (!FromTy || !ToTy)
1468 case TargetOpcode::G_FCMP: {
1472 MI.eraseFromParent();
1475 case TargetOpcode::G_FPTOSI:
1476 case TargetOpcode::G_FPTOUI: {
1480 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1481 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1484 FromTy, LocObserver);
1489 case TargetOpcode::G_SITOFP:
1490 case TargetOpcode::G_UITOFP: {
1491 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1494 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1496 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1503 case TargetOpcode::G_ATOMICRMW_XCHG:
1504 case TargetOpcode::G_ATOMICRMW_ADD:
1505 case TargetOpcode::G_ATOMICRMW_SUB:
1506 case TargetOpcode::G_ATOMICRMW_AND:
1507 case TargetOpcode::G_ATOMICRMW_OR:
1508 case TargetOpcode::G_ATOMICRMW_XOR:
1509 case TargetOpcode::G_ATOMIC_CMPXCHG:
1510 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1516 case TargetOpcode::G_BZERO:
1517 case TargetOpcode::G_MEMCPY:
1518 case TargetOpcode::G_MEMMOVE:
1519 case TargetOpcode::G_MEMSET: {
1524 MI.eraseFromParent();
1527 case TargetOpcode::G_GET_FPENV:
1528 case TargetOpcode::G_GET_FPMODE: {
1534 case TargetOpcode::G_SET_FPENV:
1535 case TargetOpcode::G_SET_FPMODE: {
1541 case TargetOpcode::G_RESET_FPENV:
1542 case TargetOpcode::G_RESET_FPMODE: {
1550 MI.eraseFromParent();
1557 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1560 switch (
MI.getOpcode()) {
1563 case TargetOpcode::G_IMPLICIT_DEF: {
1565 LLT DstTy = MRI.getType(DstReg);
1573 if (SizeOp0 % NarrowSize != 0) {
1578 MI.eraseFromParent();
1582 int NumParts = SizeOp0 / NarrowSize;
1585 for (
int i = 0; i < NumParts; ++i)
1589 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1591 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1592 MI.eraseFromParent();
1595 case TargetOpcode::G_CONSTANT: {
1596 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1597 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1598 unsigned TotalSize = Ty.getSizeInBits();
1600 int NumParts = TotalSize / NarrowSize;
1603 for (
int I = 0;
I != NumParts; ++
I) {
1604 unsigned Offset =
I * NarrowSize;
1611 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1613 if (LeftoverBits != 0) {
1617 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1621 insertParts(
MI.getOperand(0).getReg(),
1622 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1624 MI.eraseFromParent();
1627 case TargetOpcode::G_SEXT:
1628 case TargetOpcode::G_ZEXT:
1629 case TargetOpcode::G_ANYEXT:
1631 case TargetOpcode::G_TRUNC: {
1635 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1637 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1641 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1642 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1643 MI.eraseFromParent();
1646 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1647 case TargetOpcode::G_FREEZE: {
1651 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1656 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1658 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1660 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1664 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1665 MI.eraseFromParent();
1668 case TargetOpcode::G_ADD:
1669 case TargetOpcode::G_SUB:
1670 case TargetOpcode::G_SADDO:
1671 case TargetOpcode::G_SSUBO:
1672 case TargetOpcode::G_SADDE:
1673 case TargetOpcode::G_SSUBE:
1674 case TargetOpcode::G_UADDO:
1675 case TargetOpcode::G_USUBO:
1676 case TargetOpcode::G_UADDE:
1677 case TargetOpcode::G_USUBE:
1679 case TargetOpcode::G_MUL:
1680 case TargetOpcode::G_UMULH:
1682 case TargetOpcode::G_EXTRACT:
1684 case TargetOpcode::G_INSERT:
1686 case TargetOpcode::G_LOAD: {
1688 Register DstReg = LoadMI.getDstReg();
1689 LLT DstTy = MRI.getType(DstReg);
1693 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1694 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1695 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1697 LoadMI.eraseFromParent();
1703 case TargetOpcode::G_ZEXTLOAD:
1704 case TargetOpcode::G_SEXTLOAD:
1705 case TargetOpcode::G_FPEXTLOAD: {
1707 Register DstReg = LoadMI.getDstReg();
1708 Register PtrReg = LoadMI.getPointerReg();
1710 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1711 auto &MMO = LoadMI.getMMO();
1714 if (MemSize == NarrowSize) {
1716 }
else if (MemSize < NarrowSize) {
1717 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1718 }
else if (MemSize > NarrowSize) {
1730 LoadMI.eraseFromParent();
1733 case TargetOpcode::G_STORE: {
1736 Register SrcReg = StoreMI.getValueReg();
1737 LLT SrcTy = MRI.getType(SrcReg);
1738 if (SrcTy.isVector())
1741 int NumParts = SizeOp0 / NarrowSize;
1743 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1744 if (SrcTy.isVector() && LeftoverBits != 0)
1747 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1748 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1750 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1751 StoreMI.eraseFromParent();
1757 case TargetOpcode::G_FPTRUNCSTORE: {
1759 Register SrcReg = StoreMI.getValueReg();
1760 Register PtrReg = StoreMI.getPointerReg();
1762 auto &MMO = StoreMI.getMMO();
1764 if (MemSize > NarrowSize) {
1768 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1769 if (MemSize == NarrowSize) {
1771 }
else if (MemSize < NarrowSize) {
1772 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1776 StoreMI.eraseFromParent();
1779 case TargetOpcode::G_SELECT:
1781 case TargetOpcode::G_AND:
1782 case TargetOpcode::G_OR:
1783 case TargetOpcode::G_XOR: {
1795 case TargetOpcode::G_SHL:
1796 case TargetOpcode::G_LSHR:
1797 case TargetOpcode::G_ASHR:
1799 case TargetOpcode::G_CTLZ:
1800 case TargetOpcode::G_CTLZ_ZERO_POISON:
1801 case TargetOpcode::G_CTTZ:
1802 case TargetOpcode::G_CTTZ_ZERO_POISON:
1803 case TargetOpcode::G_CTLS:
1804 case TargetOpcode::G_CTPOP:
1806 switch (
MI.getOpcode()) {
1807 case TargetOpcode::G_CTLZ:
1808 case TargetOpcode::G_CTLZ_ZERO_POISON:
1810 case TargetOpcode::G_CTTZ:
1811 case TargetOpcode::G_CTTZ_ZERO_POISON:
1813 case TargetOpcode::G_CTPOP:
1815 case TargetOpcode::G_CTLS:
1825 case TargetOpcode::G_INTTOPTR:
1833 case TargetOpcode::G_PTRTOINT:
1841 case TargetOpcode::G_PHI: {
1844 if (SizeOp0 % NarrowSize != 0)
1847 unsigned NumParts = SizeOp0 / NarrowSize;
1851 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1859 for (
unsigned i = 0; i < NumParts; ++i) {
1860 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1862 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1863 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1864 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1867 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1869 MI.eraseFromParent();
1872 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1873 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1877 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1883 case TargetOpcode::G_ICMP: {
1885 LLT SrcTy = MRI.getType(LHS);
1891 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1897 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1898 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1904 LLT ResTy = MRI.getType(Dst);
1909 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1911 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1912 auto LHS = std::get<0>(LHSAndRHS);
1913 auto RHS = std::get<1>(LHSAndRHS);
1914 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1921 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1922 auto LHS = std::get<0>(LHSAndRHS);
1923 auto RHS = std::get<1>(LHSAndRHS);
1924 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1925 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1926 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1927 TargetOpcode::G_ZEXT);
1934 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1935 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1936 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1941 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1945 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1950 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1954 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1957 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1960 LHSPartRegs[
I], RHSPartRegs[
I]);
1961 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1967 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1976 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1980 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1981 RHSLeftoverRegs[
I]);
1983 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1984 RHSLeftoverRegs[
I]);
1987 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1988 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1994 MI.eraseFromParent();
1997 case TargetOpcode::G_FCMP:
2006 case TargetOpcode::G_SEXT_INREG: {
2010 int64_t SizeInBits =
MI.getOperand(2).getImm();
2019 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2020 MO1.
setReg(TruncMIB.getReg(0));
2023 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2035 if (SizeOp0 % NarrowSize != 0)
2037 int NumParts = SizeOp0 / NarrowSize;
2045 for (
int i = 0; i < NumParts; ++i) {
2046 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2061 for (
int i = 0; i < NumParts; ++i) {
2064 PartialExtensionReg = DstRegs.
back();
2066 assert(PartialExtensionReg &&
2067 "Expected to visit partial extension before full");
2068 if (FullExtensionReg) {
2073 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2075 FullExtensionReg = DstRegs.
back();
2080 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2083 PartialExtensionReg = DstRegs.
back();
2089 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2090 MI.eraseFromParent();
2093 case TargetOpcode::G_BSWAP:
2094 case TargetOpcode::G_BITREVERSE: {
2095 if (SizeOp0 % NarrowSize != 0)
2100 unsigned NumParts = SizeOp0 / NarrowSize;
2101 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2104 for (
unsigned i = 0; i < NumParts; ++i) {
2105 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2106 {SrcRegs[NumParts - 1 - i]});
2110 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2113 MI.eraseFromParent();
2116 case TargetOpcode::G_PTR_ADD:
2117 case TargetOpcode::G_PTRMASK: {
2125 case TargetOpcode::G_FPTOUI:
2126 case TargetOpcode::G_FPTOSI:
2127 case TargetOpcode::G_FPTOUI_SAT:
2128 case TargetOpcode::G_FPTOSI_SAT:
2130 case TargetOpcode::G_FPEXT:
2137 case TargetOpcode::G_FLDEXP:
2138 case TargetOpcode::G_STRICT_FLDEXP:
2140 case TargetOpcode::G_VSCALE: {
2142 LLT Ty = MRI.getType(Dst);
2146 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2147 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2148 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2151 MI.eraseFromParent();
2158 LLT Ty = MRI.getType(Val);
2159 if (Ty.isScalar() && !Ty.isFloat())
2166 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2168 if (Ty.isPointer()) {
2169 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2171 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2177 if (Ty.isPointerVector())
2178 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2179 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2183 unsigned OpIdx,
unsigned ExtOpcode) {
2185 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2186 MO.
setReg(ExtB.getReg(0));
2192 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2194 MO.
setReg(ExtB.getReg(0));
2200 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2201 MO.
setReg(ExtB.getReg(0));
2205 unsigned OpIdx,
unsigned TruncOpcode) {
2207 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2209 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2216 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2218 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2223 unsigned OpIdx,
unsigned ExtOpcode) {
2225 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2227 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2236 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2238 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2244 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2254 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2261LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2266 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2267 if (DstTy.isVector())
2272 const int SrcSize = SrcTy.getSizeInBits();
2274 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2276 unsigned NumOps =
MI.getNumOperands();
2277 unsigned NumSrc =
MI.getNumOperands() - 1;
2278 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2280 if (WideSize >= DstSize) {
2284 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2285 const unsigned Offset = (
I - 1) * PartSize;
2298 ResultReg = NextResult;
2301 if (WideSize > DstSize)
2303 else if (DstTy.isPointer())
2305 else if (DstTy != WideTy)
2308 MI.eraseFromParent();
2333 const int GCD = std::gcd(SrcSize, WideSize);
2343 if (GCD == SrcSize) {
2346 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2347 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2353 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2355 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2359 const int PartsPerGCD = WideSize / GCD;
2363 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2365 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2372 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2374 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2375 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2378 MI.eraseFromParent();
2383LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2388 int NumDst =
MI.getNumOperands() - 1;
2389 Register SrcReg =
MI.getOperand(NumDst).getReg();
2390 LLT SrcTy = MRI.getType(SrcReg);
2394 Register Dst0Reg =
MI.getOperand(0).getReg();
2395 LLT DstTy = MRI.getType(Dst0Reg);
2404 dbgs() <<
"Not casting non-integral address space integer\n");
2409 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2417 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2426 SrcTy = MRI.getType(SrcReg);
2430 for (
int I = 1;
I != NumDst; ++
I) {
2431 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2432 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2436 MI.eraseFromParent();
2447 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2451 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2454 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2472 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2477 if (PartsPerRemerge == 1) {
2480 for (
int I = 0;
I != NumUnmerge; ++
I) {
2481 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2483 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2484 int Idx =
I * PartsPerUnmerge + J;
2486 MIB.addDef(
MI.getOperand(Idx).getReg());
2489 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2493 MIB.addUse(Unmerge.getReg(
I));
2496 SmallVector<Register, 16> Parts;
2497 for (
int J = 0; J != NumUnmerge; ++J)
2498 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2501 for (
int I = 0;
I != NumDst; ++
I) {
2502 for (
int J = 0; J < PartsPerRemerge; ++J) {
2503 const int Idx =
I * PartsPerRemerge + J;
2507 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2508 RemergeParts.
clear();
2512 MI.eraseFromParent();
2517LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2519 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2520 unsigned Offset =
MI.getOperand(2).getImm();
2523 if (SrcTy.
isVector() || DstTy.isVector())
2535 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2539 if (DstTy.isPointer())
2546 MI.eraseFromParent();
2551 LLT ShiftTy = SrcTy;
2560 MI.eraseFromParent();
2591LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2593 if (TypeIdx != 0 || WideTy.
isVector())
2603LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2607 std::optional<Register> CarryIn;
2608 switch (
MI.getOpcode()) {
2611 case TargetOpcode::G_SADDO:
2612 Opcode = TargetOpcode::G_ADD;
2613 ExtOpcode = TargetOpcode::G_SEXT;
2615 case TargetOpcode::G_SSUBO:
2616 Opcode = TargetOpcode::G_SUB;
2617 ExtOpcode = TargetOpcode::G_SEXT;
2619 case TargetOpcode::G_UADDO:
2620 Opcode = TargetOpcode::G_ADD;
2621 ExtOpcode = TargetOpcode::G_ZEXT;
2623 case TargetOpcode::G_USUBO:
2624 Opcode = TargetOpcode::G_SUB;
2625 ExtOpcode = TargetOpcode::G_ZEXT;
2627 case TargetOpcode::G_SADDE:
2628 Opcode = TargetOpcode::G_UADDE;
2629 ExtOpcode = TargetOpcode::G_SEXT;
2630 CarryIn =
MI.getOperand(4).getReg();
2632 case TargetOpcode::G_SSUBE:
2633 Opcode = TargetOpcode::G_USUBE;
2634 ExtOpcode = TargetOpcode::G_SEXT;
2635 CarryIn =
MI.getOperand(4).getReg();
2637 case TargetOpcode::G_UADDE:
2638 Opcode = TargetOpcode::G_UADDE;
2639 ExtOpcode = TargetOpcode::G_ZEXT;
2640 CarryIn =
MI.getOperand(4).getReg();
2642 case TargetOpcode::G_USUBE:
2643 Opcode = TargetOpcode::G_USUBE;
2644 ExtOpcode = TargetOpcode::G_ZEXT;
2645 CarryIn =
MI.getOperand(4).getReg();
2661 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2662 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2666 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2668 .buildInstr(Opcode, {WideTy, CarryOutTy},
2669 {LHSExt, RHSExt, *CarryIn})
2672 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2674 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2675 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2676 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2681 MI.eraseFromParent();
2686LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2688 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2689 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2690 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2691 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2692 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2705 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2712 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2716 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2717 {ShiftL, ShiftR},
MI.getFlags());
2722 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2725 MI.eraseFromParent();
2730LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2739 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2741 LLT SrcTy = MRI.getType(
LHS);
2742 LLT OverflowTy = MRI.getType(OriginalOverflow);
2749 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2750 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2751 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2758 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2760 MachineInstrBuilder Mulo;
2761 if (WideMulCanOverflow)
2762 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2763 {LeftOperand, RightOperand});
2765 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2770 MachineInstrBuilder ExtResult;
2777 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2781 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2784 if (WideMulCanOverflow) {
2792 MI.eraseFromParent();
2798 unsigned Opcode =
MI.getOpcode();
2802 case TargetOpcode::G_ATOMICRMW_XCHG:
2803 case TargetOpcode::G_ATOMICRMW_ADD:
2804 case TargetOpcode::G_ATOMICRMW_SUB:
2805 case TargetOpcode::G_ATOMICRMW_AND:
2806 case TargetOpcode::G_ATOMICRMW_OR:
2807 case TargetOpcode::G_ATOMICRMW_XOR:
2808 case TargetOpcode::G_ATOMICRMW_MIN:
2809 case TargetOpcode::G_ATOMICRMW_MAX:
2810 case TargetOpcode::G_ATOMICRMW_UMIN:
2811 case TargetOpcode::G_ATOMICRMW_UMAX:
2812 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2818 case TargetOpcode::G_ATOMIC_CMPXCHG:
2819 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2826 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2836 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2841 case TargetOpcode::G_EXTRACT:
2842 return widenScalarExtract(
MI, TypeIdx, WideTy);
2843 case TargetOpcode::G_INSERT:
2844 return widenScalarInsert(
MI, TypeIdx, WideTy);
2845 case TargetOpcode::G_MERGE_VALUES:
2846 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2847 case TargetOpcode::G_UNMERGE_VALUES:
2848 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2849 case TargetOpcode::G_SADDO:
2850 case TargetOpcode::G_SSUBO:
2851 case TargetOpcode::G_UADDO:
2852 case TargetOpcode::G_USUBO:
2853 case TargetOpcode::G_SADDE:
2854 case TargetOpcode::G_SSUBE:
2855 case TargetOpcode::G_UADDE:
2856 case TargetOpcode::G_USUBE:
2857 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2858 case TargetOpcode::G_UMULO:
2859 case TargetOpcode::G_SMULO:
2860 return widenScalarMulo(
MI, TypeIdx, WideTy);
2861 case TargetOpcode::G_SADDSAT:
2862 case TargetOpcode::G_SSUBSAT:
2863 case TargetOpcode::G_SSHLSAT:
2864 case TargetOpcode::G_UADDSAT:
2865 case TargetOpcode::G_USUBSAT:
2866 case TargetOpcode::G_USHLSAT:
2867 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2868 case TargetOpcode::G_CTTZ:
2869 case TargetOpcode::G_CTTZ_ZERO_POISON:
2870 case TargetOpcode::G_CTLZ:
2871 case TargetOpcode::G_CTLZ_ZERO_POISON:
2872 case TargetOpcode::G_CTLS:
2873 case TargetOpcode::G_CTPOP: {
2886 case TargetOpcode::G_CTTZ:
2887 case TargetOpcode::G_CTTZ_ZERO_POISON:
2888 case TargetOpcode::G_CTLZ_ZERO_POISON:
2889 ExtOpc = TargetOpcode::G_ANYEXT;
2891 case TargetOpcode::G_CTLS:
2892 ExtOpc = TargetOpcode::G_SEXT;
2895 ExtOpc = TargetOpcode::G_ZEXT;
2898 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2899 LLT CurTy = MRI.getType(SrcReg);
2900 unsigned NewOpc = Opcode;
2901 if (NewOpc == TargetOpcode::G_CTTZ) {
2908 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2910 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2916 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2926 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2928 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2933 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2934 Opcode == TargetOpcode::G_CTLZ
2939 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2940 MI.eraseFromParent();
2943 case TargetOpcode::G_BSWAP: {
2947 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2948 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2949 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2952 MI.getOperand(0).setReg(DstExt);
2956 LLT Ty = MRI.getType(DstReg);
2958 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2959 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2965 case TargetOpcode::G_BITREVERSE: {
2969 LLT Ty = MRI.getType(DstReg);
2972 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2974 MI.getOperand(0).setReg(DstExt);
2977 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2978 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2983 case TargetOpcode::G_FREEZE:
2984 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2991 case TargetOpcode::G_ABS:
2998 case TargetOpcode::G_ADD:
2999 case TargetOpcode::G_AND:
3000 case TargetOpcode::G_MUL:
3001 case TargetOpcode::G_OR:
3002 case TargetOpcode::G_XOR:
3003 case TargetOpcode::G_SUB:
3004 case TargetOpcode::G_SHUFFLE_VECTOR:
3015 case TargetOpcode::G_SBFX:
3016 case TargetOpcode::G_UBFX:
3030 case TargetOpcode::G_SHL:
3046 case TargetOpcode::G_ROTR:
3047 case TargetOpcode::G_ROTL:
3056 case TargetOpcode::G_SDIV:
3057 case TargetOpcode::G_SREM:
3058 case TargetOpcode::G_SMIN:
3059 case TargetOpcode::G_SMAX:
3060 case TargetOpcode::G_ABDS:
3068 case TargetOpcode::G_SDIVREM:
3078 case TargetOpcode::G_ASHR:
3079 case TargetOpcode::G_LSHR:
3083 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3084 : TargetOpcode::G_ZEXT;
3097 case TargetOpcode::G_UDIV:
3098 case TargetOpcode::G_UREM:
3099 case TargetOpcode::G_ABDU:
3106 case TargetOpcode::G_UDIVREM:
3115 case TargetOpcode::G_UMIN:
3116 case TargetOpcode::G_UMAX: {
3117 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3119 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3123 ? TargetOpcode::G_SEXT
3124 : TargetOpcode::G_ZEXT;
3134 case TargetOpcode::G_SELECT:
3144 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3151 case TargetOpcode::G_FPEXT:
3159 case TargetOpcode::G_FPTOSI:
3160 case TargetOpcode::G_FPTOUI:
3161 case TargetOpcode::G_INTRINSIC_LRINT:
3162 case TargetOpcode::G_INTRINSIC_LLRINT:
3163 case TargetOpcode::G_IS_FPCLASS:
3173 case TargetOpcode::G_SITOFP:
3183 case TargetOpcode::G_UITOFP:
3193 case TargetOpcode::G_FPTOSI_SAT:
3194 case TargetOpcode::G_FPTOUI_SAT:
3199 LLT Ty = MRI.getType(OldDst);
3200 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3202 MI.getOperand(0).setReg(ExtReg);
3203 uint64_t ShortBits = Ty.getScalarSizeInBits();
3206 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3217 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3218 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3226 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3234 case TargetOpcode::G_LOAD:
3235 case TargetOpcode::G_SEXTLOAD:
3236 case TargetOpcode::G_ZEXTLOAD:
3237 case TargetOpcode::G_FPEXTLOAD:
3243 case TargetOpcode::G_STORE: {
3247 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3248 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3249 if (!Ty.isScalar()) {
3257 MI.setMemRefs(MF, {NewMMO});
3264 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3265 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3271 case TargetOpcode::G_FPTRUNCSTORE:
3278 case TargetOpcode::G_CONSTANT: {
3281 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3282 MRI.getType(
MI.getOperand(0).getReg()));
3283 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3284 ExtOpc == TargetOpcode::G_ANYEXT) &&
3287 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3291 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3297 case TargetOpcode::G_FCONSTANT: {
3303 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3305 MI.eraseFromParent();
3308 case TargetOpcode::G_IMPLICIT_DEF: {
3314 case TargetOpcode::G_BRCOND:
3320 case TargetOpcode::G_FCMP:
3331 case TargetOpcode::G_ICMP:
3336 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3340 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3341 unsigned ExtOpcode =
3345 ? TargetOpcode::G_SEXT
3346 : TargetOpcode::G_ZEXT;
3353 case TargetOpcode::G_PTR_ADD:
3354 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3360 case TargetOpcode::G_PHI: {
3361 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3364 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3376 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3379 LLT VecTy = MRI.getType(VecReg);
3383 TargetOpcode::G_ANYEXT);
3397 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3413 LLT VecTy = MRI.getType(VecReg);
3432 case TargetOpcode::G_FADD:
3433 case TargetOpcode::G_FMUL:
3434 case TargetOpcode::G_FSUB:
3435 case TargetOpcode::G_FMA:
3436 case TargetOpcode::G_FMAD:
3437 case TargetOpcode::G_FNEG:
3438 case TargetOpcode::G_FABS:
3439 case TargetOpcode::G_FCANONICALIZE:
3440 case TargetOpcode::G_FMINNUM:
3441 case TargetOpcode::G_FMAXNUM:
3442 case TargetOpcode::G_FMINNUM_IEEE:
3443 case TargetOpcode::G_FMAXNUM_IEEE:
3444 case TargetOpcode::G_FMINIMUM:
3445 case TargetOpcode::G_FMAXIMUM:
3446 case TargetOpcode::G_FMINIMUMNUM:
3447 case TargetOpcode::G_FMAXIMUMNUM:
3448 case TargetOpcode::G_FDIV:
3449 case TargetOpcode::G_FREM:
3450 case TargetOpcode::G_FCEIL:
3451 case TargetOpcode::G_FFLOOR:
3452 case TargetOpcode::G_FCOS:
3453 case TargetOpcode::G_FSIN:
3454 case TargetOpcode::G_FTAN:
3455 case TargetOpcode::G_FACOS:
3456 case TargetOpcode::G_FASIN:
3457 case TargetOpcode::G_FATAN:
3458 case TargetOpcode::G_FATAN2:
3459 case TargetOpcode::G_FCOSH:
3460 case TargetOpcode::G_FSINH:
3461 case TargetOpcode::G_FTANH:
3462 case TargetOpcode::G_FLOG10:
3463 case TargetOpcode::G_FLOG:
3464 case TargetOpcode::G_FLOG2:
3465 case TargetOpcode::G_FRINT:
3466 case TargetOpcode::G_FNEARBYINT:
3467 case TargetOpcode::G_FSQRT:
3468 case TargetOpcode::G_FEXP:
3469 case TargetOpcode::G_FEXP2:
3470 case TargetOpcode::G_FEXP10:
3471 case TargetOpcode::G_FPOW:
3472 case TargetOpcode::G_INTRINSIC_TRUNC:
3473 case TargetOpcode::G_INTRINSIC_ROUND:
3474 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3478 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3484 case TargetOpcode::G_FMODF: {
3494 case TargetOpcode::G_FPOWI:
3495 case TargetOpcode::G_FLDEXP:
3496 case TargetOpcode::G_STRICT_FLDEXP: {
3498 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3519 case TargetOpcode::G_FFREXP: {
3532 case TargetOpcode::G_LROUND:
3533 case TargetOpcode::G_LLROUND:
3544 case TargetOpcode::G_INTTOPTR:
3552 case TargetOpcode::G_PTRTOINT:
3560 case TargetOpcode::G_BUILD_VECTOR: {
3564 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3570 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3578 case TargetOpcode::G_SEXT_INREG:
3587 case TargetOpcode::G_PTRMASK: {
3595 case TargetOpcode::G_VECREDUCE_ADD: {
3604 case TargetOpcode::G_VECREDUCE_FADD:
3605 case TargetOpcode::G_VECREDUCE_FMUL:
3606 case TargetOpcode::G_VECREDUCE_FMIN:
3607 case TargetOpcode::G_VECREDUCE_FMAX:
3608 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3609 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3614 LLT VecTy = MRI.getType(VecReg);
3621 case TargetOpcode::G_VSCALE: {
3628 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3633 case TargetOpcode::G_SPLAT_VECTOR: {
3642 case TargetOpcode::G_INSERT_SUBVECTOR: {
3650 LLT SubVecTy = MRI.getType(SubVec);
3654 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3655 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3656 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3660 auto SplatZero =
MIRBuilder.buildSplatVector(
3665 MI.eraseFromParent();
3669 case TargetOpcode::G_BITCAST:
3681 if (MRI.getType(Dst) == MRI.getType(Src)) {
3682 Observer.changingAllUsesOfReg(MRI, Dst);
3683 MRI.replaceRegWith(Dst, Src);
3684 Observer.finishedChangingAllUsesOfReg();
3685 MI.eraseFromParent();
3694 auto Unmerge =
B.buildUnmerge(Ty, Src);
3695 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3704 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3718 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3727 MI.eraseFromParent();
3738 MI.eraseFromParent();
3745 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3746 if (SrcTy.isVector()) {
3750 if (DstTy.isVector()) {
3751 int NumDstElt = DstTy.getNumElements();
3752 int NumSrcElt = SrcTy.getNumElements();
3755 LLT DstCastTy = DstEltTy;
3756 LLT SrcPartTy = SrcEltTy;
3760 if (NumSrcElt < NumDstElt) {
3771 SrcPartTy = SrcEltTy;
3772 }
else if (NumSrcElt > NumDstElt) {
3784 DstCastTy = DstEltTy;
3789 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3793 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3794 MI.eraseFromParent();
3798 if (DstTy.isVector()) {
3801 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3802 MI.eraseFromParent();
3818 unsigned NewEltSize,
3819 unsigned OldEltSize) {
3820 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3821 LLT IdxTy =
B.getMRI()->getType(Idx);
3824 auto OffsetMask =
B.buildConstant(
3826 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3827 return B.buildShl(IdxTy, OffsetIdx,
3828 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3843 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3847 unsigned OldNumElts = SrcVecTy.getNumElements();
3854 if (NewNumElts > OldNumElts) {
3865 if (NewNumElts % OldNumElts != 0)
3869 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3873 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3876 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3878 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3879 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3880 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3881 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3882 NewOps[
I] = Elt.getReg(0);
3885 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3887 MI.eraseFromParent();
3891 if (NewNumElts < OldNumElts) {
3892 if (NewEltSize % OldEltSize != 0)
3914 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3915 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3918 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3922 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3923 ScaledIdx).getReg(0);
3931 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3933 MI.eraseFromParent();
3947 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3948 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3949 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3950 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3953 auto EltMask =
B.buildConstant(
3957 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3958 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3961 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3965 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3979 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3980 MI.getFirst4RegLLTs();
3992 if (NewNumElts < OldNumElts) {
3993 if (NewEltSize % OldEltSize != 0)
4002 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4003 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4006 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4010 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4011 ScaledIdx).getReg(0);
4021 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4022 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4026 MI.eraseFromParent();
4056 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4060 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4061 return UnableToLegalize;
4066 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4068 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4077 MI.eraseFromParent();
4095 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4096 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4106 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4107 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4109 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4110 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4112 MI.eraseFromParent();
4138 uint64_t Idx = ES->getIndexImm();
4142 LLT DstTy = MRI.getType(Dst);
4143 LLT SrcTy = MRI.getType(Src);
4149 if (DstTy == CastTy)
4157 if (CastEltSize < DstEltSize)
4160 auto AdjustAmt = CastEltSize / DstEltSize;
4161 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4162 SrcTyMinElts % AdjustAmt != 0)
4167 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4168 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4171 ES->eraseFromParent();
4202 uint64_t Idx = ES->getIndexImm();
4206 LLT DstTy = MRI.getType(Dst);
4207 LLT BigVecTy = MRI.getType(BigVec);
4208 LLT SubVecTy = MRI.getType(SubVec);
4210 if (DstTy == CastTy)
4225 if (CastEltSize < DstEltSize)
4228 auto AdjustAmt = CastEltSize / DstEltSize;
4229 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4230 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4236 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4237 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4239 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4242 ES->eraseFromParent();
4250 LLT DstTy = MRI.getType(DstReg);
4260 if (MemSizeInBits != MemStoreSizeInBits) {
4277 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4281 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4282 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4284 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4287 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4289 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4292 if (DstTy != LoadTy)
4300 if (
MIRBuilder.getDataLayout().isBigEndian())
4318 uint64_t LargeSplitSize, SmallSplitSize;
4323 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4330 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4333 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4344 if (Alignment.value() * 8 > MemSizeInBits &&
4349 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4366 LLT PtrTy = MRI.getType(PtrReg);
4379 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4382 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4383 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4384 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4386 SmallPtr, *SmallMMO);
4388 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4389 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4391 if (AnyExtTy == DstTy)
4392 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4394 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4398 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4418 LLT SrcTy = MRI.getType(SrcReg);
4426 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4432 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4434 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4438 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4442 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4457 uint64_t LargeSplitSize, SmallSplitSize;
4464 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4467 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4476 if (SrcTy.isPointer()) {
4481 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4484 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4485 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4488 LLT PtrTy = MRI.getType(PtrReg);
4490 LargeSplitSize / 8);
4491 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4497 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4498 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4507 LLT SrcTy = MRI.getType(SrcReg);
4513 assert(SrcTy.isVector() &&
"Expect a vector store type");
4520 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4524 auto Elt =
MIRBuilder.buildExtractVectorElement(
4525 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4526 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4527 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4533 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4534 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4538 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4549 switch (
MI.getOpcode()) {
4550 case TargetOpcode::G_LOAD: {
4568 case TargetOpcode::G_STORE: {
4584 case TargetOpcode::G_SELECT: {
4588 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4590 dbgs() <<
"bitcast action not implemented for vector select\n");
4601 case TargetOpcode::G_AND:
4602 case TargetOpcode::G_OR:
4603 case TargetOpcode::G_XOR: {
4611 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4613 case TargetOpcode::G_INSERT_VECTOR_ELT:
4615 case TargetOpcode::G_CONCAT_VECTORS:
4617 case TargetOpcode::G_SHUFFLE_VECTOR:
4619 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4621 case TargetOpcode::G_INSERT_SUBVECTOR:
4629void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4638 switch(
MI.getOpcode()) {
4641 case TargetOpcode::G_FCONSTANT:
4643 case TargetOpcode::G_BITCAST:
4645 case TargetOpcode::G_SREM:
4646 case TargetOpcode::G_UREM: {
4647 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4649 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4650 {MI.getOperand(1), MI.getOperand(2)});
4652 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4654 MI.eraseFromParent();
4657 case TargetOpcode::G_SADDO:
4658 case TargetOpcode::G_SSUBO:
4660 case TargetOpcode::G_SADDE:
4662 case TargetOpcode::G_SSUBE:
4664 case TargetOpcode::G_UMULH:
4665 case TargetOpcode::G_SMULH:
4667 case TargetOpcode::G_SMULO:
4668 case TargetOpcode::G_UMULO: {
4671 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4672 LLT Ty = MRI.getType(Res);
4674 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4675 ? TargetOpcode::G_SMULH
4676 : TargetOpcode::G_UMULH;
4680 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4681 MI.removeOperand(1);
4684 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4692 if (Opcode == TargetOpcode::G_SMULH) {
4693 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4694 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4701 case TargetOpcode::G_FNEG: {
4702 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4705 Register CastedSubByReg = SubByReg;
4707 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4708 !SubByRegTy.getScalarType().isInteger()) {
4709 auto BitcastDst = SubByRegTy.changeElementType(
4711 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4717 if (ResTy != TyInt) {
4719 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4722 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4724 MI.eraseFromParent();
4727 case TargetOpcode::G_FSUB:
4728 case TargetOpcode::G_STRICT_FSUB: {
4729 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4730 LLT Ty = MRI.getType(Res);
4735 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4736 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4740 MI.eraseFromParent();
4743 case TargetOpcode::G_FMAD:
4745 case TargetOpcode::G_FFLOOR:
4747 case TargetOpcode::G_LROUND:
4748 case TargetOpcode::G_LLROUND: {
4751 LLT SrcTy = MRI.getType(SrcReg);
4752 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4755 MI.eraseFromParent();
4758 case TargetOpcode::G_INTRINSIC_ROUND:
4760 case TargetOpcode::G_FRINT: {
4763 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4766 case TargetOpcode::G_INTRINSIC_LRINT:
4767 case TargetOpcode::G_INTRINSIC_LLRINT: {
4770 LLT SrcTy = MRI.getType(SrcReg);
4772 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4774 MI.eraseFromParent();
4777 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4778 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4779 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4780 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4781 **
MI.memoperands_begin());
4783 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4784 MI.eraseFromParent();
4787 case TargetOpcode::G_LOAD:
4788 case TargetOpcode::G_SEXTLOAD:
4789 case TargetOpcode::G_ZEXTLOAD:
4791 case TargetOpcode::G_STORE:
4793 case TargetOpcode::G_CTLZ_ZERO_POISON:
4794 case TargetOpcode::G_CTTZ_ZERO_POISON:
4795 case TargetOpcode::G_CTLZ:
4796 case TargetOpcode::G_CTTZ:
4797 case TargetOpcode::G_CTPOP:
4798 case TargetOpcode::G_CTLS:
4801 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4803 Register NewRes = MRI.cloneVirtualRegister(Res);
4810 MI.eraseFromParent();
4814 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4815 const LLT CondTy = MRI.getType(CarryOut);
4816 const LLT Ty = MRI.getType(Res);
4818 Register NewRes = MRI.cloneVirtualRegister(Res);
4821 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4827 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4828 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4835 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4840 MI.eraseFromParent();
4844 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4849 MI.eraseFromParent();
4853 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4854 const LLT CondTy = MRI.getType(BorrowOut);
4855 const LLT Ty = MRI.getType(Res);
4858 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4864 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4865 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4872 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4873 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4875 MI.eraseFromParent();
4915 case G_MERGE_VALUES:
4917 case G_UNMERGE_VALUES:
4919 case TargetOpcode::G_SEXT_INREG: {
4920 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4921 int64_t SizeInBits =
MI.getOperand(2).getImm();
4923 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4924 LLT DstTy = MRI.getType(DstReg);
4925 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4928 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4929 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4930 MI.eraseFromParent();
4933 case G_EXTRACT_VECTOR_ELT:
4934 case G_INSERT_VECTOR_ELT:
4936 case G_SHUFFLE_VECTOR:
4938 case G_VECTOR_COMPRESS:
4940 case G_DYN_STACKALLOC:
4942 case G_INSERT_SUBVECTOR: {
4943 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4944 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4949 Register Subvector =
MI.getOperand(2).getReg();
4950 auto InsertionPointImm =
MI.getOperand(3).getImm();
4953 LLT DstTy = MRI.getType(Subvector);
4957 bool InsertInLowHalf = InsertionPointImm == 0;
4958 auto Extract =
MIRBuilder.buildExtractSubvector(
4960 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
4962 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4963 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4965 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4966 {LowHalf, HighHalf});
4967 MI.eraseFromParent();
4973 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4974 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4980 if (i >= InsertionPointImm &&
4982 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4990 MI.eraseFromParent();
4994 case G_EXTRACT_SUBVECTOR: {
4997 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
4999 LLT SrcTy = MRI.getType(SrcReg);
5000 LLT DstTy = MRI.getType(DstReg);
5002 if (SrcTy.isScalable() || DstTy.
isScalable())
5013 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5014 ExtractionPointImm + i)
5018 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5019 MI.eraseFromParent();
5024 case G_STACKRESTORE:
5034 case G_READ_REGISTER:
5035 case G_WRITE_REGISTER:
5042 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5043 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5049 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5054 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5061 case G_TRUNC_SSAT_S:
5062 case G_TRUNC_USAT_U:
5063 case G_TRUNC_SSAT_U:
5069 bool IsSigned =
MI.getOpcode() == G_ABDS;
5070 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5071 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5072 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5095 case G_MEMCPY_INLINE:
5096 case G_MEMSET_INLINE:
5108 case G_ATOMICRMW_SUB: {
5109 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5110 const LLT ValTy = MRI.getType(Val);
5114 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5115 MI.eraseFromParent();
5143 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5147 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5153 Align StackTypeAlign =
5160 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5161 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5166 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5178 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5181 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5192 "Converting bits to bytes lost precision");
5198 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5199 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5201 if (IdxTy != MRI.getType(Index))
5202 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5207 LLT PtrTy = MRI.getType(VecPtr);
5208 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5216 std::initializer_list<unsigned> NonVecOpIndices) {
5217 if (
MI.getNumMemOperands() != 0)
5225 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5234 if (!Ty.isVector()) {
5240 if (Ty.getNumElements() != NumElts)
5255 assert(Ty.isVector() &&
"Expected vector type");
5257 int NumParts, NumLeftover;
5258 std::tie(NumParts, NumLeftover) =
5261 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5262 for (
int i = 0; i < NumParts; ++i) {
5267 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5276 for (
unsigned i = 0; i <
N; ++i) {
5278 Ops.push_back(
Op.getReg());
5279 else if (
Op.isImm())
5280 Ops.push_back(
Op.getImm());
5281 else if (
Op.isPredicate())
5303 std::initializer_list<unsigned> NonVecOpIndices) {
5305 "Non-compatible opcode or not specified non-vector operands");
5306 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5308 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5309 unsigned NumDefs =
MI.getNumDefs();
5317 for (
unsigned i = 0; i < NumDefs; ++i) {
5318 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5326 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5327 ++UseIdx, ++UseNo) {
5330 MI.getOperand(UseIdx));
5339 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5343 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5345 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5346 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5349 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5350 Uses.push_back(InputOpsPieces[InputNo][i]);
5353 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5354 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5359 for (
unsigned i = 0; i < NumDefs; ++i)
5360 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5362 for (
unsigned i = 0; i < NumDefs; ++i)
5363 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5366 MI.eraseFromParent();
5373 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5375 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5376 unsigned NumDefs =
MI.getNumDefs();
5380 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5385 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5386 UseIdx += 2, ++UseNo) {
5394 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5396 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5397 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5399 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5402 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5403 Phi.addUse(InputOpsPieces[j][i]);
5404 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5414 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5416 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5419 MI.eraseFromParent();
5427 const int NumDst =
MI.getNumOperands() - 1;
5428 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5429 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5430 LLT SrcTy = MRI.getType(SrcReg);
5432 if (TypeIdx != 1 || NarrowTy == DstTy)
5439 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5442 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5456 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5457 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5458 const int PartsPerUnmerge = NumDst / NumUnmerge;
5460 for (
int I = 0;
I != NumUnmerge; ++
I) {
5461 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5463 for (
int J = 0; J != PartsPerUnmerge; ++J)
5464 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5465 MIB.addUse(Unmerge.getReg(
I));
5468 MI.eraseFromParent();
5475 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5479 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5481 if (NarrowTy == SrcTy)
5489 assert(SrcTy.isVector() &&
"Expected vector types");
5491 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5505 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5506 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5507 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5513 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5514 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5515 ++i,
Offset += NumNarrowTyElts) {
5518 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5521 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5522 MI.eraseFromParent();
5526 assert(TypeIdx == 0 &&
"Bad type index");
5527 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5542 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5543 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5545 for (
unsigned i = 0; i < NumParts; ++i) {
5547 for (
unsigned j = 0; j < NumElts; ++j)
5548 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5550 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5553 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5554 MI.eraseFromParent();
5562 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5564 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5566 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5568 InsertVal =
MI.getOperand(2).getReg();
5570 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5571 LLT VecTy = MRI.getType(SrcVec);
5577 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5581 MI.eraseFromParent();
5590 SplitPieces[IdxVal] = InsertVal;
5591 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5593 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5597 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5600 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5601 TargetOpcode::G_ANYEXT);
5605 LLT IdxTy = MRI.getType(Idx);
5606 int64_t PartIdx = IdxVal / NewNumElts;
5608 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5611 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5614 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5615 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5616 VecParts[PartIdx] = InsertPart.getReg(0);
5620 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5622 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5626 MI.eraseFromParent();
5646 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5658 LLT ValTy = MRI.getType(ValReg);
5667 int NumLeftover = -1;
5673 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5675 NumParts = NarrowRegs.
size();
5676 NumLeftover = NarrowLeftoverRegs.
size();
5683 LLT PtrTy = MRI.getType(AddrReg);
5693 auto MMO = LdStMI.
getMMO();
5695 unsigned NumParts,
unsigned Offset) ->
unsigned {
5698 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5700 unsigned ByteOffset =
Offset / 8;
5703 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5710 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5711 ValRegs.push_back(Dst);
5712 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5714 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5723 unsigned HandledOffset =
5724 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5728 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5731 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5732 LeftoverTy, NarrowLeftoverRegs);
5746 switch (
MI.getOpcode()) {
5747 case G_IMPLICIT_DEF:
5763 case G_FCANONICALIZE:
5780 case G_INTRINSIC_LRINT:
5781 case G_INTRINSIC_LLRINT:
5782 case G_INTRINSIC_ROUND:
5783 case G_INTRINSIC_ROUNDEVEN:
5786 case G_INTRINSIC_TRUNC:
5814 case G_FMINNUM_IEEE:
5815 case G_FMAXNUM_IEEE:
5837 case G_CTLZ_ZERO_POISON:
5839 case G_CTTZ_ZERO_POISON:
5856 case G_ADDRSPACE_CAST:
5869 case G_STRICT_FLDEXP:
5871 case G_TRUNC_SSAT_S:
5872 case G_TRUNC_SSAT_U:
5873 case G_TRUNC_USAT_U:
5881 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5886 case G_UNMERGE_VALUES:
5888 case G_BUILD_VECTOR:
5889 assert(TypeIdx == 0 &&
"not a vector type index");
5891 case G_CONCAT_VECTORS:
5895 case G_EXTRACT_SUBVECTOR: {
5897 LLT DstTy = MRI.getType(DstReg);
5899 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5909 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5910 uint64_t RequiredSubvectorIndex =
5914 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5917 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5920 MI.eraseFromParent();
5923 case G_EXTRACT_VECTOR_ELT:
5924 case G_INSERT_VECTOR_ELT:
5933 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5934 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5936 case G_SHUFFLE_VECTOR:
5942 case G_INTRINSIC_FPTRUNC_ROUND:
5952 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5953 "Not a bitcast operation");
5958 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5960 unsigned NewElemCount =
5963 if (NewElemCount == 1) {
5966 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5973 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5982 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5983 MI.eraseFromParent();
5989 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5993 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5994 MI.getFirst3RegLLTs();
5997 if (DstTy != Src1Ty)
5999 if (DstTy != Src2Ty)
6014 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6030 unsigned InputUsed[2] = {-1U, -1U};
6031 unsigned FirstMaskIdx =
High * NewElts;
6032 bool UseBuildVector =
false;
6033 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6035 int Idx = Mask[FirstMaskIdx + MaskOffset];
6040 if (
Input >= std::size(Inputs)) {
6047 Idx -=
Input * NewElts;
6051 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6052 if (InputUsed[OpNo] ==
Input) {
6055 }
else if (InputUsed[OpNo] == -1U) {
6057 InputUsed[OpNo] =
Input;
6062 if (OpNo >= std::size(InputUsed)) {
6065 UseBuildVector =
true;
6070 Ops.push_back(Idx + OpNo * NewElts);
6073 if (UseBuildVector) {
6078 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6080 int Idx = Mask[FirstMaskIdx + MaskOffset];
6085 if (
Input >= std::size(Inputs)) {
6092 Idx -=
Input * NewElts;
6096 .buildExtractVectorElement(
6097 EltTy, Inputs[
Input],
6103 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6104 }
else if (InputUsed[0] == -1U) {
6106 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6107 }
else if (NewElts == 1) {
6108 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6110 Register Op0 = Inputs[InputUsed[0]];
6114 : Inputs[InputUsed[1]];
6116 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6123 MI.eraseFromParent();
6136 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6142 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6145 const unsigned NumParts =
6147 : SrcTy.getNumElements();
6151 if (DstTy != NarrowTy)
6157 unsigned NumPartsLeft = NumParts;
6158 while (NumPartsLeft > 1) {
6159 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6162 .buildInstr(ScalarOpc, {NarrowTy},
6163 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6166 SplitSrcs = PartialResults;
6167 PartialResults.
clear();
6168 NumPartsLeft = SplitSrcs.
size();
6172 MI.eraseFromParent();
6177 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6178 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6181 MI.eraseFromParent();
6185 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6187 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6195 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6198 Register Acc = PartialReductions[0];
6199 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6200 if (Part == NumParts - 1) {
6202 {Acc, PartialReductions[Part]});
6205 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6209 MI.eraseFromParent();
6215 unsigned int TypeIdx,
6217 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6218 MI.getFirst3RegLLTs();
6219 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6223 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6224 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6225 "Unexpected vecreduce opcode");
6226 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6227 ? TargetOpcode::G_FADD
6228 : TargetOpcode::G_FMUL;
6231 unsigned NumParts = SrcTy.getNumElements();
6234 for (
unsigned i = 0; i < NumParts; i++)
6235 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6239 MI.eraseFromParent();
6246 unsigned ScalarOpc) {
6254 while (SplitSrcs.
size() > 1) {
6256 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6264 SplitSrcs = std::move(PartialRdxs);
6268 MI.getOperand(1).setReg(SplitSrcs[0]);
6275 const LLT HalfTy,
const LLT AmtTy) {
6277 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6278 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6282 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6283 MI.eraseFromParent();
6289 unsigned VTBits = 2 * NVTBits;
6292 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6293 if (Amt.
ugt(VTBits)) {
6295 }
else if (Amt.
ugt(NVTBits)) {
6298 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6299 }
else if (Amt == NVTBits) {
6307 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6310 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6311 if (Amt.
ugt(VTBits)) {
6313 }
else if (Amt.
ugt(NVTBits)) {
6315 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6317 }
else if (Amt == NVTBits) {
6321 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6323 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6325 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6331 if (Amt.
ugt(VTBits)) {
6333 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6334 }
else if (Amt.
ugt(NVTBits)) {
6336 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6338 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6339 }
else if (Amt == NVTBits) {
6342 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6344 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6346 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6348 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6355 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6356 MI.eraseFromParent();
6372 LLT DstTy = MRI.getType(DstReg);
6377 LLT ShiftAmtTy = MRI.getType(Amt);
6379 if (DstEltSize % 2 != 0)
6395 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6406 const unsigned NewBitSize = DstEltSize / 2;
6418 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6420 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6421 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6424 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6425 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6427 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6432 switch (
MI.getOpcode()) {
6433 case TargetOpcode::G_SHL: {
6435 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6437 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6438 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6439 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6442 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6443 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6445 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6447 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6449 ResultRegs[0] =
Lo.getReg(0);
6450 ResultRegs[1] =
Hi.getReg(0);
6453 case TargetOpcode::G_LSHR:
6454 case TargetOpcode::G_ASHR: {
6456 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6458 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6459 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6460 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6464 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6467 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6468 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6470 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6474 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6476 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6478 ResultRegs[0] =
Lo.getReg(0);
6479 ResultRegs[1] =
Hi.getReg(0);
6486 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6487 MI.eraseFromParent();
6496 LLT TargetTy,
LLT ShiftAmtTy) {
6499 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6501 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6502 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6503 const bool NeedsInterWordShift = ShiftBits != 0;
6506 case TargetOpcode::G_SHL: {
6509 if (PartIdx < ShiftWords)
6512 unsigned SrcIdx = PartIdx - ShiftWords;
6513 if (!NeedsInterWordShift)
6514 return SrcParts[SrcIdx];
6519 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6523 return Hi.getReg(0);
6526 case TargetOpcode::G_LSHR: {
6527 unsigned SrcIdx = PartIdx + ShiftWords;
6528 if (SrcIdx >= NumParts)
6530 if (!NeedsInterWordShift)
6531 return SrcParts[SrcIdx];
6535 if (SrcIdx + 1 < NumParts) {
6536 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6540 return Lo.getReg(0);
6543 case TargetOpcode::G_ASHR: {
6545 unsigned SrcIdx = PartIdx + ShiftWords;
6546 if (SrcIdx >= NumParts)
6548 if (!NeedsInterWordShift)
6549 return SrcParts[SrcIdx];
6554 (SrcIdx == NumParts - 1)
6558 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6580 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6581 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6586 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6595 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6596 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6598 auto IsZeroBitShift =
6606 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6607 : TargetOpcode::G_SHL;
6610 auto TargetBitsConst =
6612 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6617 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6622 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6624 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6628 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6641 LLT DstTy = MRI.getType(DstReg);
6645 const unsigned NumParts = DstBits / TargetBits;
6647 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6657 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6658 MI.eraseFromParent();
6663 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6664 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6670 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6674 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6677 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6678 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6682 for (
unsigned I = 0;
I < NumParts; ++
I)
6684 Params, TargetTy, ShiftAmtTy);
6686 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6687 MI.eraseFromParent();
6696 LLT DstTy = MRI.getType(DstReg);
6697 LLT ShiftAmtTy = MRI.getType(AmtReg);
6701 const unsigned NumParts = DstBits / TargetBits;
6703 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6720 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6732 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6733 auto TargetBitsLog2Const =
6734 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6735 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6738 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6740 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6748 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6749 auto TargetBitsMinusOneConst =
6750 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6752 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6753 TargetBitsMinusOneConst)
6756 FillValue = ZeroReg;
6764 for (
unsigned I = 0;
I < NumParts; ++
I) {
6766 Register InBoundsResult = FillValue;
6776 for (
unsigned K = 0; K < NumParts; ++K) {
6777 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6779 WordShift, WordShiftKConst);
6791 switch (
MI.getOpcode()) {
6792 case TargetOpcode::G_SHL:
6793 MainSrcIdx = (int)
I - (
int)K;
6794 CarrySrcIdx = MainSrcIdx - 1;
6796 case TargetOpcode::G_LSHR:
6797 case TargetOpcode::G_ASHR:
6798 MainSrcIdx = (int)
I + (
int)K;
6799 CarrySrcIdx = MainSrcIdx + 1;
6807 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6808 Register MainOp = SrcParts[MainSrcIdx];
6812 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6813 CarryOp = SrcParts[CarrySrcIdx];
6814 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6815 CarrySrcIdx >= (
int)NumParts)
6816 CarryOp = FillValue;
6822 ResultForK = FillValue;
6828 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6835 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6839 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6840 MI.eraseFromParent();
6847 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6850 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6865 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6870 "getNeutralElementForVecReduce called with invalid opcode!");
6871 case TargetOpcode::G_VECREDUCE_ADD:
6872 case TargetOpcode::G_VECREDUCE_OR:
6873 case TargetOpcode::G_VECREDUCE_XOR:
6874 case TargetOpcode::G_VECREDUCE_UMAX:
6876 case TargetOpcode::G_VECREDUCE_MUL:
6878 case TargetOpcode::G_VECREDUCE_AND:
6879 case TargetOpcode::G_VECREDUCE_UMIN:
6882 case TargetOpcode::G_VECREDUCE_SMAX:
6885 case TargetOpcode::G_VECREDUCE_SMIN:
6888 case TargetOpcode::G_VECREDUCE_FADD:
6890 case TargetOpcode::G_VECREDUCE_FMUL:
6892 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6893 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6894 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6895 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6903 unsigned Opc =
MI.getOpcode();
6905 case TargetOpcode::G_IMPLICIT_DEF:
6906 case TargetOpcode::G_LOAD: {
6914 case TargetOpcode::G_STORE:
6921 case TargetOpcode::G_AND:
6922 case TargetOpcode::G_OR:
6923 case TargetOpcode::G_XOR:
6924 case TargetOpcode::G_ADD:
6925 case TargetOpcode::G_SUB:
6926 case TargetOpcode::G_MUL:
6927 case TargetOpcode::G_FADD:
6928 case TargetOpcode::G_FSUB:
6929 case TargetOpcode::G_FMUL:
6930 case TargetOpcode::G_FDIV:
6931 case TargetOpcode::G_FCOPYSIGN:
6932 case TargetOpcode::G_UADDSAT:
6933 case TargetOpcode::G_USUBSAT:
6934 case TargetOpcode::G_SADDSAT:
6935 case TargetOpcode::G_SSUBSAT:
6936 case TargetOpcode::G_SMIN:
6937 case TargetOpcode::G_SMAX:
6938 case TargetOpcode::G_UMIN:
6939 case TargetOpcode::G_UMAX:
6940 case TargetOpcode::G_FMINNUM:
6941 case TargetOpcode::G_FMAXNUM:
6942 case TargetOpcode::G_FMINNUM_IEEE:
6943 case TargetOpcode::G_FMAXNUM_IEEE:
6944 case TargetOpcode::G_FMINIMUM:
6945 case TargetOpcode::G_FMAXIMUM:
6946 case TargetOpcode::G_FMINIMUMNUM:
6947 case TargetOpcode::G_FMAXIMUMNUM:
6948 case TargetOpcode::G_STRICT_FADD:
6949 case TargetOpcode::G_STRICT_FSUB:
6950 case TargetOpcode::G_STRICT_FMUL: {
6958 case TargetOpcode::G_SHL:
6959 case TargetOpcode::G_ASHR:
6960 case TargetOpcode::G_LSHR: {
6966 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6972 case TargetOpcode::G_FMA:
6973 case TargetOpcode::G_STRICT_FMA:
6974 case TargetOpcode::G_FSHR:
6975 case TargetOpcode::G_FSHL: {
6984 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6985 case TargetOpcode::G_EXTRACT:
6992 case TargetOpcode::G_INSERT:
6993 case TargetOpcode::G_INSERT_VECTOR_ELT:
6994 case TargetOpcode::G_FREEZE:
6995 case TargetOpcode::G_FNEG:
6996 case TargetOpcode::G_FABS:
6997 case TargetOpcode::G_FSQRT:
6998 case TargetOpcode::G_FCEIL:
6999 case TargetOpcode::G_FFLOOR:
7000 case TargetOpcode::G_FNEARBYINT:
7001 case TargetOpcode::G_FRINT:
7002 case TargetOpcode::G_INTRINSIC_ROUND:
7003 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7004 case TargetOpcode::G_INTRINSIC_TRUNC:
7005 case TargetOpcode::G_BITREVERSE:
7006 case TargetOpcode::G_BSWAP:
7007 case TargetOpcode::G_FCANONICALIZE:
7008 case TargetOpcode::G_SEXT_INREG:
7009 case TargetOpcode::G_ABS:
7010 case TargetOpcode::G_CTLZ:
7011 case TargetOpcode::G_CTPOP:
7019 case TargetOpcode::G_SELECT: {
7020 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7022 if (!CondTy.isScalar() ||
7028 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7030 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7035 if (CondTy.isVector())
7045 case TargetOpcode::G_UNMERGE_VALUES:
7047 case TargetOpcode::G_PHI:
7049 case TargetOpcode::G_SHUFFLE_VECTOR:
7051 case TargetOpcode::G_BUILD_VECTOR: {
7053 for (
auto Op :
MI.uses()) {
7061 MIRBuilder.buildDeleteTrailingVectorElements(
7062 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7063 MI.eraseFromParent();
7066 case TargetOpcode::G_SEXT:
7067 case TargetOpcode::G_ZEXT:
7068 case TargetOpcode::G_ANYEXT:
7069 case TargetOpcode::G_TRUNC:
7070 case TargetOpcode::G_FPTRUNC:
7071 case TargetOpcode::G_FPEXT:
7072 case TargetOpcode::G_FPTOSI:
7073 case TargetOpcode::G_FPTOUI:
7074 case TargetOpcode::G_FPTOSI_SAT:
7075 case TargetOpcode::G_FPTOUI_SAT:
7076 case TargetOpcode::G_SITOFP:
7077 case TargetOpcode::G_UITOFP:
7078 case TargetOpcode::G_TRUNC_SSAT_S:
7079 case TargetOpcode::G_TRUNC_SSAT_U:
7080 case TargetOpcode::G_TRUNC_USAT_U: {
7087 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7090 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7098 case TargetOpcode::G_ICMP:
7099 case TargetOpcode::G_FCMP: {
7107 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7112 case TargetOpcode::G_BITCAST: {
7116 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7117 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7133 case TargetOpcode::G_VECREDUCE_FADD:
7134 case TargetOpcode::G_VECREDUCE_FMUL:
7135 case TargetOpcode::G_VECREDUCE_ADD:
7136 case TargetOpcode::G_VECREDUCE_MUL:
7137 case TargetOpcode::G_VECREDUCE_AND:
7138 case TargetOpcode::G_VECREDUCE_OR:
7139 case TargetOpcode::G_VECREDUCE_XOR:
7140 case TargetOpcode::G_VECREDUCE_SMAX:
7141 case TargetOpcode::G_VECREDUCE_SMIN:
7142 case TargetOpcode::G_VECREDUCE_UMAX:
7143 case TargetOpcode::G_VECREDUCE_UMIN: {
7144 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7146 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7147 auto NeutralElement = getNeutralElementForVecReduce(
7153 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7154 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7155 NeutralElement, Idx);
7159 MO.
setReg(NewVec.getReg(0));
7171 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7173 unsigned MaskNumElts = Mask.size();
7174 unsigned SrcNumElts = SrcTy.getNumElements();
7177 if (MaskNumElts == SrcNumElts)
7180 if (MaskNumElts < SrcNumElts) {
7188 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7189 MI.getOperand(1).getReg(),
7190 MI.getOperand(2).getReg(), NewMask);
7191 MI.eraseFromParent();
7196 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7197 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7206 MOps1[0] =
MI.getOperand(1).getReg();
7207 MOps2[0] =
MI.getOperand(2).getReg();
7209 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7210 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7214 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7216 if (Idx >=
static_cast<int>(SrcNumElts))
7217 Idx += PaddedMaskNumElts - SrcNumElts;
7222 if (MaskNumElts != PaddedMaskNumElts) {
7224 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7227 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7229 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7234 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7237 MI.eraseFromParent();
7243 unsigned int TypeIdx,
LLT MoreTy) {
7244 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7246 unsigned NumElts = DstTy.getNumElements();
7249 if (DstTy.isVector() && Src1Ty.isVector() &&
7250 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7258 if (DstTy != Src1Ty || DstTy != Src2Ty)
7266 for (
unsigned I = 0;
I != NumElts; ++
I) {
7268 if (Idx <
static_cast<int>(NumElts))
7271 NewMask[
I] = Idx - NumElts + WidenNumElts;
7275 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7276 MI.getOperand(1).getReg(),
7277 MI.getOperand(2).getReg(), NewMask);
7278 MI.eraseFromParent();
7287 unsigned SrcParts = Src1Regs.
size();
7288 unsigned DstParts = DstRegs.
size();
7290 unsigned DstIdx = 0;
7292 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7293 DstRegs[DstIdx] = FactorSum;
7298 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7300 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7301 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7303 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7309 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7310 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7311 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7312 unsigned i = RevI - 1;
7314 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7324 if (DstIdx != DstParts - 1) {
7325 MachineInstrBuilder Uaddo =
7326 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7327 FactorSum = Uaddo.
getReg(0);
7328 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7329 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7330 MachineInstrBuilder Uaddo =
7331 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7332 FactorSum = Uaddo.
getReg(0);
7333 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7334 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7338 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7339 for (
unsigned i = 2; i < Factors.
size(); ++i)
7340 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7343 CarrySumPrevDstIdx = CarrySum;
7344 DstRegs[DstIdx] = FactorSum;
7356 LLT DstType = MRI.getType(DstReg);
7358 if (DstType.isVector())
7361 unsigned Opcode =
MI.getOpcode();
7362 unsigned OpO, OpE, OpF;
7364 case TargetOpcode::G_SADDO:
7365 case TargetOpcode::G_SADDE:
7366 case TargetOpcode::G_UADDO:
7367 case TargetOpcode::G_UADDE:
7368 case TargetOpcode::G_ADD:
7369 OpO = TargetOpcode::G_UADDO;
7370 OpE = TargetOpcode::G_UADDE;
7371 OpF = TargetOpcode::G_UADDE;
7372 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7373 OpF = TargetOpcode::G_SADDE;
7375 case TargetOpcode::G_SSUBO:
7376 case TargetOpcode::G_SSUBE:
7377 case TargetOpcode::G_USUBO:
7378 case TargetOpcode::G_USUBE:
7379 case TargetOpcode::G_SUB:
7380 OpO = TargetOpcode::G_USUBO;
7381 OpE = TargetOpcode::G_USUBE;
7382 OpF = TargetOpcode::G_USUBE;
7383 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7384 OpF = TargetOpcode::G_SSUBE;
7391 unsigned NumDefs =
MI.getNumExplicitDefs();
7392 Register Src1 =
MI.getOperand(NumDefs).getReg();
7393 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7396 CarryDst =
MI.getOperand(1).getReg();
7397 if (
MI.getNumOperands() == NumDefs + 3)
7398 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7400 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7401 LLT LeftoverTy, DummyTy;
7403 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7408 int NarrowParts = Src1Regs.
size();
7409 Src1Regs.
append(Src1Left);
7410 Src2Regs.
append(Src2Left);
7413 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7415 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7418 if (i == e - 1 && CarryDst)
7419 CarryOut = CarryDst;
7421 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7424 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7425 {Src1Regs[i], Src2Regs[i]});
7426 }
else if (i == e - 1) {
7427 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7428 {Src1Regs[i], Src2Regs[i], CarryIn});
7430 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7431 {Src1Regs[i], Src2Regs[i], CarryIn});
7437 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7438 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7439 ArrayRef(DstRegs).drop_front(NarrowParts));
7441 MI.eraseFromParent();
7447 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7449 LLT Ty = MRI.getType(DstReg);
7453 unsigned Size = Ty.getSizeInBits();
7455 if (
Size % NarrowSize != 0)
7458 unsigned NumParts =
Size / NarrowSize;
7459 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7460 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7466 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7470 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7471 MI.eraseFromParent();
7481 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7484 LLT SrcTy = MRI.getType(Src);
7495 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7508 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7511 if (SizeOp1 % NarrowSize != 0)
7513 int NumParts = SizeOp1 / NarrowSize;
7516 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7520 uint64_t OpStart =
MI.getOperand(2).getImm();
7521 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7522 for (
int i = 0; i < NumParts; ++i) {
7523 unsigned SrcStart = i * NarrowSize;
7525 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7528 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7536 int64_t ExtractOffset;
7538 if (OpStart < SrcStart) {
7540 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7542 ExtractOffset = OpStart - SrcStart;
7543 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7547 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7549 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7550 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7557 if (MRI.getType(DstReg).isVector())
7558 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7559 else if (DstRegs.
size() > 1)
7560 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7563 MI.eraseFromParent();
7575 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7577 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7580 SrcRegs.
append(LeftoverRegs);
7584 uint64_t OpStart =
MI.getOperand(3).getImm();
7585 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7586 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7587 unsigned DstStart =
I * NarrowSize;
7589 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7597 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7599 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7603 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7611 int64_t ExtractOffset, InsertOffset;
7613 if (OpStart < DstStart) {
7615 ExtractOffset = DstStart - OpStart;
7616 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7618 InsertOffset = OpStart - DstStart;
7621 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7625 if (ExtractOffset != 0 || SegSize != OpSize) {
7627 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7628 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7631 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7632 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7636 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7640 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7643 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7645 MI.eraseFromParent();
7653 LLT DstTy = MRI.getType(DstReg);
7655 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7661 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7662 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7666 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7667 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7670 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7671 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7672 {Src0Regs[I], Src1Regs[I]});
7676 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7679 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7680 DstLeftoverRegs.
push_back(Inst.getReg(0));
7683 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7684 LeftoverTy, DstLeftoverRegs);
7686 MI.eraseFromParent();
7696 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7698 LLT DstTy = MRI.getType(DstReg);
7703 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7704 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7705 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7707 MI.eraseFromParent();
7717 Register CondReg =
MI.getOperand(1).getReg();
7718 LLT CondTy = MRI.getType(CondReg);
7719 if (CondTy.isVector())
7723 LLT DstTy = MRI.getType(DstReg);
7729 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7730 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7734 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7735 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7738 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7740 CondReg, Src1Regs[
I], Src2Regs[
I]);
7744 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7746 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7750 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7751 LeftoverTy, DstLeftoverRegs);
7753 MI.eraseFromParent();
7763 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7766 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7767 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7770 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7772 auto C_0 =
B.buildConstant(NarrowTy, 0);
7774 UnmergeSrc.getReg(1), C_0);
7775 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7776 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7777 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7778 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7779 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7780 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7782 MI.eraseFromParent();
7795 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7798 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7799 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7802 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7804 auto C_0 =
B.buildConstant(NarrowTy, 0);
7806 UnmergeSrc.getReg(0), C_0);
7807 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7808 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7809 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7810 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7811 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7812 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7814 MI.eraseFromParent();
7827 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7830 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7835 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7839 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7840 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7848 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7849 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7852 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7853 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7855 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7857 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7859 MI.eraseFromParent();
7869 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7872 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7873 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7875 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7876 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7877 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7879 MI.eraseFromParent();
7894 LLT ExpTy = MRI.getType(ExpReg);
7899 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7900 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7901 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7902 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7904 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7906 MI.getOperand(2).setReg(Trunc.getReg(0));
7913 unsigned Opc =
MI.getOpcode();
7916 auto QAction = LI.getAction(Q).Action;
7922 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7925 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7929 case TargetOpcode::G_CTLZ: {
7930 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7931 unsigned Len = SrcTy.getScalarSizeInBits();
7933 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7935 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7936 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7939 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7940 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7941 MI.eraseFromParent();
7957 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7958 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7961 Op = MIBOp.getReg(0);
7966 MI.eraseFromParent();
7969 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7972 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7976 case TargetOpcode::G_CTTZ: {
7977 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7979 unsigned Len = SrcTy.getScalarSizeInBits();
7980 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7983 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7984 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7987 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7988 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7989 MI.eraseFromParent();
7996 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7997 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7999 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8000 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8001 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8002 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8005 MI.eraseFromParent();
8009 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8010 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8014 case TargetOpcode::G_CTPOP: {
8016 LLT Ty = MRI.getType(SrcReg);
8017 unsigned Size = Ty.getScalarSizeInBits();
8029 auto C_1 =
B.buildConstant(Ty, 1);
8030 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8032 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8033 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8034 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8038 auto C_2 =
B.buildConstant(Ty, 2);
8039 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8041 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8042 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8043 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8044 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8051 auto C_4 =
B.buildConstant(Ty, 4);
8052 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8053 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8055 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8056 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8058 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8061 if (
Size == 16 && !Ty.isVector()) {
8063 auto C_8 =
B.buildConstant(Ty, 8);
8064 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8065 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8066 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8067 MI.eraseFromParent();
8076 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8078 auto IsMulSupported = [
this](
const LLT Ty) {
8079 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8082 if (IsMulSupported(Ty)) {
8083 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8084 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8086 auto ResTmp = B8Count;
8087 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8088 auto ShiftC =
B.buildConstant(Ty, Shift);
8089 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8090 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8092 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8094 MI.eraseFromParent();
8097 case TargetOpcode::G_CTLS: {
8098 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8102 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8103 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8105 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8111 MI.eraseFromParent();
8132 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8133 LLT Ty = MRI.getType(Dst);
8134 LLT ShTy = MRI.getType(Z);
8141 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8142 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8147 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8148 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8152 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8165 MI.eraseFromParent();
8171 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8172 LLT Ty = MRI.getType(Dst);
8173 LLT ShTy = MRI.getType(Z);
8176 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8186 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8187 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8188 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8189 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8190 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8194 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8197 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8200 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8202 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8203 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8204 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8207 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8209 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8211 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8214 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8215 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8220 MI.eraseFromParent();
8231 LLT Ty = MRI.getType(Dst);
8232 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8234 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8235 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8238 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8239 return lowerFunnelShiftAsShifts(
MI);
8243 if (Result == UnableToLegalize)
8244 return lowerFunnelShiftAsShifts(
MI);
8249 auto [Dst, Src] =
MI.getFirst2Regs();
8250 LLT DstTy = MRI.getType(Dst);
8251 LLT SrcTy = MRI.getType(Src);
8255 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8263 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8267 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8271 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8276 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8277 {UnmergeSrc.getReg(0)});
8278 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8279 {UnmergeSrc.getReg(1)});
8282 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8284 MI.eraseFromParent();
8301 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8305 LLT DstTy = MRI.getType(DstReg);
8306 LLT SrcTy = MRI.getType(SrcReg);
8314 SrcTy.getElementCount().divideCoefficientBy(2));
8327 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8339 MI.eraseFromParent();
8348 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8349 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8350 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8351 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8352 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8353 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8354 MI.eraseFromParent();
8359 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8361 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8362 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8367 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8368 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8370 return lowerRotateWithReverseRotate(
MI);
8373 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8374 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8375 bool IsFShLegal =
false;
8376 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8377 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8381 MI.eraseFromParent();
8386 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8389 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8394 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8395 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8396 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8402 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8403 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8405 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8411 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8412 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8414 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8416 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8421 MI.eraseFromParent();
8429 auto [Dst, Src] =
MI.getFirst2Regs();
8434 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8462 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8475 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8479 MI.eraseFromParent();
8487 auto [Dst, Src] =
MI.getFirst2Regs();
8492 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8505 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8507 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8512 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8514 MI.eraseFromParent();
8522 auto [Dst, Src] =
MI.getFirst2Regs();
8526 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8537 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8538 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8540 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8547 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8548 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8549 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8551 MI.eraseFromParent();
8562 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8563 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8569 MI.eraseFromParent();
8574 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8577 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8578 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8579 MIRBuilder.buildSelect(Dst, Src, True, False);
8580 MI.eraseFromParent();
8584 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8604 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8611 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8612 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8613 MIRBuilder.buildSelect(Dst, Src, True, False);
8614 MI.eraseFromParent();
8618 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8624 if (DstTy.getScalarSizeInBits() == 32) {
8631 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8632 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8634 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8641 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8642 MI.eraseFromParent();
8650 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8654 if (SrcTy !=
S64 && SrcTy !=
S32)
8656 if (DstTy !=
S32 && DstTy !=
S64)
8683 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8685 MI.eraseFromParent();
8690 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8695 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8702 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8704 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8705 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8707 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8708 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8710 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8712 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8713 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8714 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8717 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8718 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8719 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8721 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8724 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8729 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8730 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8736 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8738 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8739 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8741 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8746 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8747 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8749 MI.eraseFromParent();
8755 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8757 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8758 unsigned SatWidth = DstTy.getScalarSizeInBits();
8762 APInt MinInt, MaxInt;
8785 if (AreExactFloatBounds) {
8787 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8790 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8792 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8801 MI.eraseFromParent();
8806 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8811 MI.eraseFromParent();
8818 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8826 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8836 MI.eraseFromParent();
8842 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8846 MI.eraseFromParent();
8853 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8854 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8855 "Only G_FPEXT and G_FPTRUNC are expected");
8857 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8862 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8864 StoreOpc = TargetOpcode::G_STORE;
8865 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8868 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8869 LoadOpc = TargetOpcode::G_LOAD;
8878 StackTy, StackTyAlign);
8879 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8882 StackTy, StackTyAlign);
8883 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8885 MI.eraseFromParent();
8893 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8894 assert(SrcTy.getScalarType().isBFloat16() &&
8895 "expected a bf16 source for bf16 fpext lowering");
8906 if (DstTy.getScalarType().isFloat32())
8911 MI.eraseFromParent();
8916 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8917 if (SrcTy.getScalarType().isBFloat16() &&
8918 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8930 auto [Dst, Src] =
MI.getFirst2Regs();
8934 if (MRI.getType(Src).isVector())
8938 unsigned Flags =
MI.getFlags();
8941 MI.eraseFromParent();
8945 const unsigned ExpMask = 0x7ff;
8946 const unsigned ExpBiasf64 = 1023;
8947 const unsigned ExpBiasf16 = 15;
8949 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8959 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8966 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8968 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8970 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8974 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8976 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8978 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8979 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8987 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8988 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8999 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9010 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9026 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9036 MI.eraseFromParent();
9043 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9051 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9077 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9079 MI.eraseFromParent();
9088 LLT OperandTy = MRI.getType(
Op);
9098 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9100 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9101 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9102 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9103 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9104 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9112 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9115 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9117 AbsWide, AbsNarrowAsWide);
9121 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9122 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9124 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9125 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9131 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9137 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9138 MI.eraseFromParent();
9144 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9145 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9148 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9151 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9158 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9159 LLT Ty = MRI.getType(Dst);
9161 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9162 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9163 MI.eraseFromParent();
9168 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9169 LLT Ty = MRI.getType(Src);
9170 auto Flags =
MI.getFlags();
9178 FracToUse = FracPart.getReg(0);
9180 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9184 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9186 FracToUse =
Select.getReg(0);
9189 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9192 MI.eraseFromParent();
9198 case TargetOpcode::G_SMIN:
9200 case TargetOpcode::G_SMAX:
9202 case TargetOpcode::G_UMIN:
9204 case TargetOpcode::G_UMAX:
9212 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9217 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9218 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9220 MI.eraseFromParent();
9229 LLT DstTy = MRI.getType(Dst);
9230 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9240 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9241 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9243 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9246 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9247 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9248 if (TLI.preferSelectsOverBooleanArithmetic(
9251 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9252 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9254 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9255 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9261 unsigned BoolExtOp =
9263 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9264 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9268 MI.eraseFromParent();
9274 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9275 const int Src0Size = Src0Ty.getScalarSizeInBits();
9276 const int Src1Size = Src1Ty.getScalarSizeInBits();
9286 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9287 Src0Ty.getScalarType().isInteger()))
9288 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9290 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9291 Src1Ty.getScalarType().isInteger()))
9292 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9297 auto NotSignBitMask =
MIRBuilder.buildConstant(
9301 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9303 if (Src0Ty == Src1Ty) {
9304 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9305 }
else if (Src0Size > Src1Size) {
9306 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9307 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9308 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9309 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9311 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9312 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9313 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9314 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9320 unsigned Flags =
MI.getFlags();
9325 if (DstTy == DstIntTy)
9326 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9332 MI.eraseFromParent();
9343 switch (
MI.getOpcode()) {
9344 case TargetOpcode::G_FMINNUM:
9345 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9347 case TargetOpcode::G_FMINIMUMNUM:
9348 NewOp = TargetOpcode::G_FMINNUM;
9350 case TargetOpcode::G_FMAXNUM:
9351 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9353 case TargetOpcode::G_FMAXIMUMNUM:
9354 NewOp = TargetOpcode::G_FMAXNUM;
9360 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9361 LLT Ty = MRI.getType(Dst);
9370 if (!VT->isKnownNeverSNaN(Src0))
9371 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9373 if (!VT->isKnownNeverSNaN(Src1))
9374 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9379 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9380 MI.eraseFromParent();
9386 unsigned Opc =
MI.getOpcode();
9387 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9388 LLT Ty = MRI.getType(Dst);
9391 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9393 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9394 unsigned OpcNonIeee =
9395 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9396 bool MinMaxMustRespectOrderedZero =
false;
9400 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9402 MinMaxMustRespectOrderedZero =
true;
9403 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9408 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9413 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9416 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9420 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9422 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9432 const unsigned Flags =
MI.getFlags();
9438 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9440 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9442 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9444 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9446 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9451 MI.eraseFromParent();
9458 LLT Ty = MRI.getType(DstReg);
9459 unsigned Flags =
MI.getFlags();
9464 MI.eraseFromParent();
9470 auto [DstReg,
X] =
MI.getFirst2Regs();
9471 const unsigned Flags =
MI.getFlags();
9472 const LLT Ty = MRI.getType(DstReg);
9484 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9486 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9491 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9492 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9493 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9494 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9496 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9498 MI.eraseFromParent();