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:
3020 case TargetOpcode::G_SBFX:
3021 case TargetOpcode::G_UBFX:
3035 case TargetOpcode::G_SHL:
3055 case TargetOpcode::G_ROTR:
3056 case TargetOpcode::G_ROTL:
3065 case TargetOpcode::G_SDIV:
3066 case TargetOpcode::G_SREM:
3067 case TargetOpcode::G_SMIN:
3068 case TargetOpcode::G_SMAX:
3069 case TargetOpcode::G_ABDS:
3077 case TargetOpcode::G_SDIVREM:
3087 case TargetOpcode::G_ASHR:
3088 case TargetOpcode::G_LSHR:
3092 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3093 : TargetOpcode::G_ZEXT;
3106 case TargetOpcode::G_UDIV:
3107 case TargetOpcode::G_UREM:
3108 case TargetOpcode::G_ABDU:
3115 case TargetOpcode::G_UDIVREM:
3124 case TargetOpcode::G_UMIN:
3125 case TargetOpcode::G_UMAX: {
3126 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3128 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3132 ? TargetOpcode::G_SEXT
3133 : TargetOpcode::G_ZEXT;
3143 case TargetOpcode::G_SELECT:
3153 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3160 case TargetOpcode::G_FPEXT:
3168 case TargetOpcode::G_FPTOSI:
3169 case TargetOpcode::G_FPTOUI:
3170 case TargetOpcode::G_INTRINSIC_LRINT:
3171 case TargetOpcode::G_INTRINSIC_LLRINT:
3172 case TargetOpcode::G_IS_FPCLASS:
3182 case TargetOpcode::G_SITOFP:
3192 case TargetOpcode::G_UITOFP:
3202 case TargetOpcode::G_FPTOSI_SAT:
3203 case TargetOpcode::G_FPTOUI_SAT:
3208 LLT Ty = MRI.getType(OldDst);
3209 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3211 MI.getOperand(0).setReg(ExtReg);
3212 uint64_t ShortBits = Ty.getScalarSizeInBits();
3215 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3226 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3227 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3235 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3243 case TargetOpcode::G_LOAD:
3244 case TargetOpcode::G_SEXTLOAD:
3245 case TargetOpcode::G_ZEXTLOAD:
3246 case TargetOpcode::G_FPEXTLOAD:
3252 case TargetOpcode::G_STORE: {
3256 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3257 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3258 if (!Ty.isScalar()) {
3266 MI.setMemRefs(MF, {NewMMO});
3273 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3274 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3280 case TargetOpcode::G_FPTRUNCSTORE:
3287 case TargetOpcode::G_CONSTANT: {
3290 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3291 MRI.getType(
MI.getOperand(0).getReg()));
3292 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3293 ExtOpc == TargetOpcode::G_ANYEXT) &&
3296 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3300 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3306 case TargetOpcode::G_FCONSTANT: {
3312 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3314 MI.eraseFromParent();
3317 case TargetOpcode::G_IMPLICIT_DEF: {
3323 case TargetOpcode::G_BRCOND:
3329 case TargetOpcode::G_FCMP:
3340 case TargetOpcode::G_ICMP:
3345 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3349 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3350 unsigned ExtOpcode =
3354 ? TargetOpcode::G_SEXT
3355 : TargetOpcode::G_ZEXT;
3362 case TargetOpcode::G_PTR_ADD:
3363 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3369 case TargetOpcode::G_PHI: {
3370 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3373 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3385 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3388 LLT VecTy = MRI.getType(VecReg);
3392 TargetOpcode::G_ANYEXT);
3406 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3422 LLT VecTy = MRI.getType(VecReg);
3441 case TargetOpcode::G_FADD:
3442 case TargetOpcode::G_FMUL:
3443 case TargetOpcode::G_FSUB:
3444 case TargetOpcode::G_FMA:
3445 case TargetOpcode::G_FMAD:
3446 case TargetOpcode::G_FNEG:
3447 case TargetOpcode::G_FABS:
3448 case TargetOpcode::G_FCANONICALIZE:
3449 case TargetOpcode::G_FMINNUM:
3450 case TargetOpcode::G_FMAXNUM:
3451 case TargetOpcode::G_FMINNUM_IEEE:
3452 case TargetOpcode::G_FMAXNUM_IEEE:
3453 case TargetOpcode::G_FMINIMUM:
3454 case TargetOpcode::G_FMAXIMUM:
3455 case TargetOpcode::G_FMINIMUMNUM:
3456 case TargetOpcode::G_FMAXIMUMNUM:
3457 case TargetOpcode::G_FDIV:
3458 case TargetOpcode::G_FREM:
3459 case TargetOpcode::G_FCEIL:
3460 case TargetOpcode::G_FFLOOR:
3461 case TargetOpcode::G_FCOS:
3462 case TargetOpcode::G_FSIN:
3463 case TargetOpcode::G_FTAN:
3464 case TargetOpcode::G_FACOS:
3465 case TargetOpcode::G_FASIN:
3466 case TargetOpcode::G_FATAN:
3467 case TargetOpcode::G_FATAN2:
3468 case TargetOpcode::G_FCOSH:
3469 case TargetOpcode::G_FSINH:
3470 case TargetOpcode::G_FTANH:
3471 case TargetOpcode::G_FLOG10:
3472 case TargetOpcode::G_FLOG:
3473 case TargetOpcode::G_FLOG2:
3474 case TargetOpcode::G_FRINT:
3475 case TargetOpcode::G_FNEARBYINT:
3476 case TargetOpcode::G_FSQRT:
3477 case TargetOpcode::G_FEXP:
3478 case TargetOpcode::G_FEXP2:
3479 case TargetOpcode::G_FEXP10:
3480 case TargetOpcode::G_FPOW:
3481 case TargetOpcode::G_INTRINSIC_TRUNC:
3482 case TargetOpcode::G_INTRINSIC_ROUND:
3483 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3487 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3493 case TargetOpcode::G_FMODF: {
3503 case TargetOpcode::G_FPOWI:
3504 case TargetOpcode::G_FLDEXP:
3505 case TargetOpcode::G_STRICT_FLDEXP: {
3507 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3528 case TargetOpcode::G_FFREXP: {
3541 case TargetOpcode::G_LROUND:
3542 case TargetOpcode::G_LLROUND:
3553 case TargetOpcode::G_INTTOPTR:
3561 case TargetOpcode::G_PTRTOINT:
3569 case TargetOpcode::G_BUILD_VECTOR: {
3573 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3579 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3587 case TargetOpcode::G_SEXT_INREG:
3596 case TargetOpcode::G_PTRMASK: {
3604 case TargetOpcode::G_VECREDUCE_ADD: {
3613 case TargetOpcode::G_VECREDUCE_FADD:
3614 case TargetOpcode::G_VECREDUCE_FMUL:
3615 case TargetOpcode::G_VECREDUCE_FMIN:
3616 case TargetOpcode::G_VECREDUCE_FMAX:
3617 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3618 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3623 LLT VecTy = MRI.getType(VecReg);
3630 case TargetOpcode::G_VSCALE: {
3637 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3642 case TargetOpcode::G_SPLAT_VECTOR: {
3651 case TargetOpcode::G_INSERT_SUBVECTOR: {
3659 LLT SubVecTy = MRI.getType(SubVec);
3663 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3664 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3665 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3669 auto SplatZero =
MIRBuilder.buildSplatVector(
3674 MI.eraseFromParent();
3678 case TargetOpcode::G_BITCAST:
3690 if (MRI.getType(Dst) == MRI.getType(Src)) {
3691 Observer.changingAllUsesOfReg(MRI, Dst);
3692 MRI.replaceRegWith(Dst, Src);
3693 Observer.finishedChangingAllUsesOfReg();
3694 MI.eraseFromParent();
3703 auto Unmerge =
B.buildUnmerge(Ty, Src);
3704 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3713 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3727 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3736 MI.eraseFromParent();
3747 MI.eraseFromParent();
3754 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3755 if (SrcTy.isVector()) {
3759 if (DstTy.isVector()) {
3760 int NumDstElt = DstTy.getNumElements();
3761 int NumSrcElt = SrcTy.getNumElements();
3764 LLT DstCastTy = DstEltTy;
3765 LLT SrcPartTy = SrcEltTy;
3769 if (NumSrcElt < NumDstElt) {
3780 SrcPartTy = SrcEltTy;
3781 }
else if (NumSrcElt > NumDstElt) {
3793 DstCastTy = DstEltTy;
3798 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3802 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3803 MI.eraseFromParent();
3807 if (DstTy.isVector()) {
3810 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3811 MI.eraseFromParent();
3827 unsigned NewEltSize,
3828 unsigned OldEltSize) {
3829 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3830 LLT IdxTy =
B.getMRI()->getType(Idx);
3833 auto OffsetMask =
B.buildConstant(
3835 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3836 return B.buildShl(IdxTy, OffsetIdx,
3837 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3852 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3856 unsigned OldNumElts = SrcVecTy.getNumElements();
3863 if (NewNumElts > OldNumElts) {
3874 if (NewNumElts % OldNumElts != 0)
3878 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3882 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3885 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3887 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3888 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3889 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3890 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3891 NewOps[
I] = Elt.getReg(0);
3894 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3896 MI.eraseFromParent();
3900 if (NewNumElts < OldNumElts) {
3901 if (NewEltSize % OldEltSize != 0)
3923 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3924 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3927 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3931 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3932 ScaledIdx).getReg(0);
3940 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3942 MI.eraseFromParent();
3956 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3957 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3958 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3959 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3962 auto EltMask =
B.buildConstant(
3966 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3967 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3970 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3974 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3988 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3989 MI.getFirst4RegLLTs();
4001 if (NewNumElts < OldNumElts) {
4002 if (NewEltSize % OldEltSize != 0)
4011 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4012 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4015 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4019 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4020 ScaledIdx).getReg(0);
4030 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4031 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4035 MI.eraseFromParent();
4065 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4069 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4070 return UnableToLegalize;
4075 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4077 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4086 MI.eraseFromParent();
4104 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4105 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4115 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4116 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4118 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4119 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4121 MI.eraseFromParent();
4147 uint64_t Idx = ES->getIndexImm();
4151 LLT DstTy = MRI.getType(Dst);
4152 LLT SrcTy = MRI.getType(Src);
4158 if (DstTy == CastTy)
4166 if (CastEltSize < DstEltSize)
4169 auto AdjustAmt = CastEltSize / DstEltSize;
4170 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4171 SrcTyMinElts % AdjustAmt != 0)
4176 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4177 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4180 ES->eraseFromParent();
4211 uint64_t Idx = ES->getIndexImm();
4215 LLT DstTy = MRI.getType(Dst);
4216 LLT BigVecTy = MRI.getType(BigVec);
4217 LLT SubVecTy = MRI.getType(SubVec);
4219 if (DstTy == CastTy)
4234 if (CastEltSize < DstEltSize)
4237 auto AdjustAmt = CastEltSize / DstEltSize;
4238 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4239 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4245 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4246 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4248 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4251 ES->eraseFromParent();
4259 LLT DstTy = MRI.getType(DstReg);
4269 if (MemSizeInBits != MemStoreSizeInBits) {
4286 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4290 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4291 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4293 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4296 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4298 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4301 if (DstTy != LoadTy)
4309 if (
MIRBuilder.getDataLayout().isBigEndian())
4327 uint64_t LargeSplitSize, SmallSplitSize;
4332 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4339 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4342 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4353 if (Alignment.value() * 8 > MemSizeInBits &&
4358 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4375 LLT PtrTy = MRI.getType(PtrReg);
4388 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4391 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4392 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4393 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4395 SmallPtr, *SmallMMO);
4397 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4398 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4400 if (AnyExtTy == DstTy)
4401 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4403 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4407 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4427 LLT SrcTy = MRI.getType(SrcReg);
4435 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4441 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4443 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4447 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4451 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4466 uint64_t LargeSplitSize, SmallSplitSize;
4473 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4476 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4485 if (SrcTy.isPointer()) {
4490 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4493 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4494 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4497 LLT PtrTy = MRI.getType(PtrReg);
4499 LargeSplitSize / 8);
4500 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4506 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4507 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4516 LLT SrcTy = MRI.getType(SrcReg);
4522 assert(SrcTy.isVector() &&
"Expect a vector store type");
4529 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4533 auto Elt =
MIRBuilder.buildExtractVectorElement(
4534 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4535 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4536 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4542 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4543 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4547 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4558 switch (
MI.getOpcode()) {
4559 case TargetOpcode::G_LOAD: {
4577 case TargetOpcode::G_STORE: {
4593 case TargetOpcode::G_SELECT: {
4597 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4599 dbgs() <<
"bitcast action not implemented for vector select\n");
4610 case TargetOpcode::G_AND:
4611 case TargetOpcode::G_OR:
4612 case TargetOpcode::G_XOR: {
4620 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4622 case TargetOpcode::G_INSERT_VECTOR_ELT:
4624 case TargetOpcode::G_CONCAT_VECTORS:
4626 case TargetOpcode::G_SHUFFLE_VECTOR:
4628 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4630 case TargetOpcode::G_INSERT_SUBVECTOR:
4638void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4647 switch(
MI.getOpcode()) {
4650 case TargetOpcode::G_FCONSTANT:
4652 case TargetOpcode::G_BITCAST:
4654 case TargetOpcode::G_SREM:
4655 case TargetOpcode::G_UREM: {
4656 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4658 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4659 {MI.getOperand(1), MI.getOperand(2)});
4661 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4663 MI.eraseFromParent();
4666 case TargetOpcode::G_SADDO:
4667 case TargetOpcode::G_SSUBO:
4669 case TargetOpcode::G_SADDE:
4671 case TargetOpcode::G_SSUBE:
4673 case TargetOpcode::G_UMULH:
4674 case TargetOpcode::G_SMULH:
4676 case TargetOpcode::G_SMULO:
4677 case TargetOpcode::G_UMULO: {
4680 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4681 LLT Ty = MRI.getType(Res);
4683 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4684 ? TargetOpcode::G_SMULH
4685 : TargetOpcode::G_UMULH;
4689 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4690 MI.removeOperand(1);
4693 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4701 if (Opcode == TargetOpcode::G_SMULH) {
4702 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4703 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4710 case TargetOpcode::G_FNEG: {
4711 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4714 Register CastedSubByReg = SubByReg;
4716 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4717 !SubByRegTy.getScalarType().isInteger()) {
4718 auto BitcastDst = SubByRegTy.changeElementType(
4720 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4726 if (ResTy != TyInt) {
4728 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4731 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4733 MI.eraseFromParent();
4736 case TargetOpcode::G_FSUB:
4737 case TargetOpcode::G_STRICT_FSUB: {
4738 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4739 LLT Ty = MRI.getType(Res);
4744 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4745 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4749 MI.eraseFromParent();
4752 case TargetOpcode::G_FMAD:
4754 case TargetOpcode::G_FFLOOR:
4756 case TargetOpcode::G_LROUND:
4757 case TargetOpcode::G_LLROUND: {
4760 LLT SrcTy = MRI.getType(SrcReg);
4761 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4764 MI.eraseFromParent();
4767 case TargetOpcode::G_INTRINSIC_ROUND:
4769 case TargetOpcode::G_FRINT: {
4772 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4775 case TargetOpcode::G_INTRINSIC_LRINT:
4776 case TargetOpcode::G_INTRINSIC_LLRINT: {
4779 LLT SrcTy = MRI.getType(SrcReg);
4781 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4783 MI.eraseFromParent();
4786 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4787 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4788 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4789 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4790 **
MI.memoperands_begin());
4792 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4793 MI.eraseFromParent();
4796 case TargetOpcode::G_LOAD:
4797 case TargetOpcode::G_SEXTLOAD:
4798 case TargetOpcode::G_ZEXTLOAD:
4800 case TargetOpcode::G_STORE:
4802 case TargetOpcode::G_CTLZ_ZERO_POISON:
4803 case TargetOpcode::G_CTTZ_ZERO_POISON:
4804 case TargetOpcode::G_CTLZ:
4805 case TargetOpcode::G_CTTZ:
4806 case TargetOpcode::G_CTPOP:
4807 case TargetOpcode::G_CTLS:
4810 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4812 Register NewRes = MRI.cloneVirtualRegister(Res);
4819 MI.eraseFromParent();
4823 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4824 const LLT CondTy = MRI.getType(CarryOut);
4825 const LLT Ty = MRI.getType(Res);
4827 Register NewRes = MRI.cloneVirtualRegister(Res);
4830 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4836 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4837 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4844 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4849 MI.eraseFromParent();
4853 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4858 MI.eraseFromParent();
4862 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4863 const LLT CondTy = MRI.getType(BorrowOut);
4864 const LLT Ty = MRI.getType(Res);
4867 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4873 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4874 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4881 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4882 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4884 MI.eraseFromParent();
4924 case G_MERGE_VALUES:
4926 case G_UNMERGE_VALUES:
4928 case TargetOpcode::G_SEXT_INREG: {
4929 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4930 int64_t SizeInBits =
MI.getOperand(2).getImm();
4932 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4933 LLT DstTy = MRI.getType(DstReg);
4934 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4937 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4938 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4939 MI.eraseFromParent();
4942 case G_EXTRACT_VECTOR_ELT:
4943 case G_INSERT_VECTOR_ELT:
4945 case G_SHUFFLE_VECTOR:
4947 case G_VECTOR_COMPRESS:
4949 case G_DYN_STACKALLOC:
4951 case G_INSERT_SUBVECTOR: {
4952 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4953 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4958 Register Subvector =
MI.getOperand(2).getReg();
4959 auto InsertionPointImm =
MI.getOperand(3).getImm();
4962 LLT DstTy = MRI.getType(Subvector);
4966 bool InsertInLowHalf = InsertionPointImm == 0;
4967 auto Extract =
MIRBuilder.buildExtractSubvector(
4969 (uint64_t)(InsertInLowHalf ? VectorTy.
getNumElements() / 2 : 0));
4971 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4972 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4974 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4975 {LowHalf, HighHalf});
4976 MI.eraseFromParent();
4982 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4983 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4989 if (i >= InsertionPointImm &&
4991 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4999 MI.eraseFromParent();
5003 case G_EXTRACT_SUBVECTOR: {
5006 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
5008 LLT SrcTy = MRI.getType(SrcReg);
5009 LLT DstTy = MRI.getType(DstReg);
5011 if (SrcTy.isScalable() || DstTy.
isScalable())
5022 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5023 ExtractionPointImm + i)
5027 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5028 MI.eraseFromParent();
5033 case G_STACKRESTORE:
5043 case G_READ_REGISTER:
5044 case G_WRITE_REGISTER:
5051 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5052 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5058 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5063 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5070 case G_TRUNC_SSAT_S:
5071 case G_TRUNC_USAT_U:
5072 case G_TRUNC_SSAT_U:
5078 bool IsSigned =
MI.getOpcode() == G_ABDS;
5079 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5080 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5081 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5104 case G_MEMCPY_INLINE:
5105 case G_MEMSET_INLINE:
5117 case G_ATOMICRMW_SUB: {
5118 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5119 const LLT ValTy = MRI.getType(Val);
5123 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5124 MI.eraseFromParent();
5152 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5156 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5162 Align StackTypeAlign =
5169 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5170 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5175 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5187 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy,
Imm)).getReg(0);
5190 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5201 "Converting bits to bytes lost precision");
5207 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5208 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5210 if (IdxTy != MRI.getType(Index))
5211 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5216 LLT PtrTy = MRI.getType(VecPtr);
5217 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5225 std::initializer_list<unsigned> NonVecOpIndices) {
5226 if (
MI.getNumMemOperands() != 0)
5234 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5243 if (!Ty.isVector()) {
5249 if (Ty.getNumElements() != NumElts)
5264 assert(Ty.isVector() &&
"Expected vector type");
5266 int NumParts, NumLeftover;
5267 std::tie(NumParts, NumLeftover) =
5270 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5271 for (
int i = 0; i < NumParts; ++i) {
5276 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5285 for (
unsigned i = 0; i <
N; ++i) {
5287 Ops.push_back(
Op.getReg());
5288 else if (
Op.isImm())
5289 Ops.push_back(
Op.getImm());
5290 else if (
Op.isPredicate())
5312 std::initializer_list<unsigned> NonVecOpIndices) {
5314 "Non-compatible opcode or not specified non-vector operands");
5315 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5317 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5318 unsigned NumDefs =
MI.getNumDefs();
5326 for (
unsigned i = 0; i < NumDefs; ++i) {
5327 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5335 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5336 ++UseIdx, ++UseNo) {
5339 MI.getOperand(UseIdx));
5348 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5352 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5354 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5355 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5358 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5359 Uses.push_back(InputOpsPieces[InputNo][i]);
5362 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5363 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5368 for (
unsigned i = 0; i < NumDefs; ++i)
5369 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5371 for (
unsigned i = 0; i < NumDefs; ++i)
5372 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5375 MI.eraseFromParent();
5382 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5384 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5385 unsigned NumDefs =
MI.getNumDefs();
5389 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5394 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5395 UseIdx += 2, ++UseNo) {
5403 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5405 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5406 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5408 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5411 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5412 Phi.addUse(InputOpsPieces[j][i]);
5413 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5423 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5425 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5428 MI.eraseFromParent();
5436 const int NumDst =
MI.getNumOperands() - 1;
5437 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5438 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5439 LLT SrcTy = MRI.getType(SrcReg);
5441 if (TypeIdx != 1 || NarrowTy == DstTy)
5448 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5451 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5465 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5466 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5467 const int PartsPerUnmerge = NumDst / NumUnmerge;
5469 for (
int I = 0;
I != NumUnmerge; ++
I) {
5470 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5472 for (
int J = 0; J != PartsPerUnmerge; ++J)
5473 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5474 MIB.addUse(Unmerge.getReg(
I));
5477 MI.eraseFromParent();
5484 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5488 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5490 if (NarrowTy == SrcTy)
5498 assert(SrcTy.isVector() &&
"Expected vector types");
5500 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5514 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5515 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5516 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5522 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5523 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5524 ++i,
Offset += NumNarrowTyElts) {
5527 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5530 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5531 MI.eraseFromParent();
5535 assert(TypeIdx == 0 &&
"Bad type index");
5536 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5551 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5552 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5554 for (
unsigned i = 0; i < NumParts; ++i) {
5556 for (
unsigned j = 0; j < NumElts; ++j)
5557 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5559 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5562 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5563 MI.eraseFromParent();
5571 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5573 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5575 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5577 InsertVal =
MI.getOperand(2).getReg();
5579 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5580 LLT VecTy = MRI.getType(SrcVec);
5586 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5590 MI.eraseFromParent();
5599 SplitPieces[IdxVal] = InsertVal;
5600 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5602 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5606 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5609 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5610 TargetOpcode::G_ANYEXT);
5614 LLT IdxTy = MRI.getType(Idx);
5615 int64_t PartIdx = IdxVal / NewNumElts;
5617 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5620 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5623 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5624 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5625 VecParts[PartIdx] = InsertPart.getReg(0);
5629 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5631 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5635 MI.eraseFromParent();
5655 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5667 LLT ValTy = MRI.getType(ValReg);
5676 int NumLeftover = -1;
5682 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5684 NumParts = NarrowRegs.
size();
5685 NumLeftover = NarrowLeftoverRegs.
size();
5692 LLT PtrTy = MRI.getType(AddrReg);
5702 auto MMO = LdStMI.
getMMO();
5704 unsigned NumParts,
unsigned Offset) ->
unsigned {
5707 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5709 unsigned ByteOffset =
Offset / 8;
5712 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5719 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5720 ValRegs.push_back(Dst);
5721 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5723 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5732 unsigned HandledOffset =
5733 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5737 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5740 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5741 LeftoverTy, NarrowLeftoverRegs);
5755 switch (
MI.getOpcode()) {
5756 case G_IMPLICIT_DEF:
5772 case G_FCANONICALIZE:
5789 case G_INTRINSIC_LRINT:
5790 case G_INTRINSIC_LLRINT:
5791 case G_INTRINSIC_ROUND:
5792 case G_INTRINSIC_ROUNDEVEN:
5795 case G_INTRINSIC_TRUNC:
5823 case G_FMINNUM_IEEE:
5824 case G_FMAXNUM_IEEE:
5846 case G_CTLZ_ZERO_POISON:
5848 case G_CTTZ_ZERO_POISON:
5865 case G_ADDRSPACE_CAST:
5878 case G_STRICT_FLDEXP:
5880 case G_TRUNC_SSAT_S:
5881 case G_TRUNC_SSAT_U:
5882 case G_TRUNC_USAT_U:
5890 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5895 case G_UNMERGE_VALUES:
5897 case G_BUILD_VECTOR:
5898 assert(TypeIdx == 0 &&
"not a vector type index");
5900 case G_CONCAT_VECTORS:
5904 case G_EXTRACT_SUBVECTOR: {
5906 LLT DstTy = MRI.getType(DstReg);
5908 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5918 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5919 uint64_t RequiredSubvectorIndex =
5923 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5926 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5929 MI.eraseFromParent();
5932 case G_EXTRACT_VECTOR_ELT:
5933 case G_INSERT_VECTOR_ELT:
5942 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5943 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5945 case G_SHUFFLE_VECTOR:
5951 case G_INTRINSIC_FPTRUNC_ROUND:
5961 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5962 "Not a bitcast operation");
5967 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5969 unsigned NewElemCount =
5972 if (NewElemCount == 1) {
5975 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5982 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5991 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5992 MI.eraseFromParent();
5998 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
6002 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
6003 MI.getFirst3RegLLTs();
6006 if (DstTy != Src1Ty)
6008 if (DstTy != Src2Ty)
6023 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6039 unsigned InputUsed[2] = {-1U, -1U};
6040 unsigned FirstMaskIdx =
High * NewElts;
6041 bool UseBuildVector =
false;
6042 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6044 int Idx = Mask[FirstMaskIdx + MaskOffset];
6049 if (
Input >= std::size(Inputs)) {
6056 Idx -=
Input * NewElts;
6060 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6061 if (InputUsed[OpNo] ==
Input) {
6064 }
else if (InputUsed[OpNo] == -1U) {
6066 InputUsed[OpNo] =
Input;
6071 if (OpNo >= std::size(InputUsed)) {
6074 UseBuildVector =
true;
6079 Ops.push_back(Idx + OpNo * NewElts);
6082 if (UseBuildVector) {
6087 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6089 int Idx = Mask[FirstMaskIdx + MaskOffset];
6094 if (
Input >= std::size(Inputs)) {
6101 Idx -=
Input * NewElts;
6105 .buildExtractVectorElement(
6106 EltTy, Inputs[
Input],
6112 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6113 }
else if (InputUsed[0] == -1U) {
6115 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6116 }
else if (NewElts == 1) {
6117 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6119 Register Op0 = Inputs[InputUsed[0]];
6123 : Inputs[InputUsed[1]];
6125 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6132 MI.eraseFromParent();
6145 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6151 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6154 const unsigned NumParts =
6156 : SrcTy.getNumElements();
6160 if (DstTy != NarrowTy)
6166 unsigned NumPartsLeft = NumParts;
6167 while (NumPartsLeft > 1) {
6168 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6171 .buildInstr(ScalarOpc, {NarrowTy},
6172 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6175 SplitSrcs = PartialResults;
6176 PartialResults.
clear();
6177 NumPartsLeft = SplitSrcs.
size();
6181 MI.eraseFromParent();
6186 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6187 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6190 MI.eraseFromParent();
6194 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6196 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6204 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6207 Register Acc = PartialReductions[0];
6208 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6209 if (Part == NumParts - 1) {
6211 {Acc, PartialReductions[Part]});
6214 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6218 MI.eraseFromParent();
6224 unsigned int TypeIdx,
6226 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6227 MI.getFirst3RegLLTs();
6228 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6232 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6233 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6234 "Unexpected vecreduce opcode");
6235 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6236 ? TargetOpcode::G_FADD
6237 : TargetOpcode::G_FMUL;
6240 unsigned NumParts = SrcTy.getNumElements();
6243 for (
unsigned i = 0; i < NumParts; i++)
6244 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6248 MI.eraseFromParent();
6255 unsigned ScalarOpc) {
6263 while (SplitSrcs.
size() > 1) {
6265 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6273 SplitSrcs = std::move(PartialRdxs);
6277 MI.getOperand(1).setReg(SplitSrcs[0]);
6284 const LLT HalfTy,
const LLT AmtTy) {
6286 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6287 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6291 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6292 MI.eraseFromParent();
6298 unsigned VTBits = 2 * NVTBits;
6301 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6302 if (Amt.
ugt(VTBits)) {
6304 }
else if (Amt.
ugt(NVTBits)) {
6307 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6308 }
else if (Amt == NVTBits) {
6316 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6319 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6320 if (Amt.
ugt(VTBits)) {
6322 }
else if (Amt.
ugt(NVTBits)) {
6324 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6326 }
else if (Amt == NVTBits) {
6330 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6332 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6334 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6340 if (Amt.
ugt(VTBits)) {
6342 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6343 }
else if (Amt.
ugt(NVTBits)) {
6345 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6347 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6348 }
else if (Amt == NVTBits) {
6351 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6353 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6355 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6357 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6364 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6365 MI.eraseFromParent();
6381 LLT DstTy = MRI.getType(DstReg);
6386 LLT ShiftAmtTy = MRI.getType(Amt);
6388 if (DstEltSize % 2 != 0)
6404 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6415 const unsigned NewBitSize = DstEltSize / 2;
6427 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6429 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6430 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6433 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6434 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6436 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6441 switch (
MI.getOpcode()) {
6442 case TargetOpcode::G_SHL: {
6444 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6446 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6447 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6448 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6451 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6452 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6454 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6456 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6458 ResultRegs[0] =
Lo.getReg(0);
6459 ResultRegs[1] =
Hi.getReg(0);
6462 case TargetOpcode::G_LSHR:
6463 case TargetOpcode::G_ASHR: {
6465 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6467 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6468 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6469 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6473 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6476 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6477 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6479 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6483 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6485 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6487 ResultRegs[0] =
Lo.getReg(0);
6488 ResultRegs[1] =
Hi.getReg(0);
6495 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6496 MI.eraseFromParent();
6505 LLT TargetTy,
LLT ShiftAmtTy) {
6508 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6510 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6511 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6512 const bool NeedsInterWordShift = ShiftBits != 0;
6515 case TargetOpcode::G_SHL: {
6518 if (PartIdx < ShiftWords)
6521 unsigned SrcIdx = PartIdx - ShiftWords;
6522 if (!NeedsInterWordShift)
6523 return SrcParts[SrcIdx];
6528 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6532 return Hi.getReg(0);
6535 case TargetOpcode::G_LSHR: {
6536 unsigned SrcIdx = PartIdx + ShiftWords;
6537 if (SrcIdx >= NumParts)
6539 if (!NeedsInterWordShift)
6540 return SrcParts[SrcIdx];
6544 if (SrcIdx + 1 < NumParts) {
6545 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6549 return Lo.getReg(0);
6552 case TargetOpcode::G_ASHR: {
6554 unsigned SrcIdx = PartIdx + ShiftWords;
6555 if (SrcIdx >= NumParts)
6557 if (!NeedsInterWordShift)
6558 return SrcParts[SrcIdx];
6563 (SrcIdx == NumParts - 1)
6567 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6589 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6590 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6595 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6604 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6605 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6607 auto IsZeroBitShift =
6615 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6616 : TargetOpcode::G_SHL;
6619 auto TargetBitsConst =
6621 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6626 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6631 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6633 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6637 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6650 LLT DstTy = MRI.getType(DstReg);
6654 const unsigned NumParts = DstBits / TargetBits;
6656 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6666 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6667 MI.eraseFromParent();
6672 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6673 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6679 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6683 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6686 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6687 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6691 for (
unsigned I = 0;
I < NumParts; ++
I)
6693 Params, TargetTy, ShiftAmtTy);
6695 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6696 MI.eraseFromParent();
6705 LLT DstTy = MRI.getType(DstReg);
6706 LLT ShiftAmtTy = MRI.getType(AmtReg);
6710 const unsigned NumParts = DstBits / TargetBits;
6712 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6729 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6741 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6742 auto TargetBitsLog2Const =
6743 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6744 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6747 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6749 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6757 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6758 auto TargetBitsMinusOneConst =
6759 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6761 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6762 TargetBitsMinusOneConst)
6765 FillValue = ZeroReg;
6773 for (
unsigned I = 0;
I < NumParts; ++
I) {
6775 Register InBoundsResult = FillValue;
6785 for (
unsigned K = 0; K < NumParts; ++K) {
6786 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6788 WordShift, WordShiftKConst);
6800 switch (
MI.getOpcode()) {
6801 case TargetOpcode::G_SHL:
6802 MainSrcIdx = (int)
I - (
int)K;
6803 CarrySrcIdx = MainSrcIdx - 1;
6805 case TargetOpcode::G_LSHR:
6806 case TargetOpcode::G_ASHR:
6807 MainSrcIdx = (int)
I + (
int)K;
6808 CarrySrcIdx = MainSrcIdx + 1;
6816 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6817 Register MainOp = SrcParts[MainSrcIdx];
6821 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6822 CarryOp = SrcParts[CarrySrcIdx];
6823 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6824 CarrySrcIdx >= (
int)NumParts)
6825 CarryOp = FillValue;
6831 ResultForK = FillValue;
6837 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6844 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6848 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6849 MI.eraseFromParent();
6856 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6859 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6874 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6879 "getNeutralElementForVecReduce called with invalid opcode!");
6880 case TargetOpcode::G_VECREDUCE_ADD:
6881 case TargetOpcode::G_VECREDUCE_OR:
6882 case TargetOpcode::G_VECREDUCE_XOR:
6883 case TargetOpcode::G_VECREDUCE_UMAX:
6885 case TargetOpcode::G_VECREDUCE_MUL:
6887 case TargetOpcode::G_VECREDUCE_AND:
6888 case TargetOpcode::G_VECREDUCE_UMIN:
6891 case TargetOpcode::G_VECREDUCE_SMAX:
6894 case TargetOpcode::G_VECREDUCE_SMIN:
6897 case TargetOpcode::G_VECREDUCE_FADD:
6899 case TargetOpcode::G_VECREDUCE_FMUL:
6901 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6902 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6903 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6904 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6912 unsigned Opc =
MI.getOpcode();
6914 case TargetOpcode::G_IMPLICIT_DEF:
6915 case TargetOpcode::G_LOAD: {
6923 case TargetOpcode::G_STORE:
6930 case TargetOpcode::G_AND:
6931 case TargetOpcode::G_OR:
6932 case TargetOpcode::G_XOR:
6933 case TargetOpcode::G_ADD:
6934 case TargetOpcode::G_SUB:
6935 case TargetOpcode::G_MUL:
6936 case TargetOpcode::G_FADD:
6937 case TargetOpcode::G_FSUB:
6938 case TargetOpcode::G_FMUL:
6939 case TargetOpcode::G_FDIV:
6940 case TargetOpcode::G_FCOPYSIGN:
6941 case TargetOpcode::G_UADDSAT:
6942 case TargetOpcode::G_USUBSAT:
6943 case TargetOpcode::G_SADDSAT:
6944 case TargetOpcode::G_SSUBSAT:
6945 case TargetOpcode::G_SMIN:
6946 case TargetOpcode::G_SMAX:
6947 case TargetOpcode::G_UMIN:
6948 case TargetOpcode::G_UMAX:
6949 case TargetOpcode::G_FMINNUM:
6950 case TargetOpcode::G_FMAXNUM:
6951 case TargetOpcode::G_FMINNUM_IEEE:
6952 case TargetOpcode::G_FMAXNUM_IEEE:
6953 case TargetOpcode::G_FMINIMUM:
6954 case TargetOpcode::G_FMAXIMUM:
6955 case TargetOpcode::G_FMINIMUMNUM:
6956 case TargetOpcode::G_FMAXIMUMNUM:
6957 case TargetOpcode::G_STRICT_FADD:
6958 case TargetOpcode::G_STRICT_FSUB:
6959 case TargetOpcode::G_STRICT_FMUL: {
6967 case TargetOpcode::G_SHL:
6968 case TargetOpcode::G_ASHR:
6969 case TargetOpcode::G_LSHR: {
6975 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6981 case TargetOpcode::G_FMA:
6982 case TargetOpcode::G_STRICT_FMA:
6983 case TargetOpcode::G_FSHR:
6984 case TargetOpcode::G_FSHL: {
6993 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6994 case TargetOpcode::G_EXTRACT:
7001 case TargetOpcode::G_INSERT:
7002 case TargetOpcode::G_INSERT_VECTOR_ELT:
7003 case TargetOpcode::G_FREEZE:
7004 case TargetOpcode::G_FNEG:
7005 case TargetOpcode::G_FABS:
7006 case TargetOpcode::G_FSQRT:
7007 case TargetOpcode::G_FCEIL:
7008 case TargetOpcode::G_FFLOOR:
7009 case TargetOpcode::G_FNEARBYINT:
7010 case TargetOpcode::G_FRINT:
7011 case TargetOpcode::G_INTRINSIC_ROUND:
7012 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
7013 case TargetOpcode::G_INTRINSIC_TRUNC:
7014 case TargetOpcode::G_BITREVERSE:
7015 case TargetOpcode::G_BSWAP:
7016 case TargetOpcode::G_FCANONICALIZE:
7017 case TargetOpcode::G_SEXT_INREG:
7018 case TargetOpcode::G_ABS:
7019 case TargetOpcode::G_CTLZ:
7020 case TargetOpcode::G_CTPOP:
7028 case TargetOpcode::G_SELECT: {
7029 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7031 if (!CondTy.isScalar() ||
7037 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7039 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7044 if (CondTy.isVector())
7054 case TargetOpcode::G_UNMERGE_VALUES:
7056 case TargetOpcode::G_PHI:
7058 case TargetOpcode::G_SHUFFLE_VECTOR:
7060 case TargetOpcode::G_BUILD_VECTOR: {
7062 for (
auto Op :
MI.uses()) {
7070 MIRBuilder.buildDeleteTrailingVectorElements(
7071 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7072 MI.eraseFromParent();
7075 case TargetOpcode::G_SEXT:
7076 case TargetOpcode::G_ZEXT:
7077 case TargetOpcode::G_ANYEXT:
7078 case TargetOpcode::G_TRUNC:
7079 case TargetOpcode::G_FPTRUNC:
7080 case TargetOpcode::G_FPEXT:
7081 case TargetOpcode::G_FPTOSI:
7082 case TargetOpcode::G_FPTOUI:
7083 case TargetOpcode::G_FPTOSI_SAT:
7084 case TargetOpcode::G_FPTOUI_SAT:
7085 case TargetOpcode::G_SITOFP:
7086 case TargetOpcode::G_UITOFP:
7087 case TargetOpcode::G_TRUNC_SSAT_S:
7088 case TargetOpcode::G_TRUNC_SSAT_U:
7089 case TargetOpcode::G_TRUNC_USAT_U: {
7096 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7099 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7107 case TargetOpcode::G_ICMP:
7108 case TargetOpcode::G_FCMP: {
7116 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7121 case TargetOpcode::G_BITCAST: {
7125 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7126 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7142 case TargetOpcode::G_VECREDUCE_FADD:
7143 case TargetOpcode::G_VECREDUCE_FMUL:
7144 case TargetOpcode::G_VECREDUCE_ADD:
7145 case TargetOpcode::G_VECREDUCE_MUL:
7146 case TargetOpcode::G_VECREDUCE_AND:
7147 case TargetOpcode::G_VECREDUCE_OR:
7148 case TargetOpcode::G_VECREDUCE_XOR:
7149 case TargetOpcode::G_VECREDUCE_SMAX:
7150 case TargetOpcode::G_VECREDUCE_SMIN:
7151 case TargetOpcode::G_VECREDUCE_UMAX:
7152 case TargetOpcode::G_VECREDUCE_UMIN: {
7153 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7155 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7156 auto NeutralElement = getNeutralElementForVecReduce(
7162 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7163 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7164 NeutralElement, Idx);
7168 MO.
setReg(NewVec.getReg(0));
7180 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7182 unsigned MaskNumElts = Mask.size();
7183 unsigned SrcNumElts = SrcTy.getNumElements();
7186 if (MaskNumElts == SrcNumElts)
7189 if (MaskNumElts < SrcNumElts) {
7197 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7198 MI.getOperand(1).getReg(),
7199 MI.getOperand(2).getReg(), NewMask);
7200 MI.eraseFromParent();
7205 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7206 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7215 MOps1[0] =
MI.getOperand(1).getReg();
7216 MOps2[0] =
MI.getOperand(2).getReg();
7218 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7219 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7223 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7225 if (Idx >=
static_cast<int>(SrcNumElts))
7226 Idx += PaddedMaskNumElts - SrcNumElts;
7231 if (MaskNumElts != PaddedMaskNumElts) {
7233 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7236 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7238 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7243 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7246 MI.eraseFromParent();
7252 unsigned int TypeIdx,
LLT MoreTy) {
7253 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7255 unsigned NumElts = DstTy.getNumElements();
7258 if (DstTy.isVector() && Src1Ty.isVector() &&
7259 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7267 if (DstTy != Src1Ty || DstTy != Src2Ty)
7275 for (
unsigned I = 0;
I != NumElts; ++
I) {
7277 if (Idx <
static_cast<int>(NumElts))
7280 NewMask[
I] = Idx - NumElts + WidenNumElts;
7284 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7285 MI.getOperand(1).getReg(),
7286 MI.getOperand(2).getReg(), NewMask);
7287 MI.eraseFromParent();
7296 unsigned SrcParts = Src1Regs.
size();
7297 unsigned DstParts = DstRegs.
size();
7299 unsigned DstIdx = 0;
7301 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7302 DstRegs[DstIdx] = FactorSum;
7307 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7309 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7310 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7312 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7318 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7319 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7320 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7321 unsigned i = RevI - 1;
7323 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7333 if (DstIdx != DstParts - 1) {
7334 MachineInstrBuilder Uaddo =
7335 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7336 FactorSum = Uaddo.
getReg(0);
7337 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7338 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7339 MachineInstrBuilder Uaddo =
7340 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7341 FactorSum = Uaddo.
getReg(0);
7342 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7343 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7347 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7348 for (
unsigned i = 2; i < Factors.
size(); ++i)
7349 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7352 CarrySumPrevDstIdx = CarrySum;
7353 DstRegs[DstIdx] = FactorSum;
7365 LLT DstType = MRI.getType(DstReg);
7367 if (DstType.isVector())
7370 unsigned Opcode =
MI.getOpcode();
7371 unsigned OpO, OpE, OpF;
7373 case TargetOpcode::G_SADDO:
7374 case TargetOpcode::G_SADDE:
7375 case TargetOpcode::G_UADDO:
7376 case TargetOpcode::G_UADDE:
7377 case TargetOpcode::G_ADD:
7378 OpO = TargetOpcode::G_UADDO;
7379 OpE = TargetOpcode::G_UADDE;
7380 OpF = TargetOpcode::G_UADDE;
7381 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7382 OpF = TargetOpcode::G_SADDE;
7384 case TargetOpcode::G_SSUBO:
7385 case TargetOpcode::G_SSUBE:
7386 case TargetOpcode::G_USUBO:
7387 case TargetOpcode::G_USUBE:
7388 case TargetOpcode::G_SUB:
7389 OpO = TargetOpcode::G_USUBO;
7390 OpE = TargetOpcode::G_USUBE;
7391 OpF = TargetOpcode::G_USUBE;
7392 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7393 OpF = TargetOpcode::G_SSUBE;
7400 unsigned NumDefs =
MI.getNumExplicitDefs();
7401 Register Src1 =
MI.getOperand(NumDefs).getReg();
7402 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7405 CarryDst =
MI.getOperand(1).getReg();
7406 if (
MI.getNumOperands() == NumDefs + 3)
7407 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7409 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7410 LLT LeftoverTy, DummyTy;
7412 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7417 int NarrowParts = Src1Regs.
size();
7418 Src1Regs.
append(Src1Left);
7419 Src2Regs.
append(Src2Left);
7422 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7424 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7427 if (i == e - 1 && CarryDst)
7428 CarryOut = CarryDst;
7430 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7433 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7434 {Src1Regs[i], Src2Regs[i]});
7435 }
else if (i == e - 1) {
7436 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7437 {Src1Regs[i], Src2Regs[i], CarryIn});
7439 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7440 {Src1Regs[i], Src2Regs[i], CarryIn});
7446 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7447 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7448 ArrayRef(DstRegs).drop_front(NarrowParts));
7450 MI.eraseFromParent();
7456 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7458 LLT Ty = MRI.getType(DstReg);
7462 unsigned Size = Ty.getSizeInBits();
7464 if (
Size % NarrowSize != 0)
7467 unsigned NumParts =
Size / NarrowSize;
7468 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7469 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7475 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7479 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7480 MI.eraseFromParent();
7490 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7493 LLT SrcTy = MRI.getType(Src);
7504 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7517 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7520 if (SizeOp1 % NarrowSize != 0)
7522 int NumParts = SizeOp1 / NarrowSize;
7525 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7529 uint64_t OpStart =
MI.getOperand(2).getImm();
7530 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7531 for (
int i = 0; i < NumParts; ++i) {
7532 unsigned SrcStart = i * NarrowSize;
7534 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7537 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7545 int64_t ExtractOffset;
7547 if (OpStart < SrcStart) {
7549 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7551 ExtractOffset = OpStart - SrcStart;
7552 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7556 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7558 SegReg = MRI.createGenericVirtualRegister(
LLT::integer(SegSize));
7559 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7566 if (MRI.getType(DstReg).isVector())
7567 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7568 else if (DstRegs.
size() > 1)
7569 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7572 MI.eraseFromParent();
7584 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7586 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7589 SrcRegs.
append(LeftoverRegs);
7593 uint64_t OpStart =
MI.getOperand(3).getImm();
7594 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7595 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7596 unsigned DstStart =
I * NarrowSize;
7598 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7606 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7608 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7612 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7620 int64_t ExtractOffset, InsertOffset;
7622 if (OpStart < DstStart) {
7624 ExtractOffset = DstStart - OpStart;
7625 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7627 InsertOffset = OpStart - DstStart;
7630 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7634 if (ExtractOffset != 0 || SegSize != OpSize) {
7636 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7637 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7640 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7641 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7645 uint64_t WideSize = DstRegs.
size() * NarrowSize;
7649 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7652 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7654 MI.eraseFromParent();
7662 LLT DstTy = MRI.getType(DstReg);
7664 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7670 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7671 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7675 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7676 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7679 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7680 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7681 {Src0Regs[I], Src1Regs[I]});
7685 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7688 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7689 DstLeftoverRegs.
push_back(Inst.getReg(0));
7692 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7693 LeftoverTy, DstLeftoverRegs);
7695 MI.eraseFromParent();
7705 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7707 LLT DstTy = MRI.getType(DstReg);
7712 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7713 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7714 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7716 MI.eraseFromParent();
7726 Register CondReg =
MI.getOperand(1).getReg();
7727 LLT CondTy = MRI.getType(CondReg);
7728 if (CondTy.isVector())
7732 LLT DstTy = MRI.getType(DstReg);
7738 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7739 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7743 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7744 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7747 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7749 CondReg, Src1Regs[
I], Src2Regs[
I]);
7753 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7755 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7759 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7760 LeftoverTy, DstLeftoverRegs);
7762 MI.eraseFromParent();
7772 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7775 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7776 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7779 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7781 auto C_0 =
B.buildConstant(NarrowTy, 0);
7783 UnmergeSrc.getReg(1), C_0);
7784 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7785 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7786 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7787 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7788 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7789 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7791 MI.eraseFromParent();
7804 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7807 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7808 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7811 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7813 auto C_0 =
B.buildConstant(NarrowTy, 0);
7815 UnmergeSrc.getReg(0), C_0);
7816 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7817 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7818 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7819 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7820 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7821 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7823 MI.eraseFromParent();
7836 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7839 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7844 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7848 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7849 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7857 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7858 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7861 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7862 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7864 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7866 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7868 MI.eraseFromParent();
7878 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7881 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7882 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7884 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7885 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7886 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7888 MI.eraseFromParent();
7903 LLT ExpTy = MRI.getType(ExpReg);
7908 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7909 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7910 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7911 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7913 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7915 MI.getOperand(2).setReg(Trunc.getReg(0));
7922 unsigned Opc =
MI.getOpcode();
7925 auto QAction = LI.getAction(Q).Action;
7931 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7934 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7938 case TargetOpcode::G_CTLZ: {
7939 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7940 unsigned Len = SrcTy.getScalarSizeInBits();
7942 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7944 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7945 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7948 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7949 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7950 MI.eraseFromParent();
7966 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7967 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7970 Op = MIBOp.getReg(0);
7975 MI.eraseFromParent();
7978 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7981 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7985 case TargetOpcode::G_CTTZ: {
7986 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7988 unsigned Len = SrcTy.getScalarSizeInBits();
7989 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7992 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7993 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7996 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7997 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7998 MI.eraseFromParent();
8005 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
8006 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
8008 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
8009 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
8010 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
8011 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
8014 MI.eraseFromParent();
8018 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8019 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8023 case TargetOpcode::G_CTPOP: {
8025 LLT Ty = MRI.getType(SrcReg);
8026 unsigned Size = Ty.getScalarSizeInBits();
8038 auto C_1 =
B.buildConstant(Ty, 1);
8039 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8041 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8042 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8043 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8047 auto C_2 =
B.buildConstant(Ty, 2);
8048 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8050 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8051 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8052 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8053 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8060 auto C_4 =
B.buildConstant(Ty, 4);
8061 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8062 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8064 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8065 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8067 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8070 if (
Size == 16 && !Ty.isVector()) {
8072 auto C_8 =
B.buildConstant(Ty, 8);
8073 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8074 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8075 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8076 MI.eraseFromParent();
8085 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8087 auto IsMulSupported = [
this](
const LLT Ty) {
8088 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8091 if (IsMulSupported(Ty)) {
8092 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8093 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8095 auto ResTmp = B8Count;
8096 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8097 auto ShiftC =
B.buildConstant(Ty, Shift);
8098 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8099 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8101 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8103 MI.eraseFromParent();
8106 case TargetOpcode::G_CTLS: {
8107 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8111 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8112 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8114 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8120 MI.eraseFromParent();
8141 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8142 LLT Ty = MRI.getType(Dst);
8143 LLT ShTy = MRI.getType(Z);
8150 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8151 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8156 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8157 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8161 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8174 MI.eraseFromParent();
8180 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8181 LLT Ty = MRI.getType(Dst);
8182 LLT ShTy = MRI.getType(Z);
8185 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8195 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8196 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8197 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8198 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8199 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8203 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8206 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8209 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8211 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8212 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8213 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8216 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8218 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8220 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8223 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8224 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8229 MI.eraseFromParent();
8240 LLT Ty = MRI.getType(Dst);
8241 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8243 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8244 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8247 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8248 return lowerFunnelShiftAsShifts(
MI);
8252 if (Result == UnableToLegalize)
8253 return lowerFunnelShiftAsShifts(
MI);
8258 auto [Dst, Src] =
MI.getFirst2Regs();
8259 LLT DstTy = MRI.getType(Dst);
8260 LLT SrcTy = MRI.getType(Src);
8264 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8272 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8276 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8280 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8285 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8286 {UnmergeSrc.getReg(0)});
8287 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8288 {UnmergeSrc.getReg(1)});
8291 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8293 MI.eraseFromParent();
8310 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8314 LLT DstTy = MRI.getType(DstReg);
8315 LLT SrcTy = MRI.getType(SrcReg);
8323 SrcTy.getElementCount().divideCoefficientBy(2));
8336 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8348 MI.eraseFromParent();
8357 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8358 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8359 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8360 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8361 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8362 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8363 MI.eraseFromParent();
8368 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8370 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8371 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8376 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8377 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8379 return lowerRotateWithReverseRotate(
MI);
8382 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8383 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8384 bool IsFShLegal =
false;
8385 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8386 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8390 MI.eraseFromParent();
8395 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8398 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8403 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8404 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8405 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8411 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8412 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8414 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8420 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8421 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8423 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8425 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8430 MI.eraseFromParent();
8438 auto [Dst, Src] =
MI.getFirst2Regs();
8443 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8471 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8484 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8488 MI.eraseFromParent();
8496 auto [Dst, Src] =
MI.getFirst2Regs();
8501 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8514 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8516 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8521 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8523 MI.eraseFromParent();
8531 auto [Dst, Src] =
MI.getFirst2Regs();
8535 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8546 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8547 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8549 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8556 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8557 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8558 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8560 MI.eraseFromParent();
8571 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8572 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8578 MI.eraseFromParent();
8583 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8586 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8587 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8588 MIRBuilder.buildSelect(Dst, Src, True, False);
8589 MI.eraseFromParent();
8593 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8613 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8620 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8621 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8622 MIRBuilder.buildSelect(Dst, Src, True, False);
8623 MI.eraseFromParent();
8627 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8633 if (DstTy.getScalarSizeInBits() == 32) {
8640 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8641 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8643 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8650 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8651 MI.eraseFromParent();
8659 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8663 if (SrcTy !=
S64 && SrcTy !=
S32)
8665 if (DstTy !=
S32 && DstTy !=
S64)
8692 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8694 MI.eraseFromParent();
8699 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8704 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8711 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8713 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8714 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8716 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8717 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8719 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8721 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8722 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8723 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8726 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8727 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8728 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8730 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8733 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8738 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8739 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8745 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8747 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8748 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8750 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8755 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8756 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8758 MI.eraseFromParent();
8764 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8766 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8767 unsigned SatWidth = DstTy.getScalarSizeInBits();
8771 APInt MinInt, MaxInt;
8794 if (AreExactFloatBounds) {
8796 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8799 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8801 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8810 MI.eraseFromParent();
8815 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8820 MI.eraseFromParent();
8827 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8835 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8845 MI.eraseFromParent();
8851 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8855 MI.eraseFromParent();
8862 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8863 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8864 "Only G_FPEXT and G_FPTRUNC are expected");
8866 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8871 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8873 StoreOpc = TargetOpcode::G_STORE;
8874 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8877 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8878 LoadOpc = TargetOpcode::G_LOAD;
8887 StackTy, StackTyAlign);
8888 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8891 StackTy, StackTyAlign);
8892 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8894 MI.eraseFromParent();
8902 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8903 assert(SrcTy.getScalarType().isBFloat16() &&
8904 "expected a bf16 source for bf16 fpext lowering");
8915 if (DstTy.getScalarType().isFloat32())
8920 MI.eraseFromParent();
8925 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8926 if (SrcTy.getScalarType().isBFloat16() &&
8927 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8939 auto [Dst, Src] =
MI.getFirst2Regs();
8943 if (MRI.getType(Src).isVector())
8947 unsigned Flags =
MI.getFlags();
8950 MI.eraseFromParent();
8954 const unsigned ExpMask = 0x7ff;
8955 const unsigned ExpBiasf64 = 1023;
8956 const unsigned ExpBiasf16 = 15;
8958 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8968 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8975 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8977 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8979 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8983 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8985 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8987 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8988 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8996 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8997 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
9008 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9019 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9035 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9045 MI.eraseFromParent();
9052 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9060 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9086 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9088 MI.eraseFromParent();
9097 LLT OperandTy = MRI.getType(
Op);
9107 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9109 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9110 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9111 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9112 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9113 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9121 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9124 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9126 AbsWide, AbsNarrowAsWide);
9130 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9131 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9133 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9134 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9140 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9146 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9147 MI.eraseFromParent();
9153 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9154 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9157 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9160 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9167 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9168 LLT Ty = MRI.getType(Dst);
9170 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9171 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9172 MI.eraseFromParent();
9177 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9178 LLT Ty = MRI.getType(Src);
9179 auto Flags =
MI.getFlags();
9187 FracToUse = FracPart.getReg(0);
9189 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9193 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9195 FracToUse =
Select.getReg(0);
9198 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9201 MI.eraseFromParent();
9207 case TargetOpcode::G_SMIN:
9209 case TargetOpcode::G_SMAX:
9211 case TargetOpcode::G_UMIN:
9213 case TargetOpcode::G_UMAX:
9221 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9226 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9227 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9229 MI.eraseFromParent();
9238 LLT DstTy = MRI.getType(Dst);
9239 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9249 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9250 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9252 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9255 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9256 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9257 if (TLI.preferSelectsOverBooleanArithmetic(
9260 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9261 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9263 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9264 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9270 unsigned BoolExtOp =
9272 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9273 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9277 MI.eraseFromParent();
9283 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9284 const int Src0Size = Src0Ty.getScalarSizeInBits();
9285 const int Src1Size = Src1Ty.getScalarSizeInBits();
9295 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9296 Src0Ty.getScalarType().isInteger()))
9297 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9299 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9300 Src1Ty.getScalarType().isInteger()))
9301 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9306 auto NotSignBitMask =
MIRBuilder.buildConstant(
9310 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9312 if (Src0Ty == Src1Ty) {
9313 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9314 }
else if (Src0Size > Src1Size) {
9315 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9316 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9317 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9318 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9320 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9321 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9322 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9323 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9329 unsigned Flags =
MI.getFlags();
9334 if (DstTy == DstIntTy)
9335 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9341 MI.eraseFromParent();
9352 switch (
MI.getOpcode()) {
9353 case TargetOpcode::G_FMINNUM:
9354 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9356 case TargetOpcode::G_FMINIMUMNUM:
9357 NewOp = TargetOpcode::G_FMINNUM;
9359 case TargetOpcode::G_FMAXNUM:
9360 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9362 case TargetOpcode::G_FMAXIMUMNUM:
9363 NewOp = TargetOpcode::G_FMAXNUM;
9369 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9370 LLT Ty = MRI.getType(Dst);
9379 if (!VT->isKnownNeverSNaN(Src0))
9380 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9382 if (!VT->isKnownNeverSNaN(Src1))
9383 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9388 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9389 MI.eraseFromParent();
9395 unsigned Opc =
MI.getOpcode();
9396 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9397 LLT Ty = MRI.getType(Dst);
9400 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9402 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9403 unsigned OpcNonIeee =
9404 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9405 bool MinMaxMustRespectOrderedZero =
false;
9409 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9411 MinMaxMustRespectOrderedZero =
true;
9412 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9417 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9422 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9425 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9429 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9431 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9441 const unsigned Flags =
MI.getFlags();
9447 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9449 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9451 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9453 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9455 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9460 MI.eraseFromParent();
9467 LLT Ty = MRI.getType(DstReg);
9468 unsigned Flags =
MI.getFlags();
9473 MI.eraseFromParent();
9479 auto [DstReg,
X] =
MI.getFirst2Regs();
9480 const unsigned Flags =
MI.getFlags();
9481 const LLT Ty = MRI.getType(DstReg);
9493 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9495 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9500 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9501 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);