44#define DEBUG_TYPE "legalizer"
57static std::pair<int, int>
63 unsigned NumParts =
Size / NarrowSize;
64 unsigned LeftoverSize =
Size - NumParts * NarrowSize;
67 if (LeftoverSize == 0)
72 if (LeftoverSize % EltSize != 0)
81 return std::make_pair(NumParts, NumLeftover);
89 switch (Ty.getSizeInBits()) {
130 auto Step = LI.getAction(
MI, MRI);
131 switch (Step.Action) {
146 return bitcast(
MI, Step.TypeIdx, Step.NewType);
149 return lower(
MI, Step.TypeIdx, Step.NewType);
158 return LI.legalizeCustom(*
this,
MI, LocObserver) ?
Legalized
166void LegalizerHelper::insertParts(
Register DstReg,
188 assert(LeftoverRegs.
size() == 1 &&
"Expected one leftover register");
190 AllRegs.append(LeftoverRegs.
begin(), LeftoverRegs.
end());
191 return mergeMixedSubvectors(DstReg, AllRegs);
197 extractGCDType(GCDRegs, GCDTy, PartReg);
198 LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
199 buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
204 LLT Ty = MRI.getType(
Reg);
212void LegalizerHelper::mergeMixedSubvectors(
Register DstReg,
215 for (
unsigned i = 0; i < PartRegs.
size() - 1; ++i)
216 appendVectorElts(AllElts, PartRegs[i]);
219 if (!MRI.getType(Leftover).isVector())
222 appendVectorElts(AllElts, Leftover);
224 MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
230 assert(
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);
232 const int StartIdx = Regs.
size();
233 const int NumResults =
MI.getNumOperands() - 1;
235 for (
int I = 0;
I != NumResults; ++
I)
236 Regs[StartIdx +
I] =
MI.getOperand(
I).getReg();
241 LLT SrcTy = MRI.getType(SrcReg);
242 if (SrcTy == GCDTy) {
248 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
255 LLT SrcTy = MRI.getType(SrcReg);
257 extractGCDType(Parts, GCDTy, SrcReg);
261LLT LegalizerHelper::buildLCMMergePieces(
LLT DstTy,
LLT NarrowTy,
LLT GCDTy,
263 unsigned PadStrategy) {
268 int NumOrigSrc = VRegs.
size();
274 if (NumOrigSrc < NumParts * NumSubParts) {
275 if (PadStrategy == TargetOpcode::G_ZEXT)
276 PadReg =
MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
277 else if (PadStrategy == TargetOpcode::G_ANYEXT)
278 PadReg =
MIRBuilder.buildUndef(GCDTy).getReg(0);
280 assert(PadStrategy == TargetOpcode::G_SEXT);
285 PadReg =
MIRBuilder.buildAShr(GCDTy, VRegs.
back(), ShiftAmt).getReg(0);
301 for (
int I = 0;
I != NumParts; ++
I) {
302 bool AllMergePartsArePadding =
true;
305 for (
int J = 0; J != NumSubParts; ++J) {
306 int Idx =
I * NumSubParts + J;
307 if (Idx >= NumOrigSrc) {
308 SubMerge[J] = PadReg;
312 SubMerge[J] = VRegs[Idx];
315 AllMergePartsArePadding =
false;
321 if (AllMergePartsArePadding && !AllPadReg) {
322 if (PadStrategy == TargetOpcode::G_ANYEXT)
323 AllPadReg =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
324 else if (PadStrategy == TargetOpcode::G_ZEXT)
325 AllPadReg =
MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);
334 Remerge[
I] = AllPadReg;
338 if (NumSubParts == 1)
339 Remerge[
I] = SubMerge[0];
341 Remerge[
I] =
MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);
344 if (AllMergePartsArePadding && !AllPadReg)
345 AllPadReg = Remerge[
I];
348 VRegs = std::move(Remerge);
352void LegalizerHelper::buildWidenedRemergeToDst(
Register DstReg,
LLT LCMTy,
354 LLT DstTy = MRI.getType(DstReg);
359 if (DstTy == LCMTy) {
360 MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
364 auto Remerge =
MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
373 UnmergeDefs[0] = DstReg;
374 for (
unsigned I = 1;
I != NumDefs; ++
I)
375 UnmergeDefs[
I] = MRI.createGenericVirtualRegister(DstTy);
378 MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
386#define RTLIBCASE_INT(LibcallPrefix) \
390 return RTLIB::LibcallPrefix##32; \
392 return RTLIB::LibcallPrefix##64; \
394 return RTLIB::LibcallPrefix##128; \
396 llvm_unreachable("unexpected size"); \
400#define RTLIBCASE(LibcallPrefix) \
404 return RTLIB::LibcallPrefix##32; \
406 return RTLIB::LibcallPrefix##64; \
408 return RTLIB::LibcallPrefix##80; \
410 return RTLIB::LibcallPrefix##128; \
412 llvm_unreachable("unexpected size"); \
417 case TargetOpcode::G_LROUND:
419 case TargetOpcode::G_LLROUND:
421 case TargetOpcode::G_MUL:
423 case TargetOpcode::G_SDIV:
425 case TargetOpcode::G_UDIV:
427 case TargetOpcode::G_SREM:
429 case TargetOpcode::G_UREM:
431 case TargetOpcode::G_CTLZ_ZERO_POISON:
433 case TargetOpcode::G_FADD:
435 case TargetOpcode::G_FSUB:
437 case TargetOpcode::G_FMUL:
439 case TargetOpcode::G_FDIV:
441 case TargetOpcode::G_FEXP:
443 case TargetOpcode::G_FEXP2:
445 case TargetOpcode::G_FEXP10:
447 case TargetOpcode::G_FREM:
449 case TargetOpcode::G_FPOW:
451 case TargetOpcode::G_FPOWI:
453 case TargetOpcode::G_FMA:
455 case TargetOpcode::G_FSIN:
457 case TargetOpcode::G_FCOS:
459 case TargetOpcode::G_FTAN:
461 case TargetOpcode::G_FASIN:
463 case TargetOpcode::G_FACOS:
465 case TargetOpcode::G_FATAN:
467 case TargetOpcode::G_FATAN2:
469 case TargetOpcode::G_FSINH:
471 case TargetOpcode::G_FCOSH:
473 case TargetOpcode::G_FTANH:
475 case TargetOpcode::G_FSINCOS:
477 case TargetOpcode::G_FMODF:
479 case TargetOpcode::G_FLOG10:
481 case TargetOpcode::G_FLOG:
483 case TargetOpcode::G_FLOG2:
485 case TargetOpcode::G_FLDEXP:
487 case TargetOpcode::G_FCEIL:
489 case TargetOpcode::G_FFLOOR:
491 case TargetOpcode::G_FMINNUM:
493 case TargetOpcode::G_FMAXNUM:
495 case TargetOpcode::G_FMINIMUMNUM:
497 case TargetOpcode::G_FMAXIMUMNUM:
499 case TargetOpcode::G_FSQRT:
501 case TargetOpcode::G_FRINT:
503 case TargetOpcode::G_FNEARBYINT:
505 case TargetOpcode::G_INTRINSIC_TRUNC:
507 case TargetOpcode::G_INTRINSIC_ROUND:
509 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
511 case TargetOpcode::G_INTRINSIC_LRINT:
513 case TargetOpcode::G_INTRINSIC_LLRINT:
525 Attribute::SwiftError);
540 AttributeList CallerAttrs =
F.getAttributes();
541 if (AttrBuilder(
F.getContext(), CallerAttrs.getRetAttrs())
542 .removeAttribute(Attribute::NoAlias)
543 .removeAttribute(Attribute::NonNull)
548 if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
549 CallerAttrs.hasRetAttr(Attribute::SExt))
560 if (
MI.getOpcode() == TargetOpcode::G_BZERO)
567 if (!VReg.
isVirtual() || VReg !=
Next->getOperand(1).getReg())
575 if (Ret ==
MBB.instr_end() || !Ret->isReturn())
578 if (Ret->getNumImplicitOperands() != 1)
581 if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
598 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
603 Info.OrigRet = Result;
606 (Result.Ty->isVoidTy() ||
607 Result.Ty ==
MIRBuilder.getMF().getFunction().getReturnType()) &&
618 if (
MI && Info.LoweredTailCall) {
619 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
629 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
630 "Expected instr following MI to be return or debug inst?");
633 Next->eraseFromParent();
634 }
while (
MI->getNextNode());
649 RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(
Libcall);
650 if (LibcallImpl == RTLIB::Unsupported)
654 const CallingConv::ID CC = Libcalls->getLibcallImplCallingConv(LibcallImpl);
668 Args.push_back({MO.getReg(), OpType, 0});
687 unsigned AddrSpace =
DL.getAllocaAddrSpace();
705 if (LibcallResult != LegalizeResult::Legalized)
713 MIRBuilder.
buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
714 MIRBuilder.
buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
715 MI.eraseFromParent();
730 LLT DstTy = MRI.getType(DstFrac);
735 unsigned AddrSpace =
DL.getAllocaAddrSpace();
736 MachinePointerInfo PtrInfo;
745 {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
748 if (LibcallResult != LegalizeResult::Legalized)
754 MIRBuilder.
buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
755 MI.eraseFromParent();
766 case TargetOpcode::G_FPEXT:
768 case TargetOpcode::G_FPTRUNC:
770 case TargetOpcode::G_FPTOSI:
772 case TargetOpcode::G_FPTOUI:
774 case TargetOpcode::G_SITOFP:
776 case TargetOpcode::G_UITOFP:
786 if (FromType->isIntegerTy()) {
787 if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
788 Arg.
Flags[0].setSExt();
790 Arg.
Flags[0].setZExt();
801 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
805 for (
unsigned i = 0; i <
MI.getNumOperands() - 1; ++i) {
809 LLT OpLLT = MRI.getType(Reg);
815 Args.push_back({Reg,
OpTy, 0});
818 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
819 RTLIB::Libcall RTLibcall;
820 unsigned Opc =
MI.getOpcode();
822 case TargetOpcode::G_BZERO:
823 RTLibcall = RTLIB::BZERO;
825 case TargetOpcode::G_MEMCPY:
826 RTLibcall = RTLIB::MEMCPY;
827 Args[0].Flags[0].setReturned();
829 case TargetOpcode::G_MEMMOVE:
830 RTLibcall = RTLIB::MEMMOVE;
831 Args[0].Flags[0].setReturned();
833 case TargetOpcode::G_MEMSET:
834 RTLibcall = RTLIB::MEMSET;
835 Args[0].Flags[0].setReturned();
844 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
847 if (RTLibcallImpl == RTLIB::Unsupported) {
854 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
861 MI.getOperand(
MI.getNumOperands() - 1).getImm() &&
871 if (Info.LoweredTailCall) {
872 assert(Info.IsTailCall &&
"Lowered tail call when it wasn't a tail call?");
882 (
Next->isCopy() ||
Next->isReturn() ||
Next->isDebugInstr()) &&
883 "Expected instr following MI to be return or debug inst?");
886 Next->eraseFromParent();
887 }
while (
MI.getNextNode());
897 unsigned Opc =
MI.getOpcode();
899 auto &MMO = AtomicMI.getMMO();
900 auto Ordering = MMO.getMergedOrdering();
901 LLT MemType = MMO.getMemoryType();
904 return RTLIB::UNKNOWN_LIBCALL;
906#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
908 LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
910 case TargetOpcode::G_ATOMIC_CMPXCHG:
911 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
912 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
913 return getOutlineAtomicHelper(LC, Ordering, MemSize);
915 case TargetOpcode::G_ATOMICRMW_XCHG: {
916 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
917 return getOutlineAtomicHelper(LC, Ordering, MemSize);
919 case TargetOpcode::G_ATOMICRMW_ADD:
920 case TargetOpcode::G_ATOMICRMW_SUB: {
921 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
922 return getOutlineAtomicHelper(LC, Ordering, MemSize);
924 case TargetOpcode::G_ATOMICRMW_AND: {
925 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
926 return getOutlineAtomicHelper(LC, Ordering, MemSize);
928 case TargetOpcode::G_ATOMICRMW_OR: {
929 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
930 return getOutlineAtomicHelper(LC, Ordering, MemSize);
932 case TargetOpcode::G_ATOMICRMW_XOR: {
933 const RTLIB::Libcall LC[5][4] = {
LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
934 return getOutlineAtomicHelper(LC, Ordering, MemSize);
937 return RTLIB::UNKNOWN_LIBCALL;
950 unsigned Opc =
MI.getOpcode();
952 case TargetOpcode::G_ATOMIC_CMPXCHG:
953 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
956 auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
957 MI.getFirst4RegLLTs();
960 if (
Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
961 std::tie(Ret, RetLLT,
Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
962 NewLLT) =
MI.getFirst5RegLLTs();
972 case TargetOpcode::G_ATOMICRMW_XCHG:
973 case TargetOpcode::G_ATOMICRMW_ADD:
974 case TargetOpcode::G_ATOMICRMW_SUB:
975 case TargetOpcode::G_ATOMICRMW_AND:
976 case TargetOpcode::G_ATOMICRMW_OR:
977 case TargetOpcode::G_ATOMICRMW_XOR: {
978 auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] =
MI.getFirst3RegLLTs();
981 if (
Opc == TargetOpcode::G_ATOMICRMW_AND)
985 else if (
Opc == TargetOpcode::G_ATOMICRMW_SUB)
1000 auto &CLI = *
MIRBuilder.getMF().getSubtarget().getCallLowering();
1002 RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);
1005 if (RTLibcallImpl == RTLIB::Unsupported) {
1012 Info.
CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);
1026static RTLIB::Libcall
1028 RTLIB::Libcall RTLibcall;
1029 switch (
MI.getOpcode()) {
1030 case TargetOpcode::G_GET_FPENV:
1031 RTLibcall = RTLIB::FEGETENV;
1033 case TargetOpcode::G_SET_FPENV:
1034 case TargetOpcode::G_RESET_FPENV:
1035 RTLibcall = RTLIB::FESETENV;
1037 case TargetOpcode::G_GET_FPMODE:
1038 RTLibcall = RTLIB::FEGETMODE;
1040 case TargetOpcode::G_SET_FPMODE:
1041 case TargetOpcode::G_RESET_FPMODE:
1042 RTLibcall = RTLIB::FESETMODE;
1074 LLT StateTy = MRI.getType(Dst);
1077 MachinePointerInfo TempPtrInfo;
1081 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1086 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
1094 MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);
1112 LLT StateTy = MRI.getType(Src);
1115 MachinePointerInfo TempPtrInfo;
1124 unsigned TempAddrSpace =
DL.getAllocaAddrSpace();
1129 CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
1130 LocObserver,
nullptr);
1136static std::pair<RTLIB::Libcall, CmpInst::Predicate>
1138#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred) \
1142 return {RTLIB::LibcallPrefix##32, ICmpPred}; \
1144 return {RTLIB::LibcallPrefix##64, ICmpPred}; \
1146 return {RTLIB::LibcallPrefix##128, ICmpPred}; \
1148 llvm_unreachable("unexpected size"); \
1181 LLT OpLLT = MRI.getType(
Cmp->getLHSReg());
1184 OpLLT != MRI.getType(
Cmp->getRHSReg()))
1191 LLT DstTy = MRI.getType(DstReg);
1192 const auto Cond =
Cmp->getCond();
1197 const auto BuildLibcall = [&](
const RTLIB::Libcall
Libcall,
1202 Register Temp = MRI.createGenericVirtualRegister(TempLLT);
1206 {{
Cmp->getLHSReg(), OpType, 0}, {
Cmp->getRHSReg(), OpType, 1}},
1213 .buildICmp(ICmpPred, Res, Temp,
MIRBuilder.buildConstant(TempLLT, 0))
1219 Libcall != RTLIB::UNKNOWN_LIBCALL &&
1221 if (BuildLibcall(
Libcall, ICmpPred, DstReg)) {
1234 const auto [OeqLibcall, OeqPred] =
1236 const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);
1238 const auto [UnoLibcall, UnoPred] =
1240 const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
1255 const auto [OeqLibcall, OeqPred] =
1260 const auto [UnoLibcall, UnoPred] =
1265 if (NotOeq && NotUno)
1284 const auto [InversedLibcall, InversedPred] =
1286 if (!BuildLibcall(InversedLibcall,
1311 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
1313 unsigned PtrSize =
DL.getPointerSizeInBits(AddrSpace);
1316 DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
1322 CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &
MI);
1327 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
1329 switch (
MI.getOpcode()) {
1332 case TargetOpcode::G_MUL:
1333 case TargetOpcode::G_SDIV:
1334 case TargetOpcode::G_UDIV:
1335 case TargetOpcode::G_SREM:
1336 case TargetOpcode::G_UREM:
1337 case TargetOpcode::G_CTLZ_ZERO_POISON: {
1338 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1346 case TargetOpcode::G_FADD:
1347 case TargetOpcode::G_FSUB:
1348 case TargetOpcode::G_FMUL:
1349 case TargetOpcode::G_FDIV:
1350 case TargetOpcode::G_FMA:
1351 case TargetOpcode::G_FPOW:
1352 case TargetOpcode::G_FREM:
1353 case TargetOpcode::G_FCOS:
1354 case TargetOpcode::G_FSIN:
1355 case TargetOpcode::G_FTAN:
1356 case TargetOpcode::G_FACOS:
1357 case TargetOpcode::G_FASIN:
1358 case TargetOpcode::G_FATAN:
1359 case TargetOpcode::G_FATAN2:
1360 case TargetOpcode::G_FCOSH:
1361 case TargetOpcode::G_FSINH:
1362 case TargetOpcode::G_FTANH:
1363 case TargetOpcode::G_FLOG10:
1364 case TargetOpcode::G_FLOG:
1365 case TargetOpcode::G_FLOG2:
1366 case TargetOpcode::G_FEXP:
1367 case TargetOpcode::G_FEXP2:
1368 case TargetOpcode::G_FEXP10:
1369 case TargetOpcode::G_FCEIL:
1370 case TargetOpcode::G_FFLOOR:
1371 case TargetOpcode::G_FMINNUM:
1372 case TargetOpcode::G_FMAXNUM:
1373 case TargetOpcode::G_FMINIMUMNUM:
1374 case TargetOpcode::G_FMAXIMUMNUM:
1375 case TargetOpcode::G_FSQRT:
1376 case TargetOpcode::G_FRINT:
1377 case TargetOpcode::G_FNEARBYINT:
1378 case TargetOpcode::G_INTRINSIC_TRUNC:
1379 case TargetOpcode::G_INTRINSIC_ROUND:
1380 case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
1381 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1385 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1393 case TargetOpcode::G_FSINCOS: {
1394 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1398 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1403 case TargetOpcode::G_FMODF: {
1404 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1408 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1413 case TargetOpcode::G_LROUND:
1414 case TargetOpcode::G_LLROUND:
1415 case TargetOpcode::G_INTRINSIC_LRINT:
1416 case TargetOpcode::G_INTRINSIC_LLRINT: {
1417 LLT LLTy = MRI.getType(
MI.getOperand(1).getReg());
1421 Ctx, MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits());
1423 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1429 {{
MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &
MI);
1432 MI.eraseFromParent();
1435 case TargetOpcode::G_FPOWI:
1436 case TargetOpcode::G_FLDEXP: {
1437 LLT LLTy = MRI.getType(
MI.getOperand(0).getReg());
1441 Ctx, MRI.getType(
MI.getOperand(2).getReg()).getSizeInBits());
1443 LLVM_DEBUG(
dbgs() <<
"No libcall available for type " << LLTy <<
".\n");
1448 {
MI.getOperand(1).getReg(), HLTy, 0},
1449 {
MI.getOperand(2).getReg(), ITy, 1}};
1450 Args[1].Flags[0].setSExt();
1452 Libcall, {
MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &
MI);
1457 case TargetOpcode::G_FPEXT:
1458 case TargetOpcode::G_FPTRUNC: {
1461 if (!FromTy || !ToTy)
1468 case TargetOpcode::G_FCMP: {
1472 MI.eraseFromParent();
1475 case TargetOpcode::G_FPTOSI:
1476 case TargetOpcode::G_FPTOUI: {
1480 unsigned ToSize = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1481 if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
1484 FromTy, LocObserver);
1489 case TargetOpcode::G_SITOFP:
1490 case TargetOpcode::G_UITOFP: {
1491 unsigned FromSize = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1494 if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
1496 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SITOFP;
1503 case TargetOpcode::G_ATOMICRMW_XCHG:
1504 case TargetOpcode::G_ATOMICRMW_ADD:
1505 case TargetOpcode::G_ATOMICRMW_SUB:
1506 case TargetOpcode::G_ATOMICRMW_AND:
1507 case TargetOpcode::G_ATOMICRMW_OR:
1508 case TargetOpcode::G_ATOMICRMW_XOR:
1509 case TargetOpcode::G_ATOMIC_CMPXCHG:
1510 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
1516 case TargetOpcode::G_BZERO:
1517 case TargetOpcode::G_MEMCPY:
1518 case TargetOpcode::G_MEMMOVE:
1519 case TargetOpcode::G_MEMSET: {
1524 MI.eraseFromParent();
1527 case TargetOpcode::G_GET_FPENV:
1528 case TargetOpcode::G_GET_FPMODE: {
1534 case TargetOpcode::G_SET_FPENV:
1535 case TargetOpcode::G_SET_FPMODE: {
1541 case TargetOpcode::G_RESET_FPENV:
1542 case TargetOpcode::G_RESET_FPMODE: {
1550 MI.eraseFromParent();
1557 uint64_t SizeOp0 = MRI.getType(
MI.getOperand(0).getReg()).getSizeInBits();
1560 switch (
MI.getOpcode()) {
1563 case TargetOpcode::G_IMPLICIT_DEF: {
1565 LLT DstTy = MRI.getType(DstReg);
1573 if (SizeOp0 % NarrowSize != 0) {
1578 MI.eraseFromParent();
1582 int NumParts = SizeOp0 / NarrowSize;
1585 for (
int i = 0; i < NumParts; ++i)
1589 MIRBuilder.buildBuildVector(DstReg, DstRegs);
1591 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
1592 MI.eraseFromParent();
1595 case TargetOpcode::G_CONSTANT: {
1596 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1597 const APInt &Val =
MI.getOperand(1).getCImm()->getValue();
1598 unsigned TotalSize = Ty.getSizeInBits();
1600 int NumParts = TotalSize / NarrowSize;
1603 for (
int I = 0;
I != NumParts; ++
I) {
1604 unsigned Offset =
I * NarrowSize;
1611 unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
1613 if (LeftoverBits != 0) {
1617 Val.
lshr(NumParts * NarrowSize).
trunc(LeftoverBits));
1621 insertParts(
MI.getOperand(0).getReg(),
1622 Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);
1624 MI.eraseFromParent();
1627 case TargetOpcode::G_SEXT:
1628 case TargetOpcode::G_ZEXT:
1629 case TargetOpcode::G_ANYEXT:
1631 case TargetOpcode::G_TRUNC: {
1635 uint64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
1637 LLVM_DEBUG(
dbgs() <<
"Can't narrow trunc to type " << NarrowTy <<
"\n");
1641 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
1642 MIRBuilder.buildCopy(
MI.getOperand(0), Unmerge.getReg(0));
1643 MI.eraseFromParent();
1646 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
1647 case TargetOpcode::G_FREEZE: {
1651 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1656 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1).getReg());
1658 for (
unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
1660 MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
1664 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), Parts);
1665 MI.eraseFromParent();
1668 case TargetOpcode::G_ADD:
1669 case TargetOpcode::G_SUB:
1670 case TargetOpcode::G_SADDO:
1671 case TargetOpcode::G_SSUBO:
1672 case TargetOpcode::G_SADDE:
1673 case TargetOpcode::G_SSUBE:
1674 case TargetOpcode::G_UADDO:
1675 case TargetOpcode::G_USUBO:
1676 case TargetOpcode::G_UADDE:
1677 case TargetOpcode::G_USUBE:
1679 case TargetOpcode::G_MUL:
1680 case TargetOpcode::G_UMULH:
1682 case TargetOpcode::G_EXTRACT:
1684 case TargetOpcode::G_INSERT:
1686 case TargetOpcode::G_LOAD: {
1688 Register DstReg = LoadMI.getDstReg();
1689 LLT DstTy = MRI.getType(DstReg);
1693 if (8 * LoadMI.getMemSize().getValue() != DstTy.
getSizeInBits()) {
1694 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1695 MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
1697 LoadMI.eraseFromParent();
1703 case TargetOpcode::G_ZEXTLOAD:
1704 case TargetOpcode::G_SEXTLOAD:
1705 case TargetOpcode::G_FPEXTLOAD: {
1707 Register DstReg = LoadMI.getDstReg();
1708 Register PtrReg = LoadMI.getPointerReg();
1710 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1711 auto &MMO = LoadMI.getMMO();
1714 if (MemSize == NarrowSize) {
1716 }
else if (MemSize < NarrowSize) {
1717 MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
1718 }
else if (MemSize > NarrowSize) {
1730 LoadMI.eraseFromParent();
1733 case TargetOpcode::G_STORE: {
1736 Register SrcReg = StoreMI.getValueReg();
1737 LLT SrcTy = MRI.getType(SrcReg);
1738 if (SrcTy.isVector())
1741 int NumParts = SizeOp0 / NarrowSize;
1743 unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
1744 if (SrcTy.isVector() && LeftoverBits != 0)
1747 if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
1748 Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
1750 MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
1751 StoreMI.eraseFromParent();
1757 case TargetOpcode::G_FPTRUNCSTORE: {
1759 Register SrcReg = StoreMI.getValueReg();
1760 Register PtrReg = StoreMI.getPointerReg();
1762 auto &MMO = StoreMI.getMMO();
1764 if (MemSize > NarrowSize) {
1768 auto TmpReg =
MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
1769 if (MemSize == NarrowSize) {
1771 }
else if (MemSize < NarrowSize) {
1772 MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
1776 StoreMI.eraseFromParent();
1779 case TargetOpcode::G_SELECT:
1781 case TargetOpcode::G_AND:
1782 case TargetOpcode::G_OR:
1783 case TargetOpcode::G_XOR: {
1795 case TargetOpcode::G_SHL:
1796 case TargetOpcode::G_LSHR:
1797 case TargetOpcode::G_ASHR:
1799 case TargetOpcode::G_CTLZ:
1800 case TargetOpcode::G_CTLZ_ZERO_POISON:
1801 case TargetOpcode::G_CTTZ:
1802 case TargetOpcode::G_CTTZ_ZERO_POISON:
1803 case TargetOpcode::G_CTLS:
1804 case TargetOpcode::G_CTPOP:
1806 switch (
MI.getOpcode()) {
1807 case TargetOpcode::G_CTLZ:
1808 case TargetOpcode::G_CTLZ_ZERO_POISON:
1810 case TargetOpcode::G_CTTZ:
1811 case TargetOpcode::G_CTTZ_ZERO_POISON:
1813 case TargetOpcode::G_CTPOP:
1815 case TargetOpcode::G_CTLS:
1825 case TargetOpcode::G_INTTOPTR:
1833 case TargetOpcode::G_PTRTOINT:
1841 case TargetOpcode::G_PHI: {
1844 if (SizeOp0 % NarrowSize != 0)
1847 unsigned NumParts = SizeOp0 / NarrowSize;
1851 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1859 for (
unsigned i = 0; i < NumParts; ++i) {
1860 DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
1862 MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
1863 for (
unsigned j = 1; j <
MI.getNumOperands(); j += 2)
1864 MIB.
addUse(SrcRegs[j / 2][i]).
add(
MI.getOperand(j + 1));
1867 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
1869 MI.eraseFromParent();
1872 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1873 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1877 int OpIdx =
MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
1883 case TargetOpcode::G_ICMP: {
1885 LLT SrcTy = MRI.getType(LHS);
1891 if (!
extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
1897 if (!
extractParts(
MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
1898 RHSPartRegs, RHSLeftoverRegs,
MIRBuilder, MRI))
1904 LLT ResTy = MRI.getType(Dst);
1909 auto Zero =
MIRBuilder.buildConstant(NarrowTy, 0);
1911 for (
auto LHSAndRHS :
zip(LHSPartRegs, RHSPartRegs)) {
1912 auto LHS = std::get<0>(LHSAndRHS);
1913 auto RHS = std::get<1>(LHSAndRHS);
1914 auto Xor =
MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
1921 for (
auto LHSAndRHS :
zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
1922 auto LHS = std::get<0>(LHSAndRHS);
1923 auto RHS = std::get<1>(LHSAndRHS);
1924 auto Xor =
MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
1925 LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy,
Xor);
1926 buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
1927 TargetOpcode::G_ZEXT);
1934 assert(Xors.
size() >= 2 &&
"Should have gotten at least two Xors?");
1935 auto Or =
MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
1936 for (
unsigned I = 2, E = Xors.
size();
I < E; ++
I)
1941 for (
unsigned I = 0, E = LHSPartRegs.
size();
I != E; ++
I) {
1945 if (
I == E - 1 && LHSLeftoverRegs.
empty()) {
1950 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1954 MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[
I],
1957 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[
I],
1960 LHSPartRegs[
I], RHSPartRegs[
I]);
1961 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1967 for (
unsigned I = 0, E = LHSLeftoverRegs.
size();
I != E; ++
I) {
1976 CmpOut = MRI.createGenericVirtualRegister(ResTy);
1980 MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[
I],
1981 RHSLeftoverRegs[
I]);
1983 auto Cmp =
MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[
I],
1984 RHSLeftoverRegs[
I]);
1987 LHSLeftoverRegs[
I], RHSLeftoverRegs[
I]);
1988 MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
1994 MI.eraseFromParent();
1997 case TargetOpcode::G_FCMP:
2006 case TargetOpcode::G_SEXT_INREG: {
2010 int64_t SizeInBits =
MI.getOperand(2).getImm();
2019 auto TruncMIB =
MIRBuilder.buildTrunc(NarrowTy, MO1);
2020 MO1.
setReg(TruncMIB.getReg(0));
2023 Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
2035 if (SizeOp0 % NarrowSize != 0)
2037 int NumParts = SizeOp0 / NarrowSize;
2045 for (
int i = 0; i < NumParts; ++i) {
2046 Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
2061 for (
int i = 0; i < NumParts; ++i) {
2064 PartialExtensionReg = DstRegs.
back();
2066 assert(PartialExtensionReg &&
2067 "Expected to visit partial extension before full");
2068 if (FullExtensionReg) {
2073 MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
2075 FullExtensionReg = DstRegs.
back();
2080 TargetOpcode::G_SEXT_INREG, {NarrowTy},
2083 PartialExtensionReg = DstRegs.
back();
2089 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
2090 MI.eraseFromParent();
2093 case TargetOpcode::G_BSWAP:
2094 case TargetOpcode::G_BITREVERSE: {
2095 if (SizeOp0 % NarrowSize != 0)
2100 unsigned NumParts = SizeOp0 / NarrowSize;
2101 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
2104 for (
unsigned i = 0; i < NumParts; ++i) {
2105 auto DstPart =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
2106 {SrcRegs[NumParts - 1 - i]});
2110 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), DstRegs);
2113 MI.eraseFromParent();
2116 case TargetOpcode::G_PTR_ADD:
2117 case TargetOpcode::G_PTRMASK: {
2125 case TargetOpcode::G_FPTOUI:
2126 case TargetOpcode::G_FPTOSI:
2127 case TargetOpcode::G_FPTOUI_SAT:
2128 case TargetOpcode::G_FPTOSI_SAT:
2130 case TargetOpcode::G_FPEXT:
2137 case TargetOpcode::G_FLDEXP:
2138 case TargetOpcode::G_STRICT_FLDEXP:
2140 case TargetOpcode::G_VSCALE: {
2142 LLT Ty = MRI.getType(Dst);
2146 auto VScaleBase =
MIRBuilder.buildVScale(NarrowTy, One);
2147 auto ZExt =
MIRBuilder.buildZExt(Ty, VScaleBase);
2148 auto C =
MIRBuilder.buildConstant(Ty, *
MI.getOperand(1).getCImm());
2151 MI.eraseFromParent();
2158 LLT Ty = MRI.getType(Val);
2159 if (Ty.isScalar() && !Ty.isFloat())
2166 return MIRBuilder.buildBitcast(NewTy, Val).getReg(0);
2168 if (Ty.isPointer()) {
2169 if (
DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
2171 return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
2177 if (Ty.isPointerVector())
2178 NewVal =
MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
2179 return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
2183 unsigned OpIdx,
unsigned ExtOpcode) {
2185 auto ExtB =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
2186 MO.
setReg(ExtB.getReg(0));
2192 auto ExtB =
MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
2194 MO.
setReg(ExtB.getReg(0));
2200 auto ExtB =
MIRBuilder.buildTrunc(NarrowTy, MO);
2201 MO.
setReg(ExtB.getReg(0));
2205 unsigned OpIdx,
unsigned TruncOpcode) {
2207 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2209 MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
2216 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2218 MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt},
MI.getFlags());
2223 unsigned OpIdx,
unsigned ExtOpcode) {
2225 Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
2227 MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
2236 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2238 MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
2244 MO.
setReg(
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
2254 Register CastDst = MRI.createGenericVirtualRegister(CastTy);
2261LegalizerHelper::widenScalarMergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2266 auto [DstReg, DstTy, Src1Reg, Src1Ty] =
MI.getFirst2RegLLTs();
2267 if (DstTy.isVector())
2272 const int SrcSize = SrcTy.getSizeInBits();
2274 const int NumMerge = (DstSize + WideSize - 1) / WideSize;
2276 unsigned NumOps =
MI.getNumOperands();
2277 unsigned NumSrc =
MI.getNumOperands() - 1;
2278 unsigned PartSize = DstTy.getSizeInBits() / NumSrc;
2280 if (WideSize >= DstSize) {
2284 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
2285 const unsigned Offset = (
I - 1) * PartSize;
2298 ResultReg = NextResult;
2301 if (WideSize > DstSize)
2303 else if (DstTy.isPointer())
2305 else if (DstTy != WideTy)
2308 MI.eraseFromParent();
2333 const int GCD = std::gcd(SrcSize, WideSize);
2343 if (GCD == SrcSize) {
2346 auto Unmerge =
MIRBuilder.buildUnmerge(GCDTy, SrcReg);
2347 for (
int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
2353 if (
static_cast<int>(Unmerges.
size()) != NumMerge * WideSize) {
2355 for (
int I = Unmerges.
size();
I != NumMerge * WideSize; ++
I)
2359 const int PartsPerGCD = WideSize / GCD;
2363 for (
int I = 0;
I != NumMerge; ++
I, Slicer = Slicer.drop_front(PartsPerGCD)) {
2365 MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
2372 MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
2374 auto FinalMerge =
MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
2375 MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
2378 MI.eraseFromParent();
2383LegalizerHelper::widenScalarUnmergeValues(
MachineInstr &
MI,
unsigned TypeIdx,
2388 int NumDst =
MI.getNumOperands() - 1;
2389 Register SrcReg =
MI.getOperand(NumDst).getReg();
2390 LLT SrcTy = MRI.getType(SrcReg);
2394 Register Dst0Reg =
MI.getOperand(0).getReg();
2395 LLT DstTy = MRI.getType(Dst0Reg);
2404 dbgs() <<
"Not casting non-integral address space integer\n");
2409 SrcReg =
MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
2417 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
2426 SrcTy = MRI.getType(SrcReg);
2430 for (
int I = 1;
I != NumDst; ++
I) {
2431 auto ShiftAmt =
MIRBuilder.buildConstant(SrcTy, DstSize *
I);
2432 auto Shr =
MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
2436 MI.eraseFromParent();
2447 LLVM_DEBUG(
dbgs() <<
"Widening pointer source types not implemented\n");
2451 WideSrc =
MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
2454 auto Unmerge =
MIRBuilder.buildUnmerge(WideTy, WideSrc);
2472 const int NumUnmerge = Unmerge->getNumOperands() - 1;
2477 if (PartsPerRemerge == 1) {
2480 for (
int I = 0;
I != NumUnmerge; ++
I) {
2481 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
2483 for (
int J = 0; J != PartsPerUnmerge; ++J) {
2484 int Idx =
I * PartsPerUnmerge + J;
2486 MIB.addDef(
MI.getOperand(Idx).getReg());
2489 MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
2493 MIB.addUse(Unmerge.getReg(
I));
2496 SmallVector<Register, 16> Parts;
2497 for (
int J = 0; J != NumUnmerge; ++J)
2498 extractGCDType(Parts, GCDTy, Unmerge.getReg(J));
2501 for (
int I = 0;
I != NumDst; ++
I) {
2502 for (
int J = 0; J < PartsPerRemerge; ++J) {
2503 const int Idx =
I * PartsPerRemerge + J;
2507 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(
I).getReg(), RemergeParts);
2508 RemergeParts.
clear();
2512 MI.eraseFromParent();
2517LegalizerHelper::widenScalarExtract(
MachineInstr &
MI,
unsigned TypeIdx,
2519 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
2520 unsigned Offset =
MI.getOperand(2).getImm();
2523 if (SrcTy.
isVector() || DstTy.isVector())
2535 Src =
MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
2539 if (DstTy.isPointer())
2546 MI.eraseFromParent();
2551 LLT ShiftTy = SrcTy;
2560 MI.eraseFromParent();
2591LegalizerHelper::widenScalarInsert(
MachineInstr &
MI,
unsigned TypeIdx,
2593 if (TypeIdx != 0 || WideTy.
isVector())
2603LegalizerHelper::widenScalarAddSubOverflow(
MachineInstr &
MI,
unsigned TypeIdx,
2607 std::optional<Register> CarryIn;
2608 switch (
MI.getOpcode()) {
2611 case TargetOpcode::G_SADDO:
2612 Opcode = TargetOpcode::G_ADD;
2613 ExtOpcode = TargetOpcode::G_SEXT;
2615 case TargetOpcode::G_SSUBO:
2616 Opcode = TargetOpcode::G_SUB;
2617 ExtOpcode = TargetOpcode::G_SEXT;
2619 case TargetOpcode::G_UADDO:
2620 Opcode = TargetOpcode::G_ADD;
2621 ExtOpcode = TargetOpcode::G_ZEXT;
2623 case TargetOpcode::G_USUBO:
2624 Opcode = TargetOpcode::G_SUB;
2625 ExtOpcode = TargetOpcode::G_ZEXT;
2627 case TargetOpcode::G_SADDE:
2628 Opcode = TargetOpcode::G_UADDE;
2629 ExtOpcode = TargetOpcode::G_SEXT;
2630 CarryIn =
MI.getOperand(4).getReg();
2632 case TargetOpcode::G_SSUBE:
2633 Opcode = TargetOpcode::G_USUBE;
2634 ExtOpcode = TargetOpcode::G_SEXT;
2635 CarryIn =
MI.getOperand(4).getReg();
2637 case TargetOpcode::G_UADDE:
2638 Opcode = TargetOpcode::G_UADDE;
2639 ExtOpcode = TargetOpcode::G_ZEXT;
2640 CarryIn =
MI.getOperand(4).getReg();
2642 case TargetOpcode::G_USUBE:
2643 Opcode = TargetOpcode::G_USUBE;
2644 ExtOpcode = TargetOpcode::G_ZEXT;
2645 CarryIn =
MI.getOperand(4).getReg();
2661 auto LHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(2)});
2662 auto RHSExt =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {
MI.getOperand(3)});
2666 LLT CarryOutTy = MRI.getType(
MI.getOperand(1).getReg());
2668 .buildInstr(Opcode, {WideTy, CarryOutTy},
2669 {LHSExt, RHSExt, *CarryIn})
2672 NewOp =
MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).
getReg(0);
2674 LLT OrigTy = MRI.getType(
MI.getOperand(0).getReg());
2675 auto TruncOp =
MIRBuilder.buildTrunc(OrigTy, NewOp);
2676 auto ExtOp =
MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
2681 MI.eraseFromParent();
2686LegalizerHelper::widenScalarAddSubShlSat(
MachineInstr &
MI,
unsigned TypeIdx,
2688 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SADDSAT ||
2689 MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
2690 MI.getOpcode() == TargetOpcode::G_SSHLSAT;
2691 bool IsShift =
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
2692 MI.getOpcode() == TargetOpcode::G_USHLSAT;
2705 unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();
2712 auto ShiftK =
MIRBuilder.buildConstant(WideTy, SHLAmount);
2716 auto WideInst =
MIRBuilder.buildInstr(
MI.getOpcode(), {WideTy},
2717 {ShiftL, ShiftR},
MI.getFlags());
2722 :
MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);
2725 MI.eraseFromParent();
2730LegalizerHelper::widenScalarMulo(
MachineInstr &
MI,
unsigned TypeIdx,
2739 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULO;
2741 LLT SrcTy = MRI.getType(
LHS);
2742 LLT OverflowTy = MRI.getType(OriginalOverflow);
2749 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
2750 auto LeftOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
LHS});
2751 auto RightOperand =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
RHS});
2758 WideMulCanOverflow ?
MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;
2760 MachineInstrBuilder Mulo;
2761 if (WideMulCanOverflow)
2762 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
2763 {LeftOperand, RightOperand});
2765 Mulo =
MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});
2770 MachineInstrBuilder ExtResult;
2777 ExtResult =
MIRBuilder.buildSExtInReg(WideTy,
Mul, SrcBitWidth);
2781 ExtResult =
MIRBuilder.buildZExtInReg(WideTy,
Mul, SrcBitWidth);
2784 if (WideMulCanOverflow) {
2792 MI.eraseFromParent();
2798 unsigned Opcode =
MI.getOpcode();
2802 case TargetOpcode::G_ATOMICRMW_XCHG:
2803 case TargetOpcode::G_ATOMICRMW_ADD:
2804 case TargetOpcode::G_ATOMICRMW_SUB:
2805 case TargetOpcode::G_ATOMICRMW_AND:
2806 case TargetOpcode::G_ATOMICRMW_OR:
2807 case TargetOpcode::G_ATOMICRMW_XOR:
2808 case TargetOpcode::G_ATOMICRMW_MIN:
2809 case TargetOpcode::G_ATOMICRMW_MAX:
2810 case TargetOpcode::G_ATOMICRMW_UMIN:
2811 case TargetOpcode::G_ATOMICRMW_UMAX:
2812 assert(TypeIdx == 0 &&
"atomicrmw with second scalar type");
2818 case TargetOpcode::G_ATOMIC_CMPXCHG:
2819 assert(TypeIdx == 0 &&
"G_ATOMIC_CMPXCHG with second scalar type");
2826 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
2836 "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
2841 case TargetOpcode::G_EXTRACT:
2842 return widenScalarExtract(
MI, TypeIdx, WideTy);
2843 case TargetOpcode::G_INSERT:
2844 return widenScalarInsert(
MI, TypeIdx, WideTy);
2845 case TargetOpcode::G_MERGE_VALUES:
2846 return widenScalarMergeValues(
MI, TypeIdx, WideTy);
2847 case TargetOpcode::G_UNMERGE_VALUES:
2848 return widenScalarUnmergeValues(
MI, TypeIdx, WideTy);
2849 case TargetOpcode::G_SADDO:
2850 case TargetOpcode::G_SSUBO:
2851 case TargetOpcode::G_UADDO:
2852 case TargetOpcode::G_USUBO:
2853 case TargetOpcode::G_SADDE:
2854 case TargetOpcode::G_SSUBE:
2855 case TargetOpcode::G_UADDE:
2856 case TargetOpcode::G_USUBE:
2857 return widenScalarAddSubOverflow(
MI, TypeIdx, WideTy);
2858 case TargetOpcode::G_UMULO:
2859 case TargetOpcode::G_SMULO:
2860 return widenScalarMulo(
MI, TypeIdx, WideTy);
2861 case TargetOpcode::G_SADDSAT:
2862 case TargetOpcode::G_SSUBSAT:
2863 case TargetOpcode::G_SSHLSAT:
2864 case TargetOpcode::G_UADDSAT:
2865 case TargetOpcode::G_USUBSAT:
2866 case TargetOpcode::G_USHLSAT:
2867 return widenScalarAddSubShlSat(
MI, TypeIdx, WideTy);
2868 case TargetOpcode::G_CTTZ:
2869 case TargetOpcode::G_CTTZ_ZERO_POISON:
2870 case TargetOpcode::G_CTLZ:
2871 case TargetOpcode::G_CTLZ_ZERO_POISON:
2872 case TargetOpcode::G_CTLS:
2873 case TargetOpcode::G_CTPOP: {
2886 case TargetOpcode::G_CTTZ:
2887 case TargetOpcode::G_CTTZ_ZERO_POISON:
2888 case TargetOpcode::G_CTLZ_ZERO_POISON:
2889 ExtOpc = TargetOpcode::G_ANYEXT;
2891 case TargetOpcode::G_CTLS:
2892 ExtOpc = TargetOpcode::G_SEXT;
2895 ExtOpc = TargetOpcode::G_ZEXT;
2898 auto MIBSrc =
MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
2899 LLT CurTy = MRI.getType(SrcReg);
2900 unsigned NewOpc = Opcode;
2901 if (NewOpc == TargetOpcode::G_CTTZ) {
2908 WideTy, MIBSrc,
MIRBuilder.buildConstant(WideTy, TopBit));
2910 NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
2916 if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
2926 auto MIBNewOp =
MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
2928 if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
2933 WideTy, MIBNewOp,
MIRBuilder.buildConstant(WideTy, SizeDiff),
2934 Opcode == TargetOpcode::G_CTLZ
2939 MIRBuilder.buildZExtOrTrunc(
MI.getOperand(0), MIBNewOp);
2940 MI.eraseFromParent();
2943 case TargetOpcode::G_BSWAP: {
2947 Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
2948 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2949 Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
2952 MI.getOperand(0).setReg(DstExt);
2956 LLT Ty = MRI.getType(DstReg);
2958 MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
2959 MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);
2965 case TargetOpcode::G_BITREVERSE: {
2969 LLT Ty = MRI.getType(DstReg);
2972 Register DstExt = MRI.createGenericVirtualRegister(WideTy);
2974 MI.getOperand(0).setReg(DstExt);
2977 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, DiffBits);
2978 auto Shift =
MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
2983 case TargetOpcode::G_FREEZE:
2984 case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
2991 case TargetOpcode::G_ABS:
2998 case TargetOpcode::G_ADD:
2999 case TargetOpcode::G_AND:
3000 case TargetOpcode::G_MUL:
3001 case TargetOpcode::G_OR:
3002 case TargetOpcode::G_XOR:
3003 case TargetOpcode::G_SUB:
3004 case TargetOpcode::G_SHUFFLE_VECTOR:
3015 case TargetOpcode::G_SBFX:
3016 case TargetOpcode::G_UBFX:
3030 case TargetOpcode::G_SHL:
3046 case TargetOpcode::G_ROTR:
3047 case TargetOpcode::G_ROTL:
3056 case TargetOpcode::G_SDIV:
3057 case TargetOpcode::G_SREM:
3058 case TargetOpcode::G_SMIN:
3059 case TargetOpcode::G_SMAX:
3060 case TargetOpcode::G_ABDS:
3068 case TargetOpcode::G_SDIVREM:
3078 case TargetOpcode::G_ASHR:
3079 case TargetOpcode::G_LSHR:
3083 unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
3084 : TargetOpcode::G_ZEXT;
3097 case TargetOpcode::G_UDIV:
3098 case TargetOpcode::G_UREM:
3099 case TargetOpcode::G_ABDU:
3106 case TargetOpcode::G_UDIVREM:
3115 case TargetOpcode::G_UMIN:
3116 case TargetOpcode::G_UMAX: {
3117 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3119 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3123 ? TargetOpcode::G_SEXT
3124 : TargetOpcode::G_ZEXT;
3134 case TargetOpcode::G_SELECT:
3144 bool IsVec = MRI.getType(
MI.getOperand(1).getReg()).isVector();
3151 case TargetOpcode::G_FPEXT:
3159 case TargetOpcode::G_FPTOSI:
3160 case TargetOpcode::G_FPTOUI:
3161 case TargetOpcode::G_INTRINSIC_LRINT:
3162 case TargetOpcode::G_INTRINSIC_LLRINT:
3163 case TargetOpcode::G_IS_FPCLASS:
3173 case TargetOpcode::G_SITOFP:
3183 case TargetOpcode::G_UITOFP:
3193 case TargetOpcode::G_FPTOSI_SAT:
3194 case TargetOpcode::G_FPTOUI_SAT:
3199 LLT Ty = MRI.getType(OldDst);
3200 Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
3202 MI.getOperand(0).setReg(ExtReg);
3203 uint64_t ShortBits = Ty.getScalarSizeInBits();
3206 if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
3217 MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
3218 NewDst =
MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
3226 NewDst =
MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
3234 case TargetOpcode::G_LOAD:
3235 case TargetOpcode::G_SEXTLOAD:
3236 case TargetOpcode::G_ZEXTLOAD:
3237 case TargetOpcode::G_FPEXTLOAD:
3243 case TargetOpcode::G_STORE: {
3247 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
3248 assert(!Ty.isPointerOrPointerVector() &&
"Can't widen type");
3249 if (!Ty.isScalar()) {
3257 MI.setMemRefs(MF, {NewMMO});
3264 unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
3265 TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
3271 case TargetOpcode::G_FPTRUNCSTORE:
3278 case TargetOpcode::G_CONSTANT: {
3281 unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
3282 MRI.getType(
MI.getOperand(0).getReg()));
3283 assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
3284 ExtOpc == TargetOpcode::G_ANYEXT) &&
3287 const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
3291 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3297 case TargetOpcode::G_FCONSTANT: {
3303 auto IntCst =
MIRBuilder.buildConstant(
MI.getOperand(0).getReg(), Val);
3305 MI.eraseFromParent();
3308 case TargetOpcode::G_IMPLICIT_DEF: {
3314 case TargetOpcode::G_BRCOND:
3320 case TargetOpcode::G_FCMP:
3331 case TargetOpcode::G_ICMP:
3336 LLT SrcTy = MRI.getType(
MI.getOperand(2).getReg());
3340 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
3341 unsigned ExtOpcode =
3345 ? TargetOpcode::G_SEXT
3346 : TargetOpcode::G_ZEXT;
3353 case TargetOpcode::G_PTR_ADD:
3354 assert(TypeIdx == 1 &&
"unable to legalize pointer of G_PTR_ADD");
3360 case TargetOpcode::G_PHI: {
3361 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
3364 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2) {
3376 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
3379 LLT VecTy = MRI.getType(VecReg);
3383 TargetOpcode::G_ANYEXT);
3397 case TargetOpcode::G_INSERT_VECTOR_ELT: {
3413 LLT VecTy = MRI.getType(VecReg);
3432 case TargetOpcode::G_FADD:
3433 case TargetOpcode::G_FMUL:
3434 case TargetOpcode::G_FSUB:
3435 case TargetOpcode::G_FMA:
3436 case TargetOpcode::G_FMAD:
3437 case TargetOpcode::G_FNEG:
3438 case TargetOpcode::G_FABS:
3439 case TargetOpcode::G_FCANONICALIZE:
3440 case TargetOpcode::G_FMINNUM:
3441 case TargetOpcode::G_FMAXNUM:
3442 case TargetOpcode::G_FMINNUM_IEEE:
3443 case TargetOpcode::G_FMAXNUM_IEEE:
3444 case TargetOpcode::G_FMINIMUM:
3445 case TargetOpcode::G_FMAXIMUM:
3446 case TargetOpcode::G_FMINIMUMNUM:
3447 case TargetOpcode::G_FMAXIMUMNUM:
3448 case TargetOpcode::G_FDIV:
3449 case TargetOpcode::G_FREM:
3450 case TargetOpcode::G_FCEIL:
3451 case TargetOpcode::G_FFLOOR:
3452 case TargetOpcode::G_FCOS:
3453 case TargetOpcode::G_FSIN:
3454 case TargetOpcode::G_FTAN:
3455 case TargetOpcode::G_FACOS:
3456 case TargetOpcode::G_FASIN:
3457 case TargetOpcode::G_FATAN:
3458 case TargetOpcode::G_FATAN2:
3459 case TargetOpcode::G_FCOSH:
3460 case TargetOpcode::G_FSINH:
3461 case TargetOpcode::G_FTANH:
3462 case TargetOpcode::G_FLOG10:
3463 case TargetOpcode::G_FLOG:
3464 case TargetOpcode::G_FLOG2:
3465 case TargetOpcode::G_FRINT:
3466 case TargetOpcode::G_FNEARBYINT:
3467 case TargetOpcode::G_FSQRT:
3468 case TargetOpcode::G_FEXP:
3469 case TargetOpcode::G_FEXP2:
3470 case TargetOpcode::G_FEXP10:
3471 case TargetOpcode::G_FPOW:
3472 case TargetOpcode::G_INTRINSIC_TRUNC:
3473 case TargetOpcode::G_INTRINSIC_ROUND:
3474 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
3478 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3484 case TargetOpcode::G_FMODF: {
3494 case TargetOpcode::G_FPOWI:
3495 case TargetOpcode::G_FLDEXP:
3496 case TargetOpcode::G_STRICT_FLDEXP: {
3498 if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
3519 case TargetOpcode::G_FFREXP: {
3532 case TargetOpcode::G_LROUND:
3533 case TargetOpcode::G_LLROUND:
3544 case TargetOpcode::G_INTTOPTR:
3552 case TargetOpcode::G_PTRTOINT:
3560 case TargetOpcode::G_BUILD_VECTOR: {
3564 for (
int I = 1, E =
MI.getNumOperands();
I != E; ++
I)
3570 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
3578 case TargetOpcode::G_SEXT_INREG:
3587 case TargetOpcode::G_PTRMASK: {
3595 case TargetOpcode::G_VECREDUCE_ADD: {
3604 case TargetOpcode::G_VECREDUCE_FADD:
3605 case TargetOpcode::G_VECREDUCE_FMUL:
3606 case TargetOpcode::G_VECREDUCE_FMIN:
3607 case TargetOpcode::G_VECREDUCE_FMAX:
3608 case TargetOpcode::G_VECREDUCE_FMINIMUM:
3609 case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
3614 LLT VecTy = MRI.getType(VecReg);
3621 case TargetOpcode::G_VSCALE: {
3628 SrcMO.
setCImm(ConstantInt::get(Ctx, Val));
3633 case TargetOpcode::G_SPLAT_VECTOR: {
3642 case TargetOpcode::G_INSERT_SUBVECTOR: {
3650 LLT SubVecTy = MRI.getType(SubVec);
3654 auto BigZExt =
MIRBuilder.buildZExt(WideTy, BigVec);
3655 auto SubZExt =
MIRBuilder.buildZExt(SubVecWideTy, SubVec);
3656 auto WideInsert =
MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
3660 auto SplatZero =
MIRBuilder.buildSplatVector(
3665 MI.eraseFromParent();
3669 case TargetOpcode::G_BITCAST:
3681 if (MRI.getType(Dst) == MRI.getType(Src)) {
3682 Observer.changingAllUsesOfReg(MRI, Dst);
3683 MRI.replaceRegWith(Dst, Src);
3684 Observer.finishedChangingAllUsesOfReg();
3685 MI.eraseFromParent();
3694 auto Unmerge =
B.buildUnmerge(Ty, Src);
3695 for (
int I = 0,
E = Unmerge->getNumOperands() - 1;
I !=
E; ++
I)
3704 unsigned AddrSpace =
DL.getDefaultGlobalsAddressSpace();
3718 MIRBuilder.
buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
3727 MI.eraseFromParent();
3738 MI.eraseFromParent();
3745 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
3746 if (SrcTy.isVector()) {
3750 if (DstTy.isVector()) {
3751 int NumDstElt = DstTy.getNumElements();
3752 int NumSrcElt = SrcTy.getNumElements();
3755 LLT DstCastTy = DstEltTy;
3756 LLT SrcPartTy = SrcEltTy;
3760 if (NumSrcElt < NumDstElt) {
3771 SrcPartTy = SrcEltTy;
3772 }
else if (NumSrcElt > NumDstElt) {
3784 DstCastTy = DstEltTy;
3789 SrcReg =
MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
3793 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3794 MI.eraseFromParent();
3798 if (DstTy.isVector()) {
3801 MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
3802 MI.eraseFromParent();
3818 unsigned NewEltSize,
3819 unsigned OldEltSize) {
3820 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3821 LLT IdxTy =
B.getMRI()->getType(Idx);
3824 auto OffsetMask =
B.buildConstant(
3826 auto OffsetIdx =
B.buildAnd(IdxTy, Idx, OffsetMask);
3827 return B.buildShl(IdxTy, OffsetIdx,
3828 B.buildConstant(IdxTy,
Log2_32(OldEltSize))).getReg(0);
3843 auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] =
MI.getFirst3RegLLTs();
3847 unsigned OldNumElts = SrcVecTy.getNumElements();
3854 if (NewNumElts > OldNumElts) {
3865 if (NewNumElts % OldNumElts != 0)
3869 const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
3873 auto NewEltsPerOldEltK =
MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);
3876 auto NewBaseIdx =
MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);
3878 for (
unsigned I = 0;
I < NewEltsPerOldElt; ++
I) {
3879 auto IdxOffset =
MIRBuilder.buildConstant(IdxTy,
I);
3880 auto TmpIdx =
MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
3881 auto Elt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
3882 NewOps[
I] = Elt.getReg(0);
3885 auto NewVec =
MIRBuilder.buildBuildVector(MidTy, NewOps);
3887 MI.eraseFromParent();
3891 if (NewNumElts < OldNumElts) {
3892 if (NewEltSize % OldEltSize != 0)
3914 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
3915 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
3918 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
3922 WideElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
3923 ScaledIdx).getReg(0);
3931 auto ExtractedBits =
MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
3933 MI.eraseFromParent();
3947 LLT TargetTy =
B.getMRI()->getType(TargetReg);
3948 LLT InsertTy =
B.getMRI()->getType(InsertReg);
3949 auto ZextVal =
B.buildZExt(TargetTy, InsertReg);
3950 auto ShiftedInsertVal =
B.buildShl(TargetTy, ZextVal, OffsetBits);
3953 auto EltMask =
B.buildConstant(
3957 auto ShiftedMask =
B.buildShl(TargetTy, EltMask, OffsetBits);
3958 auto InvShiftedMask =
B.buildNot(TargetTy, ShiftedMask);
3961 auto MaskedOldElt =
B.buildAnd(TargetTy, TargetReg, InvShiftedMask);
3965 return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
3979 auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
3980 MI.getFirst4RegLLTs();
3992 if (NewNumElts < OldNumElts) {
3993 if (NewEltSize % OldEltSize != 0)
4002 const unsigned Log2EltRatio =
Log2_32(NewEltSize / OldEltSize);
4003 auto Log2Ratio =
MIRBuilder.buildConstant(IdxTy, Log2EltRatio);
4006 auto ScaledIdx =
MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);
4010 ExtractedElt =
MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
4011 ScaledIdx).getReg(0);
4021 InsertedElt =
MIRBuilder.buildInsertVectorElement(
4022 CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
4026 MI.eraseFromParent();
4056 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
4060 if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
4061 return UnableToLegalize;
4066 for (
unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
4068 MIRBuilder.
buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
4077 MI.eraseFromParent();
4095 LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
4096 LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));
4106 auto Inp1 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
4107 auto Inp2 =
MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
4109 MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
4110 MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);
4112 MI.eraseFromParent();
4142 LLT DstTy = MRI.getType(Dst);
4143 LLT SrcTy = MRI.getType(Src);
4149 if (DstTy == CastTy)
4157 if (CastEltSize < DstEltSize)
4160 auto AdjustAmt = CastEltSize / DstEltSize;
4161 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4162 SrcTyMinElts % AdjustAmt != 0)
4167 auto CastVec =
MIRBuilder.buildBitcast(SrcTy, Src);
4168 auto PromotedES =
MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
4171 ES->eraseFromParent();
4206 LLT DstTy = MRI.getType(Dst);
4207 LLT BigVecTy = MRI.getType(BigVec);
4208 LLT SubVecTy = MRI.getType(SubVec);
4210 if (DstTy == CastTy)
4225 if (CastEltSize < DstEltSize)
4228 auto AdjustAmt = CastEltSize / DstEltSize;
4229 if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
4230 BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
4236 auto CastBigVec =
MIRBuilder.buildBitcast(BigVecTy, BigVec);
4237 auto CastSubVec =
MIRBuilder.buildBitcast(SubVecTy, SubVec);
4239 MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
4242 ES->eraseFromParent();
4250 LLT DstTy = MRI.getType(DstReg);
4260 if (MemSizeInBits != MemStoreSizeInBits) {
4277 LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
4281 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4282 MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
4284 auto NewLoad =
MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
4287 MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
4289 MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
4292 if (DstTy != LoadTy)
4300 if (
MIRBuilder.getDataLayout().isBigEndian())
4318 uint64_t LargeSplitSize, SmallSplitSize;
4323 SmallSplitSize = MemSizeInBits - LargeSplitSize;
4330 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4333 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4344 if (Alignment.
value() * 8 > MemSizeInBits &&
4349 auto NewLoad =
MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
4366 LLT PtrTy = MRI.getType(PtrReg);
4379 auto LargeLoad =
MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
4382 auto OffsetCst =
MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
4383 Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
4384 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
4386 SmallPtr, *SmallMMO);
4388 auto ShiftAmt =
MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
4389 auto Shift =
MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);
4391 if (AnyExtTy == DstTy)
4392 MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
4394 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4398 auto Or =
MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
4418 LLT SrcTy = MRI.getType(SrcReg);
4426 if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
4432 if (StoreSizeInBits > SrcTy.getSizeInBits()) {
4434 SrcReg =
MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
4438 auto ZextInReg =
MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);
4442 MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
4457 uint64_t LargeSplitSize, SmallSplitSize;
4464 if (TLI.allowsMemoryAccess(Ctx,
MIRBuilder.getDataLayout(), MemTy, MMO))
4467 SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
4476 if (SrcTy.isPointer()) {
4481 auto ExtVal =
MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);
4484 auto ShiftAmt =
MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
4485 auto SmallVal =
MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);
4488 LLT PtrTy = MRI.getType(PtrReg);
4490 LargeSplitSize / 8);
4491 auto SmallPtr =
MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);
4497 MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
4498 MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
4507 LLT SrcTy = MRI.getType(SrcReg);
4513 assert(SrcTy.isVector() &&
"Expect a vector store type");
4520 auto CurrVal =
MIRBuilder.buildConstant(IntTy, 0);
4524 auto Elt =
MIRBuilder.buildExtractVectorElement(
4525 SrcTy.getElementType(), SrcReg,
MIRBuilder.buildConstant(IdxTy,
I));
4526 auto Trunc =
MIRBuilder.buildTrunc(MemScalarTy, Elt);
4527 auto ZExt =
MIRBuilder.buildZExt(IntTy, Trunc);
4533 auto Shifted =
MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
4534 CurrVal =
MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
4538 MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
4549 switch (
MI.getOpcode()) {
4550 case TargetOpcode::G_LOAD: {
4568 case TargetOpcode::G_STORE: {
4584 case TargetOpcode::G_SELECT: {
4588 if (MRI.getType(
MI.getOperand(1).getReg()).isVector()) {
4590 dbgs() <<
"bitcast action not implemented for vector select\n");
4601 case TargetOpcode::G_AND:
4602 case TargetOpcode::G_OR:
4603 case TargetOpcode::G_XOR: {
4611 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
4613 case TargetOpcode::G_INSERT_VECTOR_ELT:
4615 case TargetOpcode::G_CONCAT_VECTORS:
4617 case TargetOpcode::G_SHUFFLE_VECTOR:
4619 case TargetOpcode::G_EXTRACT_SUBVECTOR:
4621 case TargetOpcode::G_INSERT_SUBVECTOR:
4629void LegalizerHelper::changeOpcode(
MachineInstr &
MI,
unsigned NewOpcode) {
4638 switch(
MI.getOpcode()) {
4641 case TargetOpcode::G_FCONSTANT:
4643 case TargetOpcode::G_BITCAST:
4645 case TargetOpcode::G_SREM:
4646 case TargetOpcode::G_UREM: {
4647 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
4649 MIRBuilder.buildInstr(
MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
4650 {MI.getOperand(1), MI.getOperand(2)});
4652 auto Prod =
MIRBuilder.buildMul(Ty, Quot,
MI.getOperand(2));
4654 MI.eraseFromParent();
4657 case TargetOpcode::G_SADDO:
4658 case TargetOpcode::G_SSUBO:
4660 case TargetOpcode::G_SADDE:
4662 case TargetOpcode::G_SSUBE:
4664 case TargetOpcode::G_UMULH:
4665 case TargetOpcode::G_SMULH:
4667 case TargetOpcode::G_SMULO:
4668 case TargetOpcode::G_UMULO: {
4671 auto [Res, Overflow, LHS, RHS] =
MI.getFirst4Regs();
4672 LLT Ty = MRI.getType(Res);
4674 unsigned Opcode =
MI.getOpcode() == TargetOpcode::G_SMULO
4675 ? TargetOpcode::G_SMULH
4676 : TargetOpcode::G_UMULH;
4680 MI.setDesc(
TII.get(TargetOpcode::G_MUL));
4681 MI.removeOperand(1);
4684 auto HiPart =
MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
4692 if (Opcode == TargetOpcode::G_SMULH) {
4693 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
4694 auto Shifted =
MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
4701 case TargetOpcode::G_FNEG: {
4702 auto [Res, ResTy, SubByReg, SubByRegTy] =
MI.getFirst2RegLLTs();
4705 Register CastedSubByReg = SubByReg;
4707 if (!SubByRegTy.getScalarType().isAnyScalar() &&
4708 !SubByRegTy.getScalarType().isInteger()) {
4709 auto BitcastDst = SubByRegTy.changeElementType(
4711 CastedSubByReg =
MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
4717 if (ResTy != TyInt) {
4719 MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
4722 MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
4724 MI.eraseFromParent();
4727 case TargetOpcode::G_FSUB:
4728 case TargetOpcode::G_STRICT_FSUB: {
4729 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
4730 LLT Ty = MRI.getType(Res);
4735 if (
MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
4736 MIRBuilder.buildStrictFAdd(Res, LHS, Neg,
MI.getFlags());
4740 MI.eraseFromParent();
4743 case TargetOpcode::G_FMAD:
4745 case TargetOpcode::G_FFLOOR:
4747 case TargetOpcode::G_LROUND:
4748 case TargetOpcode::G_LLROUND: {
4751 LLT SrcTy = MRI.getType(SrcReg);
4752 auto Round =
MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
4755 MI.eraseFromParent();
4758 case TargetOpcode::G_INTRINSIC_ROUND:
4760 case TargetOpcode::G_FRINT: {
4763 changeOpcode(
MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
4766 case TargetOpcode::G_INTRINSIC_LRINT:
4767 case TargetOpcode::G_INTRINSIC_LLRINT: {
4770 LLT SrcTy = MRI.getType(SrcReg);
4772 MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
4774 MI.eraseFromParent();
4777 case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
4778 auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] =
MI.getFirst5Regs();
4779 Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
4780 MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
4781 **
MI.memoperands_begin());
4783 MIRBuilder.buildCopy(OldValRes, NewOldValRes);
4784 MI.eraseFromParent();
4787 case TargetOpcode::G_LOAD:
4788 case TargetOpcode::G_SEXTLOAD:
4789 case TargetOpcode::G_ZEXTLOAD:
4791 case TargetOpcode::G_STORE:
4793 case TargetOpcode::G_CTLZ_ZERO_POISON:
4794 case TargetOpcode::G_CTTZ_ZERO_POISON:
4795 case TargetOpcode::G_CTLZ:
4796 case TargetOpcode::G_CTTZ:
4797 case TargetOpcode::G_CTPOP:
4798 case TargetOpcode::G_CTLS:
4801 auto [Res, CarryOut, LHS, RHS] =
MI.getFirst4Regs();
4803 Register NewRes = MRI.cloneVirtualRegister(Res);
4810 MI.eraseFromParent();
4814 auto [Res, CarryOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
4815 const LLT CondTy = MRI.getType(CarryOut);
4816 const LLT Ty = MRI.getType(Res);
4818 Register NewRes = MRI.cloneVirtualRegister(Res);
4821 auto TmpRes =
MIRBuilder.buildAdd(Ty, LHS, RHS);
4827 auto ZExtCarryIn =
MIRBuilder.buildZExt(Ty, CarryIn);
4828 MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);
4835 auto Carry2 =
MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
4840 MI.eraseFromParent();
4844 auto [Res, BorrowOut, LHS, RHS] =
MI.getFirst4Regs();
4849 MI.eraseFromParent();
4853 auto [Res, BorrowOut, LHS, RHS, BorrowIn] =
MI.getFirst5Regs();
4854 const LLT CondTy = MRI.getType(BorrowOut);
4855 const LLT Ty = MRI.getType(Res);
4858 auto TmpRes =
MIRBuilder.buildSub(Ty, LHS, RHS);
4864 auto ZExtBorrowIn =
MIRBuilder.buildZExt(Ty, BorrowIn);
4865 MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);
4872 auto Borrow2 =
MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
4873 MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);
4875 MI.eraseFromParent();
4915 case G_MERGE_VALUES:
4917 case G_UNMERGE_VALUES:
4919 case TargetOpcode::G_SEXT_INREG: {
4920 assert(
MI.getOperand(2).isImm() &&
"Expected immediate");
4921 int64_t SizeInBits =
MI.getOperand(2).getImm();
4923 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
4924 LLT DstTy = MRI.getType(DstReg);
4925 Register TmpRes = MRI.createGenericVirtualRegister(DstTy);
4928 MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
4929 MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
4930 MI.eraseFromParent();
4933 case G_EXTRACT_VECTOR_ELT:
4934 case G_INSERT_VECTOR_ELT:
4936 case G_SHUFFLE_VECTOR:
4938 case G_VECTOR_COMPRESS:
4940 case G_DYN_STACKALLOC:
4942 case G_INSERT_SUBVECTOR: {
4943 if (MRI.getType(
MI.getOperand(1).getReg()).isScalable() ||
4944 MRI.getType(
MI.getOperand(2).getReg()).isScalable())
4949 Register Subvector =
MI.getOperand(2).getReg();
4950 auto InsertionPointImm =
MI.getOperand(3).getImm();
4953 LLT DstTy = MRI.getType(Subvector);
4957 bool InsertInLowHalf = InsertionPointImm == 0;
4958 auto Extract =
MIRBuilder.buildExtractSubvector(
4962 auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
4963 auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;
4965 MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {
MI.getOperand(0)},
4966 {LowHalf, HighHalf});
4967 MI.eraseFromParent();
4973 Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
4974 MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);
4980 if (i >= InsertionPointImm &&
4982 Mask.push_back(VectorTy.
getNumElements() + i - InsertionPointImm);
4990 MI.eraseFromParent();
4994 case G_EXTRACT_SUBVECTOR: {
4997 uint64_t ExtractionPointImm =
MI.getOperand(2).getImm();
4999 LLT SrcTy = MRI.getType(SrcReg);
5000 LLT DstTy = MRI.getType(DstReg);
5002 if (SrcTy.isScalable() || DstTy.
isScalable())
5013 .buildExtractVectorElementConstant(SrcTy.getScalarType(), SrcReg,
5014 ExtractionPointImm + i)
5018 MIRBuilder.buildBuildVector(DstReg, ExtractedElements);
5019 MI.eraseFromParent();
5024 case G_STACKRESTORE:
5034 case G_READ_REGISTER:
5035 case G_WRITE_REGISTER:
5042 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5043 if (LI.isLegalOrCustom({G_UMIN, Ty}))
5049 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5054 if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
5065 bool IsSigned =
MI.getOpcode() == G_ABDS;
5066 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
5067 if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
5068 (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
5091 case G_MEMCPY_INLINE:
5092 case G_MEMSET_INLINE:
5104 case G_ATOMICRMW_SUB: {
5105 auto [Ret, Mem, Val] =
MI.getFirst3Regs();
5106 const LLT ValTy = MRI.getType(Val);
5110 MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
5111 MI.eraseFromParent();
5137 unsigned AddrSpace =
DL.getAllocaAddrSpace();
5141 return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
5147 Align StackTypeAlign =
5154 MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
5155 return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
5160 LLT IdxTy =
B.getMRI()->getType(IdxReg);
5172 return B.buildAnd(IdxTy, IdxReg,
B.buildConstant(IdxTy, Imm)).getReg(0);
5175 return B.buildUMin(IdxTy, IdxReg,
B.buildConstant(IdxTy, NElts - 1))
5186 "Converting bits to bytes lost precision");
5192 unsigned AS = MRI.getType(VecPtr).getAddressSpace();
5193 unsigned IndexSizeInBits =
DL.getIndexSize(AS) * 8;
5195 if (IdxTy != MRI.getType(Index))
5196 Index =
MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);
5201 LLT PtrTy = MRI.getType(VecPtr);
5202 return MIRBuilder.buildPtrAdd(PtrTy, VecPtr,
Mul).getReg(0);
5210 std::initializer_list<unsigned> NonVecOpIndices) {
5211 if (
MI.getNumMemOperands() != 0)
5219 for (
unsigned OpIdx = 1; OpIdx <
MI.getNumOperands(); ++OpIdx) {
5228 if (!Ty.isVector()) {
5234 if (Ty.getNumElements() != NumElts)
5249 assert(Ty.isVector() &&
"Expected vector type");
5251 int NumParts, NumLeftover;
5252 std::tie(NumParts, NumLeftover) =
5255 assert(NumParts > 0 &&
"Error in getNarrowTypeBreakDown");
5256 for (
int i = 0; i < NumParts; ++i) {
5261 assert(NumLeftover == 1 &&
"expected exactly one leftover");
5270 for (
unsigned i = 0; i <
N; ++i) {
5272 Ops.push_back(
Op.getReg());
5273 else if (
Op.isImm())
5274 Ops.push_back(
Op.getImm());
5275 else if (
Op.isPredicate())
5297 std::initializer_list<unsigned> NonVecOpIndices) {
5299 "Non-compatible opcode or not specified non-vector operands");
5300 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5302 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5303 unsigned NumDefs =
MI.getNumDefs();
5311 for (
unsigned i = 0; i < NumDefs; ++i) {
5312 makeDstOps(OutputOpsPieces[i], MRI.getType(
MI.getReg(i)), NumElts);
5320 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5321 ++UseIdx, ++UseNo) {
5324 MI.getOperand(UseIdx));
5333 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5337 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5339 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5340 Defs.
push_back(OutputOpsPieces[DstNo][i]);
5343 for (
unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
5344 Uses.push_back(InputOpsPieces[InputNo][i]);
5347 for (
unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
5348 OutputRegs[DstNo].push_back(
I.getReg(DstNo));
5353 for (
unsigned i = 0; i < NumDefs; ++i)
5354 mergeMixedSubvectors(
MI.getReg(i), OutputRegs[i]);
5356 for (
unsigned i = 0; i < NumDefs; ++i)
5357 MIRBuilder.buildMergeLikeInstr(
MI.getReg(i), OutputRegs[i]);
5360 MI.eraseFromParent();
5367 unsigned OrigNumElts = MRI.getType(
MI.getReg(0)).getNumElements();
5369 unsigned NumInputs =
MI.getNumOperands() -
MI.getNumDefs();
5370 unsigned NumDefs =
MI.getNumDefs();
5374 makeDstOps(OutputOpsPieces, MRI.getType(
MI.getReg(0)), NumElts);
5379 for (
unsigned UseIdx = NumDefs, UseNo = 0; UseIdx <
MI.getNumOperands();
5380 UseIdx += 2, ++UseNo) {
5388 unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
5390 for (
unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
5391 auto Phi =
MIRBuilder.buildInstr(TargetOpcode::G_PHI);
5393 MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
5396 for (
unsigned j = 0; j < NumInputs / 2; ++j) {
5397 Phi.addUse(InputOpsPieces[j][i]);
5398 Phi.add(
MI.getOperand(1 + j * 2 + 1));
5408 mergeMixedSubvectors(
MI.getReg(0), OutputRegs);
5410 MIRBuilder.buildMergeLikeInstr(
MI.getReg(0), OutputRegs);
5413 MI.eraseFromParent();
5421 const int NumDst =
MI.getNumOperands() - 1;
5422 const Register SrcReg =
MI.getOperand(NumDst).getReg();
5423 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
5424 LLT SrcTy = MRI.getType(SrcReg);
5426 if (TypeIdx != 1 || NarrowTy == DstTy)
5433 assert(SrcTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5436 if ((SrcTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5450 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5451 const int NumUnmerge = Unmerge->getNumOperands() - 1;
5452 const int PartsPerUnmerge = NumDst / NumUnmerge;
5454 for (
int I = 0;
I != NumUnmerge; ++
I) {
5455 auto MIB =
MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);
5457 for (
int J = 0; J != PartsPerUnmerge; ++J)
5458 MIB.addDef(
MI.getOperand(
I * PartsPerUnmerge + J).getReg());
5459 MIB.addUse(Unmerge.getReg(
I));
5462 MI.eraseFromParent();
5469 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5473 assert(DstTy.isVector() && NarrowTy.
isVector() &&
"Expected vector types");
5475 if (NarrowTy == SrcTy)
5483 assert(SrcTy.isVector() &&
"Expected vector types");
5485 if ((DstTy.getSizeInBits() % NarrowTy.
getSizeInBits() != 0) ||
5499 for (
unsigned i = 1; i <
MI.getNumOperands(); ++i) {
5500 auto Unmerge =
MIRBuilder.buildUnmerge(EltTy,
MI.getOperand(i).getReg());
5501 for (
unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
5507 unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
5508 for (
unsigned i = 0,
Offset = 0; i < NumNarrowTyPieces;
5509 ++i,
Offset += NumNarrowTyElts) {
5512 MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
5515 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5516 MI.eraseFromParent();
5520 assert(TypeIdx == 0 &&
"Bad type index");
5521 if ((NarrowTy.
getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
5536 unsigned NumParts = DstTy.getNumElements() / NarrowTy.
getNumElements();
5537 unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
5539 for (
unsigned i = 0; i < NumParts; ++i) {
5541 for (
unsigned j = 0; j < NumElts; ++j)
5542 Sources.
push_back(
MI.getOperand(1 + i * NumElts + j).getReg());
5544 MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
5547 MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
5548 MI.eraseFromParent();
5556 auto [DstReg, SrcVec] =
MI.getFirst2Regs();
5558 bool IsInsert =
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;
5560 assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) &&
"not a vector type index");
5562 InsertVal =
MI.getOperand(2).getReg();
5564 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
5565 LLT VecTy = MRI.getType(SrcVec);
5571 uint64_t IdxVal = MaybeCst->Value.getZExtValue();
5575 MI.eraseFromParent();
5584 SplitPieces[IdxVal] = InsertVal;
5585 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0).getReg(), SplitPieces);
5587 MIRBuilder.buildCopy(
MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
5591 LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);
5594 LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
5595 TargetOpcode::G_ANYEXT);
5599 LLT IdxTy = MRI.getType(Idx);
5600 int64_t PartIdx = IdxVal / NewNumElts;
5602 MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);
5605 LLT PartTy = MRI.getType(VecParts[PartIdx]);
5608 auto InsertPart =
MIRBuilder.buildInsertVectorElement(
5609 PartTy, VecParts[PartIdx], InsertVal, NewIdx);
5610 VecParts[PartIdx] = InsertPart.getReg(0);
5614 buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
5616 MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
5620 MI.eraseFromParent();
5640 LLVM_DEBUG(
dbgs() <<
"Can't narrow load/store to non-byte-sized type\n");
5652 LLT ValTy = MRI.getType(ValReg);
5661 int NumLeftover = -1;
5667 if (
extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
5669 NumParts = NarrowRegs.
size();
5670 NumLeftover = NarrowLeftoverRegs.
size();
5677 LLT PtrTy = MRI.getType(AddrReg);
5687 auto MMO = LdStMI.
getMMO();
5689 unsigned NumParts,
unsigned Offset) ->
unsigned {
5692 for (
unsigned Idx = 0, E = NumParts; Idx != E &&
Offset < TotalSize;
5694 unsigned ByteOffset =
Offset / 8;
5697 MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
5704 Register Dst = MRI.createGenericVirtualRegister(PartTy);
5705 ValRegs.push_back(Dst);
5706 MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
5708 MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
5717 unsigned HandledOffset =
5718 splitTypePieces(NarrowTy, NarrowRegs, NumParts,
Offset);
5722 splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);
5725 insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
5726 LeftoverTy, NarrowLeftoverRegs);
5740 switch (
MI.getOpcode()) {
5741 case G_IMPLICIT_DEF:
5757 case G_FCANONICALIZE:
5774 case G_INTRINSIC_LRINT:
5775 case G_INTRINSIC_LLRINT:
5776 case G_INTRINSIC_ROUND:
5777 case G_INTRINSIC_ROUNDEVEN:
5780 case G_INTRINSIC_TRUNC:
5808 case G_FMINNUM_IEEE:
5809 case G_FMAXNUM_IEEE:
5831 case G_CTLZ_ZERO_POISON:
5833 case G_CTTZ_ZERO_POISON:
5850 case G_ADDRSPACE_CAST:
5863 case G_STRICT_FLDEXP:
5865 case G_TRUNC_SSAT_S:
5866 case G_TRUNC_SSAT_U:
5867 case G_TRUNC_USAT_U:
5875 if (MRI.getType(
MI.getOperand(1).getReg()).isVector())
5880 case G_UNMERGE_VALUES:
5882 case G_BUILD_VECTOR:
5883 assert(TypeIdx == 0 &&
"not a vector type index");
5885 case G_CONCAT_VECTORS:
5889 case G_EXTRACT_SUBVECTOR: {
5891 LLT DstTy = MRI.getType(DstReg);
5893 uint64_t InsertionPointImm =
MI.getOperand(2).getImm();
5903 auto Unmerge =
MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
5908 MIRBuilder.buildCopy(DstReg, Unmerge.getReg(RequiredSubvectorIndex));
5911 DstReg, Unmerge.getReg(RequiredSubvectorIndex),
5914 MI.eraseFromParent();
5917 case G_EXTRACT_VECTOR_ELT:
5918 case G_INSERT_VECTOR_ELT:
5927 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
5928 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
5930 case G_SHUFFLE_VECTOR:
5936 case G_INTRINSIC_FPTRUNC_ROUND:
5946 assert(
MI.getOpcode() == TargetOpcode::G_BITCAST &&
5947 "Not a bitcast operation");
5952 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
5954 unsigned NewElemCount =
5957 if (NewElemCount == 1) {
5960 auto Unmerge =
MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
5967 if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
5976 MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
5977 MI.eraseFromParent();
5983 assert(
MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
5987 auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
5988 MI.getFirst3RegLLTs();
5991 if (DstTy != Src1Ty)
5993 if (DstTy != Src2Ty)
6008 Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
6024 unsigned InputUsed[2] = {-1U, -1U};
6025 unsigned FirstMaskIdx =
High * NewElts;
6026 bool UseBuildVector =
false;
6027 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6029 int Idx = Mask[FirstMaskIdx + MaskOffset];
6034 if (
Input >= std::size(Inputs)) {
6041 Idx -=
Input * NewElts;
6045 for (OpNo = 0; OpNo < std::size(InputUsed); ++OpNo) {
6046 if (InputUsed[OpNo] ==
Input) {
6049 }
else if (InputUsed[OpNo] == -1U) {
6051 InputUsed[OpNo] =
Input;
6056 if (OpNo >= std::size(InputUsed)) {
6059 UseBuildVector =
true;
6064 Ops.push_back(Idx + OpNo * NewElts);
6067 if (UseBuildVector) {
6072 for (
unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
6074 int Idx = Mask[FirstMaskIdx + MaskOffset];
6079 if (
Input >= std::size(Inputs)) {
6086 Idx -=
Input * NewElts;
6090 .buildExtractVectorElement(
6091 EltTy, Inputs[
Input],
6097 Output =
MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
6098 }
else if (InputUsed[0] == -1U) {
6100 Output =
MIRBuilder.buildUndef(NarrowTy).getReg(0);
6101 }
else if (NewElts == 1) {
6102 Output =
MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
6104 Register Op0 = Inputs[InputUsed[0]];
6108 : Inputs[InputUsed[1]];
6110 Output =
MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1,
Ops).getReg(0);
6117 MI.eraseFromParent();
6130 auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();
6136 unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
6139 const unsigned NumParts =
6141 : SrcTy.getNumElements();
6145 if (DstTy != NarrowTy)
6151 unsigned NumPartsLeft = NumParts;
6152 while (NumPartsLeft > 1) {
6153 for (
unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
6156 .buildInstr(ScalarOpc, {NarrowTy},
6157 {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
6160 SplitSrcs = PartialResults;
6161 PartialResults.
clear();
6162 NumPartsLeft = SplitSrcs.
size();
6166 MI.eraseFromParent();
6171 for (
unsigned Idx = 1; Idx < NumParts; ++Idx)
6172 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
6175 MI.eraseFromParent();
6179 for (
unsigned Part = 0; Part < NumParts; ++Part) {
6181 MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
6189 return tryNarrowPow2Reduction(
MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
6192 Register Acc = PartialReductions[0];
6193 for (
unsigned Part = 1; Part < NumParts; ++Part) {
6194 if (Part == NumParts - 1) {
6196 {Acc, PartialReductions[Part]});
6199 .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
6203 MI.eraseFromParent();
6209 unsigned int TypeIdx,
6211 auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
6212 MI.getFirst3RegLLTs();
6213 if (!NarrowTy.
isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
6217 assert((
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
6218 MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
6219 "Unexpected vecreduce opcode");
6220 unsigned ScalarOpc =
MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
6221 ? TargetOpcode::G_FADD
6222 : TargetOpcode::G_FMUL;
6225 unsigned NumParts = SrcTy.getNumElements();
6228 for (
unsigned i = 0; i < NumParts; i++)
6229 Acc =
MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
6233 MI.eraseFromParent();
6240 unsigned ScalarOpc) {
6248 while (SplitSrcs.
size() > 1) {
6250 for (
unsigned Idx = 0; Idx < SplitSrcs.
size()-1; Idx += 2) {
6258 SplitSrcs = std::move(PartialRdxs);
6262 MI.getOperand(1).setReg(SplitSrcs[0]);
6269 const LLT HalfTy,
const LLT AmtTy) {
6271 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6272 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6276 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {InL, InH});
6277 MI.eraseFromParent();
6283 unsigned VTBits = 2 * NVTBits;
6286 if (
MI.getOpcode() == TargetOpcode::G_SHL) {
6287 if (Amt.
ugt(VTBits)) {
6289 }
else if (Amt.
ugt(NVTBits)) {
6292 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6293 }
else if (Amt == NVTBits) {
6301 NVT, InL,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6304 }
else if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6305 if (Amt.
ugt(VTBits)) {
6307 }
else if (Amt.
ugt(NVTBits)) {
6309 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6311 }
else if (Amt == NVTBits) {
6315 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6317 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6319 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6325 if (Amt.
ugt(VTBits)) {
6327 NVT, InH,
MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6328 }
else if (Amt.
ugt(NVTBits)) {
6330 MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
6332 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6333 }
else if (Amt == NVTBits) {
6336 MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
6338 auto ShiftAmtConst =
MIRBuilder.buildConstant(AmtTy, Amt);
6340 auto OrLHS =
MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
6342 NVT, InH,
MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
6349 MIRBuilder.buildMergeLikeInstr(
MI.getOperand(0), {Lo, Hi});
6350 MI.eraseFromParent();
6366 LLT DstTy = MRI.getType(DstReg);
6371 LLT ShiftAmtTy = MRI.getType(Amt);
6373 if (DstEltSize % 2 != 0)
6389 const unsigned NumParts = DstEltSize / RequestedTy.
getSizeInBits();
6400 const unsigned NewBitSize = DstEltSize / 2;
6412 auto NewBits =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);
6414 Register InL = MRI.createGenericVirtualRegister(HalfTy);
6415 Register InH = MRI.createGenericVirtualRegister(HalfTy);
6418 auto AmtExcess =
MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
6419 auto AmtLack =
MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);
6421 auto Zero =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6426 switch (
MI.getOpcode()) {
6427 case TargetOpcode::G_SHL: {
6429 auto LoS =
MIRBuilder.buildShl(HalfTy, InL, Amt);
6431 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
6432 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, Amt);
6433 auto HiS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6436 auto LoL =
MIRBuilder.buildConstant(HalfTy, 0);
6437 auto HiL =
MIRBuilder.buildShl(HalfTy, InL, AmtExcess);
6439 auto Lo =
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
6441 HalfTy, IsZero, InH,
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));
6443 ResultRegs[0] =
Lo.getReg(0);
6444 ResultRegs[1] =
Hi.getReg(0);
6447 case TargetOpcode::G_LSHR:
6448 case TargetOpcode::G_ASHR: {
6450 auto HiS =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy}, {InH, Amt});
6452 auto LoOr =
MIRBuilder.buildLShr(HalfTy, InL, Amt);
6453 auto HiOr =
MIRBuilder.buildShl(HalfTy, InH, AmtLack);
6454 auto LoS =
MIRBuilder.buildOr(HalfTy, LoOr, HiOr);
6458 if (
MI.getOpcode() == TargetOpcode::G_LSHR) {
6461 auto ShiftAmt =
MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
6462 HiL =
MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);
6464 auto LoL =
MIRBuilder.buildInstr(
MI.getOpcode(), {HalfTy},
6468 HalfTy, IsZero, InL,
MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));
6470 auto Hi =
MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);
6472 ResultRegs[0] =
Lo.getReg(0);
6473 ResultRegs[1] =
Hi.getReg(0);
6480 MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
6481 MI.eraseFromParent();
6490 LLT TargetTy,
LLT ShiftAmtTy) {
6493 assert(WordShiftConst && BitShiftConst &&
"Expected constants");
6495 const unsigned ShiftWords = WordShiftConst->getZExtValue();
6496 const unsigned ShiftBits = BitShiftConst->getZExtValue();
6497 const bool NeedsInterWordShift = ShiftBits != 0;
6500 case TargetOpcode::G_SHL: {
6503 if (PartIdx < ShiftWords)
6506 unsigned SrcIdx = PartIdx - ShiftWords;
6507 if (!NeedsInterWordShift)
6508 return SrcParts[SrcIdx];
6513 auto Lo =
MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
6517 return Hi.getReg(0);
6520 case TargetOpcode::G_LSHR: {
6521 unsigned SrcIdx = PartIdx + ShiftWords;
6522 if (SrcIdx >= NumParts)
6524 if (!NeedsInterWordShift)
6525 return SrcParts[SrcIdx];
6529 if (SrcIdx + 1 < NumParts) {
6530 auto Hi =
MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
6534 return Lo.getReg(0);
6537 case TargetOpcode::G_ASHR: {
6539 unsigned SrcIdx = PartIdx + ShiftWords;
6540 if (SrcIdx >= NumParts)
6542 if (!NeedsInterWordShift)
6543 return SrcParts[SrcIdx];
6548 (SrcIdx == NumParts - 1)
6552 (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.
SignBit;
6574 unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
6575 ?
static_cast<unsigned>(TargetOpcode::G_LSHR)
6580 MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
6589 LLT ShiftAmtTy = MRI.getType(ShiftAmt);
6590 auto ZeroConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6592 auto IsZeroBitShift =
6600 unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
6601 : TargetOpcode::G_SHL;
6604 auto TargetBitsConst =
6606 auto InvShiftAmt =
MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);
6611 .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
6616 auto ZeroReg =
MIRBuilder.buildConstant(TargetTy, 0);
6618 MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
6622 return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
6635 LLT DstTy = MRI.getType(DstReg);
6639 const unsigned NumParts = DstBits / TargetBits;
6641 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6651 MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
6652 MI.eraseFromParent();
6657 const unsigned ShiftWords = Amt.
getZExtValue() / TargetBits;
6658 const unsigned ShiftBits = Amt.
getZExtValue() % TargetBits;
6664 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
6668 if (
MI.getOpcode() == TargetOpcode::G_ASHR)
6671 .buildAShr(TargetTy, SrcParts[SrcParts.
size() - 1],
6672 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
6676 for (
unsigned I = 0;
I < NumParts; ++
I)
6678 Params, TargetTy, ShiftAmtTy);
6680 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6681 MI.eraseFromParent();
6690 LLT DstTy = MRI.getType(DstReg);
6691 LLT ShiftAmtTy = MRI.getType(AmtReg);
6695 const unsigned NumParts = DstBits / TargetBits;
6697 assert(DstBits % TargetBits == 0 &&
"Target type must evenly divide source");
6714 auto ZeroAmtConst =
MIRBuilder.buildConstant(ShiftAmtTy, 0);
6726 unsigned TargetBitsLog2 =
Log2_32(TargetBits);
6727 auto TargetBitsLog2Const =
6728 MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
6729 auto TargetBitsMask =
MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6732 MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
6734 MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);
6742 if (
MI.getOpcode() == TargetOpcode::G_ASHR) {
6743 auto TargetBitsMinusOneConst =
6744 MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
6746 .buildAShr(TargetTy, SrcParts[NumParts - 1],
6747 TargetBitsMinusOneConst)
6750 FillValue = ZeroReg;
6758 for (
unsigned I = 0;
I < NumParts; ++
I) {
6760 Register InBoundsResult = FillValue;
6770 for (
unsigned K = 0; K < NumParts; ++K) {
6771 auto WordShiftKConst =
MIRBuilder.buildConstant(ShiftAmtTy, K);
6773 WordShift, WordShiftKConst);
6785 switch (
MI.getOpcode()) {
6786 case TargetOpcode::G_SHL:
6787 MainSrcIdx = (int)
I - (
int)K;
6788 CarrySrcIdx = MainSrcIdx - 1;
6790 case TargetOpcode::G_LSHR:
6791 case TargetOpcode::G_ASHR:
6792 MainSrcIdx = (int)
I + (
int)K;
6793 CarrySrcIdx = MainSrcIdx + 1;
6801 if (MainSrcIdx >= 0 && MainSrcIdx < (
int)NumParts) {
6802 Register MainOp = SrcParts[MainSrcIdx];
6806 if (CarrySrcIdx >= 0 && CarrySrcIdx < (
int)NumParts)
6807 CarryOp = SrcParts[CarrySrcIdx];
6808 else if (
MI.getOpcode() == TargetOpcode::G_ASHR &&
6809 CarrySrcIdx >= (
int)NumParts)
6810 CarryOp = FillValue;
6816 ResultForK = FillValue;
6822 .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
6829 .buildSelect(TargetTy, IsZeroShift, SrcParts[
I], InBoundsResult)
6833 MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
6834 MI.eraseFromParent();
6841 assert(TypeIdx == 0 &&
"Expecting only Idx 0");
6844 for (
unsigned I = 1, E =
MI.getNumOperands();
I != E;
I += 2) {
6859 assert(Ty.isScalar() &&
"Expected scalar type to make neutral element for");
6864 "getNeutralElementForVecReduce called with invalid opcode!");
6865 case TargetOpcode::G_VECREDUCE_ADD:
6866 case TargetOpcode::G_VECREDUCE_OR:
6867 case TargetOpcode::G_VECREDUCE_XOR:
6868 case TargetOpcode::G_VECREDUCE_UMAX:
6870 case TargetOpcode::G_VECREDUCE_MUL:
6872 case TargetOpcode::G_VECREDUCE_AND:
6873 case TargetOpcode::G_VECREDUCE_UMIN:
6876 case TargetOpcode::G_VECREDUCE_SMAX:
6879 case TargetOpcode::G_VECREDUCE_SMIN:
6882 case TargetOpcode::G_VECREDUCE_FADD:
6884 case TargetOpcode::G_VECREDUCE_FMUL:
6886 case TargetOpcode::G_VECREDUCE_FMINIMUM:
6887 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
6888 assert(
false &&
"getNeutralElementForVecReduce unimplemented for "
6889 "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
6897 unsigned Opc =
MI.getOpcode();
6899 case TargetOpcode::G_IMPLICIT_DEF:
6900 case TargetOpcode::G_LOAD: {
6908 case TargetOpcode::G_STORE:
6915 case TargetOpcode::G_AND:
6916 case TargetOpcode::G_OR:
6917 case TargetOpcode::G_XOR:
6918 case TargetOpcode::G_ADD:
6919 case TargetOpcode::G_SUB:
6920 case TargetOpcode::G_MUL:
6921 case TargetOpcode::G_FADD:
6922 case TargetOpcode::G_FSUB:
6923 case TargetOpcode::G_FMUL:
6924 case TargetOpcode::G_FDIV:
6925 case TargetOpcode::G_FCOPYSIGN:
6926 case TargetOpcode::G_UADDSAT:
6927 case TargetOpcode::G_USUBSAT:
6928 case TargetOpcode::G_SADDSAT:
6929 case TargetOpcode::G_SSUBSAT:
6930 case TargetOpcode::G_SMIN:
6931 case TargetOpcode::G_SMAX:
6932 case TargetOpcode::G_UMIN:
6933 case TargetOpcode::G_UMAX:
6934 case TargetOpcode::G_FMINNUM:
6935 case TargetOpcode::G_FMAXNUM:
6936 case TargetOpcode::G_FMINNUM_IEEE:
6937 case TargetOpcode::G_FMAXNUM_IEEE:
6938 case TargetOpcode::G_FMINIMUM:
6939 case TargetOpcode::G_FMAXIMUM:
6940 case TargetOpcode::G_FMINIMUMNUM:
6941 case TargetOpcode::G_FMAXIMUMNUM:
6942 case TargetOpcode::G_STRICT_FADD:
6943 case TargetOpcode::G_STRICT_FSUB:
6944 case TargetOpcode::G_STRICT_FMUL: {
6952 case TargetOpcode::G_SHL:
6953 case TargetOpcode::G_ASHR:
6954 case TargetOpcode::G_LSHR: {
6960 MRI.getType(
MI.getOperand(2).getReg()).getElementType());
6966 case TargetOpcode::G_FMA:
6967 case TargetOpcode::G_STRICT_FMA:
6968 case TargetOpcode::G_FSHR:
6969 case TargetOpcode::G_FSHL: {
6978 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
6979 case TargetOpcode::G_EXTRACT:
6986 case TargetOpcode::G_INSERT:
6987 case TargetOpcode::G_INSERT_VECTOR_ELT:
6988 case TargetOpcode::G_FREEZE:
6989 case TargetOpcode::G_FNEG:
6990 case TargetOpcode::G_FABS:
6991 case TargetOpcode::G_FSQRT:
6992 case TargetOpcode::G_FCEIL:
6993 case TargetOpcode::G_FFLOOR:
6994 case TargetOpcode::G_FNEARBYINT:
6995 case TargetOpcode::G_FRINT:
6996 case TargetOpcode::G_INTRINSIC_ROUND:
6997 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
6998 case TargetOpcode::G_INTRINSIC_TRUNC:
6999 case TargetOpcode::G_BITREVERSE:
7000 case TargetOpcode::G_BSWAP:
7001 case TargetOpcode::G_FCANONICALIZE:
7002 case TargetOpcode::G_SEXT_INREG:
7003 case TargetOpcode::G_ABS:
7004 case TargetOpcode::G_CTLZ:
7005 case TargetOpcode::G_CTPOP:
7013 case TargetOpcode::G_SELECT: {
7014 auto [DstReg, DstTy, CondReg, CondTy] =
MI.getFirst2RegLLTs();
7016 if (!CondTy.isScalar() ||
7022 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
7024 MI.getOperand(1).setReg(ShufSplat.getReg(0));
7029 if (CondTy.isVector())
7039 case TargetOpcode::G_UNMERGE_VALUES:
7041 case TargetOpcode::G_PHI:
7043 case TargetOpcode::G_SHUFFLE_VECTOR:
7045 case TargetOpcode::G_BUILD_VECTOR: {
7047 for (
auto Op :
MI.uses()) {
7055 MIRBuilder.buildDeleteTrailingVectorElements(
7056 MI.getOperand(0).getReg(),
MIRBuilder.buildInstr(
Opc, {MoreTy}, Elts));
7057 MI.eraseFromParent();
7060 case TargetOpcode::G_SEXT:
7061 case TargetOpcode::G_ZEXT:
7062 case TargetOpcode::G_ANYEXT:
7063 case TargetOpcode::G_TRUNC:
7064 case TargetOpcode::G_FPTRUNC:
7065 case TargetOpcode::G_FPEXT:
7066 case TargetOpcode::G_FPTOSI:
7067 case TargetOpcode::G_FPTOUI:
7068 case TargetOpcode::G_FPTOSI_SAT:
7069 case TargetOpcode::G_FPTOUI_SAT:
7070 case TargetOpcode::G_SITOFP:
7071 case TargetOpcode::G_UITOFP: {
7078 MRI.getType(
MI.getOperand(1).getReg()).getElementType());
7081 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7089 case TargetOpcode::G_ICMP:
7090 case TargetOpcode::G_FCMP: {
7098 MRI.getType(
MI.getOperand(0).getReg()).getElementType());
7103 case TargetOpcode::G_BITCAST: {
7107 LLT SrcTy = MRI.getType(
MI.getOperand(1).getReg());
7108 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
7124 case TargetOpcode::G_VECREDUCE_FADD:
7125 case TargetOpcode::G_VECREDUCE_FMUL:
7126 case TargetOpcode::G_VECREDUCE_ADD:
7127 case TargetOpcode::G_VECREDUCE_MUL:
7128 case TargetOpcode::G_VECREDUCE_AND:
7129 case TargetOpcode::G_VECREDUCE_OR:
7130 case TargetOpcode::G_VECREDUCE_XOR:
7131 case TargetOpcode::G_VECREDUCE_SMAX:
7132 case TargetOpcode::G_VECREDUCE_SMIN:
7133 case TargetOpcode::G_VECREDUCE_UMAX:
7134 case TargetOpcode::G_VECREDUCE_UMIN: {
7135 LLT OrigTy = MRI.getType(
MI.getOperand(1).getReg());
7137 auto NewVec =
MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
7138 auto NeutralElement = getNeutralElementForVecReduce(
7144 auto Idx =
MIRBuilder.buildConstant(IdxTy, i);
7145 NewVec =
MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
7146 NeutralElement, Idx);
7150 MO.
setReg(NewVec.getReg(0));
7162 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7164 unsigned MaskNumElts = Mask.size();
7165 unsigned SrcNumElts = SrcTy.getNumElements();
7168 if (MaskNumElts == SrcNumElts)
7171 if (MaskNumElts < SrcNumElts) {
7179 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7180 MI.getOperand(1).getReg(),
7181 MI.getOperand(2).getReg(), NewMask);
7182 MI.eraseFromParent();
7187 unsigned PaddedMaskNumElts =
alignTo(MaskNumElts, SrcNumElts);
7188 unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
7197 MOps1[0] =
MI.getOperand(1).getReg();
7198 MOps2[0] =
MI.getOperand(2).getReg();
7200 auto Src1 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
7201 auto Src2 =
MIRBuilder.buildConcatVectors(PaddedTy, MOps2);
7205 for (
unsigned I = 0;
I != MaskNumElts; ++
I) {
7207 if (Idx >=
static_cast<int>(SrcNumElts))
7208 Idx += PaddedMaskNumElts - SrcNumElts;
7213 if (MaskNumElts != PaddedMaskNumElts) {
7215 MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);
7218 for (
unsigned I = 0;
I < MaskNumElts; ++
I) {
7220 MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle,
I)
7225 MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
7228 MI.eraseFromParent();
7234 unsigned int TypeIdx,
LLT MoreTy) {
7235 auto [DstTy, Src1Ty, Src2Ty] =
MI.getFirst3LLTs();
7237 unsigned NumElts = DstTy.getNumElements();
7240 if (DstTy.isVector() && Src1Ty.isVector() &&
7241 DstTy.getNumElements() != Src1Ty.getNumElements()) {
7249 if (DstTy != Src1Ty || DstTy != Src2Ty)
7257 for (
unsigned I = 0;
I != NumElts; ++
I) {
7259 if (Idx <
static_cast<int>(NumElts))
7262 NewMask[
I] = Idx - NumElts + WidenNumElts;
7266 MIRBuilder.buildShuffleVector(
MI.getOperand(0).getReg(),
7267 MI.getOperand(1).getReg(),
7268 MI.getOperand(2).getReg(), NewMask);
7269 MI.eraseFromParent();
7278 unsigned SrcParts = Src1Regs.
size();
7279 unsigned DstParts = DstRegs.
size();
7281 unsigned DstIdx = 0;
7283 B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
7284 DstRegs[DstIdx] = FactorSum;
7289 for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
7291 for (
unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
7292 i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
7294 B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
7300 unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
7301 unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
7302 for (
unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
7303 unsigned i = RevI - 1;
7305 B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
7315 if (DstIdx != DstParts - 1) {
7316 MachineInstrBuilder Uaddo =
7317 B.buildUAddo(NarrowTy,
LLT::integer(1), Factors[0], Factors[1]);
7318 FactorSum = Uaddo.
getReg(0);
7319 CarrySum =
B.buildZExt(NarrowTy, Uaddo.
getReg(1)).getReg(0);
7320 for (
unsigned i = 2; i < Factors.
size(); ++i) {
7321 MachineInstrBuilder Uaddo =
7322 B.buildUAddo(NarrowTy,
LLT::integer(1), FactorSum, Factors[i]);
7323 FactorSum = Uaddo.
getReg(0);
7324 MachineInstrBuilder Carry =
B.buildZExt(NarrowTy, Uaddo.
getReg(1));
7325 CarrySum =
B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
7329 FactorSum =
B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
7330 for (
unsigned i = 2; i < Factors.
size(); ++i)
7331 FactorSum =
B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
7334 CarrySumPrevDstIdx = CarrySum;
7335 DstRegs[DstIdx] = FactorSum;
7347 LLT DstType = MRI.getType(DstReg);
7349 if (DstType.isVector())
7352 unsigned Opcode =
MI.getOpcode();
7353 unsigned OpO, OpE, OpF;
7355 case TargetOpcode::G_SADDO:
7356 case TargetOpcode::G_SADDE:
7357 case TargetOpcode::G_UADDO:
7358 case TargetOpcode::G_UADDE:
7359 case TargetOpcode::G_ADD:
7360 OpO = TargetOpcode::G_UADDO;
7361 OpE = TargetOpcode::G_UADDE;
7362 OpF = TargetOpcode::G_UADDE;
7363 if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
7364 OpF = TargetOpcode::G_SADDE;
7366 case TargetOpcode::G_SSUBO:
7367 case TargetOpcode::G_SSUBE:
7368 case TargetOpcode::G_USUBO:
7369 case TargetOpcode::G_USUBE:
7370 case TargetOpcode::G_SUB:
7371 OpO = TargetOpcode::G_USUBO;
7372 OpE = TargetOpcode::G_USUBE;
7373 OpF = TargetOpcode::G_USUBE;
7374 if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
7375 OpF = TargetOpcode::G_SSUBE;
7382 unsigned NumDefs =
MI.getNumExplicitDefs();
7383 Register Src1 =
MI.getOperand(NumDefs).getReg();
7384 Register Src2 =
MI.getOperand(NumDefs + 1).getReg();
7387 CarryDst =
MI.getOperand(1).getReg();
7388 if (
MI.getNumOperands() == NumDefs + 3)
7389 CarryIn =
MI.getOperand(NumDefs + 2).getReg();
7391 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7392 LLT LeftoverTy, DummyTy;
7394 extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
7399 int NarrowParts = Src1Regs.
size();
7400 Src1Regs.
append(Src1Left);
7401 Src2Regs.
append(Src2Left);
7404 for (
int i = 0, e = Src1Regs.
size(); i != e; ++i) {
7406 MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
7409 if (i == e - 1 && CarryDst)
7410 CarryOut = CarryDst;
7412 CarryOut = MRI.createGenericVirtualRegister(
LLT::integer(1));
7415 MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
7416 {Src1Regs[i], Src2Regs[i]});
7417 }
else if (i == e - 1) {
7418 MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
7419 {Src1Regs[i], Src2Regs[i], CarryIn});
7421 MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
7422 {Src1Regs[i], Src2Regs[i], CarryIn});
7428 insertParts(
MI.getOperand(0).getReg(), RegTy, NarrowTy,
7429 ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
7430 ArrayRef(DstRegs).drop_front(NarrowParts));
7432 MI.eraseFromParent();
7438 auto [DstReg, Src1, Src2] =
MI.getFirst3Regs();
7440 LLT Ty = MRI.getType(DstReg);
7444 unsigned Size = Ty.getSizeInBits();
7446 if (
Size % NarrowSize != 0)
7449 unsigned NumParts =
Size / NarrowSize;
7450 bool IsMulHigh =
MI.getOpcode() == TargetOpcode::G_UMULH;
7451 unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);
7457 multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);
7461 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7462 MI.eraseFromParent();
7472 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI;
7475 LLT SrcTy = MRI.getType(Src);
7486 IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
7499 int64_t SizeOp1 = MRI.getType(
MI.getOperand(1).getReg()).getSizeInBits();
7502 if (SizeOp1 % NarrowSize != 0)
7504 int NumParts = SizeOp1 / NarrowSize;
7507 extractParts(
MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
7511 uint64_t OpStart =
MI.getOperand(2).getImm();
7512 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7513 for (
int i = 0; i < NumParts; ++i) {
7514 unsigned SrcStart = i * NarrowSize;
7516 if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
7519 }
else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7527 int64_t ExtractOffset;
7529 if (OpStart < SrcStart) {
7531 SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
7533 ExtractOffset = OpStart - SrcStart;
7534 SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
7538 if (ExtractOffset != 0 || SegSize != NarrowSize) {
7540 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7541 MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
7548 if (MRI.getType(DstReg).isVector())
7549 MIRBuilder.buildBuildVector(DstReg, DstRegs);
7550 else if (DstRegs.
size() > 1)
7551 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7554 MI.eraseFromParent();
7566 LLT RegTy = MRI.getType(
MI.getOperand(0).getReg());
7568 extractParts(
MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
7571 SrcRegs.
append(LeftoverRegs);
7575 uint64_t OpStart =
MI.getOperand(3).getImm();
7576 uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
7577 for (
int I = 0, E = SrcRegs.
size();
I != E; ++
I) {
7578 unsigned DstStart =
I * NarrowSize;
7580 if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
7588 if (MRI.getType(SrcRegs[
I]) == LeftoverTy) {
7590 SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
7594 if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
7602 int64_t ExtractOffset, InsertOffset;
7604 if (OpStart < DstStart) {
7606 ExtractOffset = DstStart - OpStart;
7607 SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
7609 InsertOffset = OpStart - DstStart;
7612 std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
7616 if (ExtractOffset != 0 || SegSize != OpSize) {
7618 SegReg = MRI.createGenericVirtualRegister(
LLT::scalar(SegSize));
7619 MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
7622 Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
7623 MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
7631 MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
7634 MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
7636 MI.eraseFromParent();
7644 LLT DstTy = MRI.getType(DstReg);
7646 assert(
MI.getNumOperands() == 3 && TypeIdx == 0);
7652 if (!
extractParts(
MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
7653 Src0Regs, Src0LeftoverRegs,
MIRBuilder, MRI))
7657 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
7658 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7661 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7662 auto Inst =
MIRBuilder.buildInstr(
MI.getOpcode(), {NarrowTy},
7663 {Src0Regs[I], Src1Regs[I]});
7667 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7670 {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
7671 DstLeftoverRegs.
push_back(Inst.getReg(0));
7674 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7675 LeftoverTy, DstLeftoverRegs);
7677 MI.eraseFromParent();
7687 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
7689 LLT DstTy = MRI.getType(DstReg);
7694 LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
7695 LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts,
MI.getOpcode());
7696 buildWidenedRemergeToDst(DstReg, LCMTy, Parts);
7698 MI.eraseFromParent();
7708 Register CondReg =
MI.getOperand(1).getReg();
7709 LLT CondTy = MRI.getType(CondReg);
7710 if (CondTy.isVector())
7714 LLT DstTy = MRI.getType(DstReg);
7720 if (!
extractParts(
MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
7721 Src1Regs, Src1LeftoverRegs,
MIRBuilder, MRI))
7725 if (!
extractParts(
MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
7726 Src2Regs, Src2LeftoverRegs,
MIRBuilder, MRI))
7729 for (
unsigned I = 0, E = Src1Regs.
size();
I != E; ++
I) {
7731 CondReg, Src1Regs[
I], Src2Regs[
I]);
7735 for (
unsigned I = 0, E = Src1LeftoverRegs.
size();
I != E; ++
I) {
7737 LeftoverTy, CondReg, Src1LeftoverRegs[
I], Src2LeftoverRegs[
I]);
7741 insertParts(DstReg, DstTy, NarrowTy, DstRegs,
7742 LeftoverTy, DstLeftoverRegs);
7744 MI.eraseFromParent();
7754 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7757 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7758 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;
7761 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7763 auto C_0 =
B.buildConstant(NarrowTy, 0);
7765 UnmergeSrc.getReg(1), C_0);
7766 auto LoCTLZ = IsUndef ?
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
7767 :
B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
7768 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7769 auto HiIsZeroCTLZ =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
7770 auto HiCTLZ =
B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
7771 B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);
7773 MI.eraseFromParent();
7786 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7789 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7790 const bool IsUndef =
MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;
7793 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7795 auto C_0 =
B.buildConstant(NarrowTy, 0);
7797 UnmergeSrc.getReg(0), C_0);
7798 auto HiCTTZ = IsUndef ?
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
7799 :
B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
7800 auto C_NarrowSize =
B.buildConstant(DstTy, NarrowSize);
7801 auto LoIsZeroCTTZ =
B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
7802 auto LoCTTZ =
B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
7803 B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);
7805 MI.eraseFromParent();
7818 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7821 if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
7826 auto UnmergeSrc =
B.buildUnmerge(NarrowTy, SrcReg);
7830 auto ShAmt =
B.buildConstant(NarrowTy, NarrowSize - 1);
7831 auto Sign =
B.buildAShr(NarrowTy,
Hi, ShAmt);
7839 auto LoInv =
B.buildXor(DstTy,
Lo, Sign);
7840 auto LoCTLZ =
B.buildCTLZ(DstTy, LoInv);
7843 auto C_NarrowSizeM1 =
B.buildConstant(DstTy, NarrowSize - 1);
7844 auto HiIsSignCTLS =
B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);
7846 auto HiCTLS =
B.buildCTLS(DstTy,
Hi);
7848 B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);
7850 MI.eraseFromParent();
7860 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7863 if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
7864 auto UnmergeSrc =
MIRBuilder.buildUnmerge(NarrowTy,
MI.getOperand(1));
7866 auto LoCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
7867 auto HiCTPOP =
MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
7868 MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);
7870 MI.eraseFromParent();
7885 LLT ExpTy = MRI.getType(ExpReg);
7890 auto MinExp =
B.buildConstant(ExpTy,
minIntN(ClampSize));
7891 auto ClampMin =
B.buildSMax(ExpTy, ExpReg, MinExp);
7892 auto MaxExp =
B.buildConstant(ExpTy,
maxIntN(ClampSize));
7893 auto Clamp =
B.buildSMin(ExpTy, ClampMin, MaxExp);
7895 auto Trunc =
B.buildTrunc(NarrowTy, Clamp);
7897 MI.getOperand(2).setReg(Trunc.getReg(0));
7904 unsigned Opc =
MI.getOpcode();
7907 auto QAction = LI.getAction(Q).Action;
7913 case TargetOpcode::G_CTLZ_ZERO_POISON: {
7916 MI.setDesc(
TII.get(TargetOpcode::G_CTLZ));
7920 case TargetOpcode::G_CTLZ: {
7921 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7922 unsigned Len = SrcTy.getScalarSizeInBits();
7924 if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
7926 auto CtlzZU =
MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
7927 auto ZeroSrc =
MIRBuilder.buildConstant(SrcTy, 0);
7930 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7931 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
7932 MI.eraseFromParent();
7948 for (
unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
7949 auto MIBShiftAmt =
MIRBuilder.buildConstant(SrcTy, 1ULL << i);
7952 Op = MIBOp.getReg(0);
7957 MI.eraseFromParent();
7960 case TargetOpcode::G_CTTZ_ZERO_POISON: {
7963 MI.setDesc(
TII.get(TargetOpcode::G_CTTZ));
7967 case TargetOpcode::G_CTTZ: {
7968 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
7970 unsigned Len = SrcTy.getScalarSizeInBits();
7971 if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
7974 auto CttzZU =
MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
7975 auto Zero =
MIRBuilder.buildConstant(SrcTy, 0);
7978 auto LenConst =
MIRBuilder.buildConstant(DstTy, Len);
7979 MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
7980 MI.eraseFromParent();
7987 auto MIBCstNeg1 =
MIRBuilder.buildConstant(SrcTy, -1);
7988 auto MIBNot =
MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
7990 SrcTy, MIBNot,
MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
7991 if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
7992 isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
7993 auto MIBCstLen =
MIRBuilder.buildConstant(SrcTy, Len);
7996 MI.eraseFromParent();
8000 MI.setDesc(
TII.get(TargetOpcode::G_CTPOP));
8001 MI.getOperand(1).setReg(MIBTmp.getReg(0));
8005 case TargetOpcode::G_CTPOP: {
8007 LLT Ty = MRI.getType(SrcReg);
8008 unsigned Size = Ty.getScalarSizeInBits();
8020 auto C_1 =
B.buildConstant(Ty, 1);
8021 auto B2Set1LoTo1Hi =
B.buildLShr(Ty, SrcReg, C_1);
8023 auto C_B2Mask1HiTo0 =
B.buildConstant(Ty, B2Mask1HiTo0);
8024 auto B2Count1Hi =
B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
8025 auto B2Count =
B.buildSub(Ty, SrcReg, B2Count1Hi);
8029 auto C_2 =
B.buildConstant(Ty, 2);
8030 auto B4Set2LoTo2Hi =
B.buildLShr(Ty, B2Count, C_2);
8032 auto C_B4Mask2HiTo0 =
B.buildConstant(Ty, B4Mask2HiTo0);
8033 auto B4HiB2Count =
B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
8034 auto B4LoB2Count =
B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
8035 auto B4Count =
B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);
8042 auto C_4 =
B.buildConstant(Ty, 4);
8043 auto B8HiB4Count =
B.buildLShr(Ty, B4Count, C_4);
8044 auto B8CountDirty4Hi =
B.buildAdd(Ty, B8HiB4Count, B4Count);
8046 auto C_B8Mask4HiTo0 =
B.buildConstant(Ty, B8Mask4HiTo0);
8047 auto B8Count =
B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);
8049 assert(
Size <= 128 &&
"Scalar size is too large for CTPOP lower algorithm");
8052 if (
Size == 16 && !Ty.isVector()) {
8054 auto C_8 =
B.buildConstant(Ty, 8);
8055 auto HighSum =
B.buildLShr(Ty, B8Count, C_8);
8056 auto Res =
B.buildAdd(Ty, B8Count, HighSum);
8057 B.buildAnd(
MI.getOperand(0).getReg(), Res,
B.buildConstant(Ty, 0xFF));
8058 MI.eraseFromParent();
8067 auto C_SizeM8 =
B.buildConstant(Ty,
Size - 8);
8069 auto IsMulSupported = [
this](
const LLT Ty) {
8070 auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
8073 if (IsMulSupported(Ty)) {
8074 auto ResTmp =
B.buildMul(Ty, B8Count, MulMask);
8075 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8077 auto ResTmp = B8Count;
8078 for (
unsigned Shift = 8; Shift <
Size; Shift *= 2) {
8079 auto ShiftC =
B.buildConstant(Ty, Shift);
8080 auto Shl =
B.buildShl(Ty, ResTmp, ShiftC);
8081 ResTmp =
B.buildAdd(Ty, ResTmp, Shl);
8083 B.buildLShr(
MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
8085 MI.eraseFromParent();
8088 case TargetOpcode::G_CTLS: {
8089 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8093 MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
8094 auto OneC =
MIRBuilder.buildConstant(DstTy, 1);
8096 auto Shr =
MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);
8102 MI.eraseFromParent();
8123 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8124 LLT Ty = MRI.getType(Dst);
8125 LLT ShTy = MRI.getType(Z);
8132 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8133 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8138 auto Zero =
MIRBuilder.buildConstant(ShTy, 0);
8139 Z =
MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
8143 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8156 MI.eraseFromParent();
8162 auto [Dst,
X,
Y, Z] =
MI.getFirst4Regs();
8163 LLT Ty = MRI.getType(Dst);
8164 LLT ShTy = MRI.getType(Z);
8167 const bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8177 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8178 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8179 InvShAmt =
MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
8180 ShX =
MIRBuilder.buildShl(Ty,
X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
8181 ShY =
MIRBuilder.buildLShr(Ty,
Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
8185 auto Mask =
MIRBuilder.buildConstant(ShTy, BW - 1);
8188 ShAmt =
MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
8191 InvShAmt =
MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
8193 auto BitWidthC =
MIRBuilder.buildConstant(ShTy, BW);
8194 ShAmt =
MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
8195 InvShAmt =
MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
8198 auto One =
MIRBuilder.buildConstant(ShTy, 1);
8200 ShX =
MIRBuilder.buildShl(Ty,
X, ShAmt).getReg(0);
8202 ShY =
MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
8205 ShX =
MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
8206 ShY =
MIRBuilder.buildLShr(Ty,
Y, ShAmt).getReg(0);
8211 MI.eraseFromParent();
8222 LLT Ty = MRI.getType(Dst);
8223 LLT ShTy = MRI.getType(
MI.getOperand(3).getReg());
8225 bool IsFSHL =
MI.getOpcode() == TargetOpcode::G_FSHL;
8226 unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;
8229 if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action ==
Lower)
8230 return lowerFunnelShiftAsShifts(
MI);
8234 if (Result == UnableToLegalize)
8235 return lowerFunnelShiftAsShifts(
MI);
8240 auto [Dst, Src] =
MI.getFirst2Regs();
8241 LLT DstTy = MRI.getType(Dst);
8242 LLT SrcTy = MRI.getType(Src);
8246 uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();
8254 if (SrcTyScalarSize * 2 < DstTyScalarSize) {
8258 auto NewExt =
MIRBuilder.buildInstr(
MI.getOpcode(), {MidTy}, {Src});
8262 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, NewExt);
8267 auto ZExtRes1 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8268 {UnmergeSrc.getReg(0)});
8269 auto ZExtRes2 =
MIRBuilder.buildInstr(
MI.getOpcode(), {ZExtResTy},
8270 {UnmergeSrc.getReg(1)});
8273 MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});
8275 MI.eraseFromParent();
8292 assert(
MI.getOpcode() == TargetOpcode::G_TRUNC);
8296 LLT DstTy = MRI.getType(DstReg);
8297 LLT SrcTy = MRI.getType(SrcReg);
8305 SrcTy.getElementCount().divideCoefficientBy(2));
8318 Src =
MIRBuilder.buildTrunc(InterTy, Src).getReg(0);
8330 MI.eraseFromParent();
8339 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8340 auto Zero =
MIRBuilder.buildConstant(AmtTy, 0);
8341 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8342 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8343 auto Neg =
MIRBuilder.buildSub(AmtTy, Zero, Amt);
8344 MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
8345 MI.eraseFromParent();
8350 auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] =
MI.getFirst3RegLLTs();
8352 unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
8353 bool IsLeft =
MI.getOpcode() == TargetOpcode::G_ROTL;
8358 unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
8359 if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
8361 return lowerRotateWithReverseRotate(
MI);
8364 unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8365 unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
8366 bool IsFShLegal =
false;
8367 if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
8368 LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
8372 MI.eraseFromParent();
8377 return buildFunnelShift(FShOpc, Dst, Src, Amt);
8380 return buildFunnelShift(RevFsh, Dst, Src, Amt);
8385 unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
8386 unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
8387 auto BitWidthMinusOneC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits - 1);
8393 auto NegAmt = MIRBuilder.
buildSub(AmtTy, Zero, Amt);
8394 auto ShAmt = MIRBuilder.
buildAnd(AmtTy, Amt, BitWidthMinusOneC);
8396 auto RevAmt = MIRBuilder.
buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
8402 auto BitWidthC = MIRBuilder.
buildConstant(AmtTy, EltSizeInBits);
8403 auto ShAmt = MIRBuilder.
buildURem(AmtTy, Amt, BitWidthC);
8405 auto RevAmt = MIRBuilder.
buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
8407 auto Inner = MIRBuilder.
buildInstr(RevShiftOpc, {DstTy}, {Src, One});
8412 MI.eraseFromParent();
8420 auto [Dst, Src] =
MI.getFirst2Regs();
8425 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8453 auto Mask1 =
MIRBuilder.buildConstant(
S64, 0xffffffffffULL);
8466 auto Select0 =
MIRBuilder.buildSelect(
S32, TCmp, VTrunc1, Zero32);
8470 MI.eraseFromParent();
8478 auto [Dst, Src] =
MI.getFirst2Regs();
8483 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S32);
8496 auto RoundedHalved =
MIRBuilder.buildOr(
S64, Halved, LowerBit);
8498 auto LargeResult =
MIRBuilder.buildFAdd(
S32, HalvedFP, HalvedFP);
8503 MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);
8505 MI.eraseFromParent();
8513 auto [Dst, Src] =
MI.getFirst2Regs();
8517 assert(MRI.getType(Src) ==
S64 && MRI.getType(Dst) ==
S64);
8528 auto TwoP52 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4330000000000000));
8529 auto TwoP84 =
MIRBuilder.buildConstant(
S64, UINT64_C(0x4530000000000000));
8531 auto TwoP52P84FP =
MIRBuilder.buildFConstant(
S64, TwoP52P84);
8538 auto HighBitsFP =
MIRBuilder.buildOr(
S64, TwoP84, HighBits);
8539 auto Scratch =
MIRBuilder.buildFSub(
S64, HighBitsFP, TwoP52P84FP);
8540 MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);
8542 MI.eraseFromParent();
8553 SrcTy.changeElementType(
LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
8554 auto M1 =
MI.getOpcode() == TargetOpcode::G_UITOFP
8560 MI.eraseFromParent();
8565 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8568 auto True =
MIRBuilder.buildFConstant(DstTy, 1.0);
8569 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8570 MIRBuilder.buildSelect(Dst, Src, True, False);
8571 MI.eraseFromParent();
8575 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8595 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8602 auto True =
MIRBuilder.buildFConstant(DstTy, -1.0);
8603 auto False =
MIRBuilder.buildFConstant(DstTy, 0.0);
8604 MIRBuilder.buildSelect(Dst, Src, True, False);
8605 MI.eraseFromParent();
8609 if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
8615 if (DstTy.getScalarSizeInBits() == 32) {
8622 auto SignBit =
MIRBuilder.buildConstant(I64, 63);
8623 auto S =
MIRBuilder.buildAShr(I64, L, SignBit);
8625 auto LPlusS =
MIRBuilder.buildAdd(I64, L, S);
8632 MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
8633 MI.eraseFromParent();
8641 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8645 if (SrcTy !=
S64 && SrcTy !=
S32)
8647 if (DstTy !=
S32 && DstTy !=
S64)
8674 MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);
8676 MI.eraseFromParent();
8681 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8686 if (SrcTy.getScalarType() !=
S32 || DstTy.getScalarType() !=
S64)
8693 unsigned SrcEltBits = SrcTy.getScalarSizeInBits();
8695 auto ExponentMask =
MIRBuilder.buildConstant(SrcTy, 0x7F800000);
8696 auto ExponentLoBit =
MIRBuilder.buildConstant(SrcTy, 23);
8698 auto AndExpMask =
MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
8699 auto ExponentBits =
MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);
8701 auto SignMask =
MIRBuilder.buildConstant(SrcTy,
8703 auto AndSignMask =
MIRBuilder.buildAnd(SrcTy, Src, SignMask);
8704 auto SignLowBit =
MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
8705 auto Sign =
MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
8708 auto MantissaMask =
MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
8709 auto AndMantissaMask =
MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
8710 auto K =
MIRBuilder.buildConstant(SrcTy, 0x00800000);
8712 auto R =
MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
8715 auto Bias =
MIRBuilder.buildConstant(SrcTy, 127);
8720 auto Shl =
MIRBuilder.buildShl(DstTy, R, SubExponent);
8721 auto Srl =
MIRBuilder.buildLShr(DstTy, R, ExponentSub);
8727 R =
MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);
8729 auto XorSign =
MIRBuilder.buildXor(DstTy, R, Sign);
8730 auto Ret =
MIRBuilder.buildSub(DstTy, XorSign, Sign);
8732 auto ZeroSrcTy =
MIRBuilder.buildConstant(SrcTy, 0);
8737 auto ZeroDstTy =
MIRBuilder.buildConstant(DstTy, 0);
8738 MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);
8740 MI.eraseFromParent();
8746 auto [Dst, DstTy, Src, SrcTy] =
MI.getFirst2RegLLTs();
8748 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
8749 unsigned SatWidth = DstTy.getScalarSizeInBits();
8753 APInt MinInt, MaxInt;
8776 if (AreExactFloatBounds) {
8778 auto MaxC =
MIRBuilder.buildFConstant(SrcTy, MinFloat);
8781 auto Max =
MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
8783 auto MinC =
MIRBuilder.buildFConstant(SrcTy, MaxFloat);
8792 MI.eraseFromParent();
8797 auto FpToInt =
MIRBuilder.buildFPTOSI(DstTy, Min);
8802 MI.eraseFromParent();
8809 auto FpToInt = IsSigned ?
MIRBuilder.buildFPTOSI(DstTy, Src)
8817 DstTy, ULT,
MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
8827 MI.eraseFromParent();
8833 DstTy, OGT,
MIRBuilder.buildConstant(DstTy, MaxInt), Max);
8837 MI.eraseFromParent();
8844 assert((
MI.getOpcode() == TargetOpcode::G_FPEXT ||
8845 MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
8846 "Only G_FPEXT and G_FPTRUNC are expected");
8848 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8853 if (
MI.getOpcode() == TargetOpcode::G_FPEXT) {
8855 StoreOpc = TargetOpcode::G_STORE;
8856 LoadOpc = TargetOpcode::G_FPEXTLOAD;
8859 StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
8860 LoadOpc = TargetOpcode::G_LOAD;
8869 StackTy, StackTyAlign);
8870 MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);
8873 StackTy, StackTyAlign);
8874 MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);
8876 MI.eraseFromParent();
8884 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
8885 assert(SrcTy.getScalarType().isBFloat16() &&
8886 "expected a bf16 source for bf16 fpext lowering");
8897 if (DstTy.getScalarType().isFloat32())
8902 MI.eraseFromParent();
8907 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
8908 if (SrcTy.getScalarType().isBFloat16() &&
8909 (DstTy.getScalarType().isFloat32() || DstTy.getScalarType().isFloat64()))
8921 auto [Dst, Src] =
MI.getFirst2Regs();
8925 if (MRI.getType(Src).isVector())
8929 unsigned Flags =
MI.getFlags();
8932 MI.eraseFromParent();
8936 const unsigned ExpMask = 0x7ff;
8937 const unsigned ExpBiasf64 = 1023;
8938 const unsigned ExpBiasf16 = 15;
8940 auto Unmerge =
MIRBuilder.buildUnmerge(I32, Src);
8950 I32, E,
MIRBuilder.buildConstant(I32, -ExpBiasf64 + ExpBiasf16));
8957 MaskedSig =
MIRBuilder.buildOr(I32, MaskedSig, U);
8959 auto Zero =
MIRBuilder.buildConstant(I32, 0);
8961 auto Lo40Set =
MIRBuilder.buildZExt(I32, SigCmpNE0);
8965 auto Bits0x200 =
MIRBuilder.buildConstant(I32, 0x0200);
8967 auto SelectCC =
MIRBuilder.buildSelect(I32, CmpM_NE0, Bits0x200, Zero);
8969 auto Bits0x7c00 =
MIRBuilder.buildConstant(I32, 0x7c00);
8970 auto I =
MIRBuilder.buildOr(I32, SelectCC, Bits0x7c00);
8978 auto OneSubExp =
MIRBuilder.buildSub(I32, One, E);
8979 auto B =
MIRBuilder.buildSMax(I32, OneSubExp, Zero);
8990 auto D1 =
MIRBuilder.buildZExt(I32, D0_NE_SigSetHigh);
9001 auto V0 =
MIRBuilder.buildZExt(I32, VLow3Eq3);
9017 V =
MIRBuilder.buildSelect(I32, CmpEGt1039,
I, V);
9027 MI.eraseFromParent();
9034 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9042 auto SrcI =
MIRBuilder.buildBitcast(I32Ty, SrcReg);
9068 auto Trunc =
MIRBuilder.buildTrunc(I16Ty, Srl);
9070 MI.eraseFromParent();
9079 LLT OperandTy = MRI.getType(
Op);
9089 auto NarrowAsWide =
MIRBuilder.buildFPExt(OperandTy, Narrow);
9091 auto NarrowBits =
MIRBuilder.buildBitcast(ResultIntTy, Narrow);
9092 auto One =
MIRBuilder.buildConstant(ResultIntTy, 1);
9093 auto NegativeOne =
MIRBuilder.buildConstant(ResultIntTy, -1);
9094 auto Zero =
MIRBuilder.buildConstant(ResultIntTy, 0);
9095 auto And =
MIRBuilder.buildAnd(ResultIntTy, NarrowBits, One);
9103 KeepNarrow =
MIRBuilder.buildOr(OperandCCTy, KeepNarrow, AlreadyOdd);
9106 auto AbsNarrowAsWide =
MIRBuilder.buildFAbs(OperandTy, NarrowAsWide);
9108 AbsWide, AbsNarrowAsWide);
9112 MIRBuilder.buildSelect(ResultIntTy, NarrowIsRd, One, NegativeOne);
9113 auto Adjusted =
MIRBuilder.buildAdd(ResultIntTy, NarrowBits, Adjust);
9115 MIRBuilder.buildSelect(ResultIntTy, KeepNarrow, NarrowBits, Adjusted);
9116 return MIRBuilder.buildBitcast(ResultTy, Res).getReg(0);
9122 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9128 MIRBuilder.buildFPTrunc(DstReg, OddF32,
MI.getFlags());
9129 MI.eraseFromParent();
9135 auto [DstTy, SrcTy] =
MI.getFirst2LLTs();
9136 if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
9139 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
9142 if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat64())
9149 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9150 LLT Ty = MRI.getType(Dst);
9152 auto CvtSrc1 =
MIRBuilder.buildSITOFP(Ty, Src1);
9153 MIRBuilder.buildFPow(Dst, Src0, CvtSrc1,
MI.getFlags());
9154 MI.eraseFromParent();
9159 auto [DstFrac, DstInt, Src] =
MI.getFirst3Regs();
9160 LLT Ty = MRI.getType(Src);
9161 auto Flags =
MI.getFlags();
9169 FracToUse = FracPart.getReg(0);
9171 auto Abs =
MIRBuilder.buildFAbs(Ty, Src, Flags);
9175 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9177 FracToUse =
Select.getReg(0);
9180 MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
9183 MI.eraseFromParent();
9189 case TargetOpcode::G_SMIN:
9191 case TargetOpcode::G_SMAX:
9193 case TargetOpcode::G_UMIN:
9195 case TargetOpcode::G_UMAX:
9203 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9208 auto Cmp =
MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
9209 MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
9211 MI.eraseFromParent();
9220 LLT DstTy = MRI.getType(Dst);
9221 LLT SrcTy = MRI.getType(Cmp->getReg(1));
9231 auto Zero =
MIRBuilder.buildConstant(DstTy, 0);
9232 auto IsGT =
MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
9234 auto IsLT =
MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
9237 auto &Ctx =
MIRBuilder.getMF().getFunction().getContext();
9238 auto BC = TLI.getBooleanContents(DstTy.
isVector(),
false);
9239 if (TLI.preferSelectsOverBooleanArithmetic(
9242 auto One =
MIRBuilder.buildConstant(DstTy, 1);
9243 auto SelectZeroOrOne =
MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);
9245 auto MinusOne =
MIRBuilder.buildConstant(DstTy, -1);
9246 MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
9252 unsigned BoolExtOp =
9254 IsGT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
9255 IsLT =
MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
9259 MI.eraseFromParent();
9265 auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] =
MI.getFirst3RegLLTs();
9266 const int Src0Size = Src0Ty.getScalarSizeInBits();
9267 const int Src1Size = Src1Ty.getScalarSizeInBits();
9277 if (!(Src0Ty.getScalarType().isAnyScalar() ||
9278 Src0Ty.getScalarType().isInteger()))
9279 Src0Int =
MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
9281 if (!(Src1Ty.getScalarType().isAnyScalar() ||
9282 Src1Ty.getScalarType().isInteger()))
9283 Src1Int =
MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
9288 auto NotSignBitMask =
MIRBuilder.buildConstant(
9292 MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
9294 if (Src0Ty == Src1Ty) {
9295 And1 =
MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
9296 }
else if (Src0Size > Src1Size) {
9297 auto ShiftAmt =
MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
9298 auto Zext =
MIRBuilder.buildZExt(Src0IntTy, Src1Int);
9299 auto Shift =
MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
9300 And1 =
MIRBuilder.buildAnd(Src0IntTy, Shift, SignBitMask).getReg(0);
9302 auto ShiftAmt =
MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
9303 auto Shift =
MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
9304 auto Trunc =
MIRBuilder.buildTrunc(Src0IntTy, Shift);
9305 And1 =
MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
9311 unsigned Flags =
MI.getFlags();
9316 if (DstTy == DstIntTy)
9317 MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
9323 MI.eraseFromParent();
9334 switch (
MI.getOpcode()) {
9335 case TargetOpcode::G_FMINNUM:
9336 NewOp = TargetOpcode::G_FMINNUM_IEEE;
9338 case TargetOpcode::G_FMINIMUMNUM:
9339 NewOp = TargetOpcode::G_FMINNUM;
9341 case TargetOpcode::G_FMAXNUM:
9342 NewOp = TargetOpcode::G_FMAXNUM_IEEE;
9344 case TargetOpcode::G_FMAXIMUMNUM:
9345 NewOp = TargetOpcode::G_FMAXNUM;
9351 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9352 LLT Ty = MRI.getType(Dst);
9361 if (!VT->isKnownNeverSNaN(Src0))
9362 Src0 =
MIRBuilder.buildFCanonicalize(Ty, Src0,
MI.getFlags()).getReg(0);
9364 if (!VT->isKnownNeverSNaN(Src1))
9365 Src1 =
MIRBuilder.buildFCanonicalize(Ty, Src1,
MI.getFlags()).getReg(0);
9370 MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1},
MI.getFlags());
9371 MI.eraseFromParent();
9377 unsigned Opc =
MI.getOpcode();
9378 auto [Dst, Src0, Src1] =
MI.getFirst3Regs();
9379 LLT Ty = MRI.getType(Dst);
9382 bool IsMax = (
Opc == TargetOpcode::G_FMAXIMUM);
9384 IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
9385 unsigned OpcNonIeee =
9386 IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
9387 bool MinMaxMustRespectOrderedZero =
false;
9391 if (LI.isLegalOrCustom({OpcIeee, Ty})) {
9393 MinMaxMustRespectOrderedZero =
true;
9394 }
else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
9399 Res =
MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
9404 (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
9407 LLT ElementTy = Ty.
isScalar() ? Ty : Ty.getElementType();
9411 NaN =
MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);
9413 Res =
MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
9423 const unsigned Flags =
MI.getFlags();
9429 auto LHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
9431 MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);
9433 auto RHSTestZero =
MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
9435 MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);
9437 Res =
MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
9442 MI.eraseFromParent();
9449 LLT Ty = MRI.getType(DstReg);
9450 unsigned Flags =
MI.getFlags();
9455 MI.eraseFromParent();
9461 auto [DstReg,
X] =
MI.getFirst2Regs();
9462 const unsigned Flags =
MI.getFlags();
9463 const LLT Ty = MRI.getType(DstReg);
9475 auto AbsDiff =
MIRBuilder.buildFAbs(Ty, Diff, Flags);
9477 auto Half =
MIRBuilder.buildFConstant(Ty, 0.5);
9482 auto One =
MIRBuilder.buildFConstant(Ty, 1.0);
9483 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9484 auto BoolFP =
MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
9485 auto SignedOffset =
MIRBuilder.buildFCopysign(Ty, BoolFP,
X);
9487 MIRBuilder.buildFAdd(DstReg,
T, SignedOffset, Flags);
9489 MI.eraseFromParent();
9494 auto [DstReg, SrcReg] =
MI.getFirst2Regs();
9495 unsigned Flags =
MI.getFlags();
9496 LLT Ty = MRI.getType(DstReg);
9503 auto Trunc =
MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
9504 auto Zero =
MIRBuilder.buildFConstant(Ty, 0.0);
9507 SrcReg, Zero, Flags);
9509 SrcReg, Trunc, Flags);
9513 MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
9514 MI.eraseFromParent();
9520 const unsigned NumOps =
MI.getNumOperands();
9521 auto [DstReg, DstTy, Src0Reg, Src0Ty] =
MI.getFirst2RegLLTs();
9522 unsigned PartSize = Src0Ty.getSizeInBits();
9527 for (
unsigned I = 2;
I !=
NumOps; ++
I) {
9528 const unsigned Offset = (
I - 1) * PartSize;
9531 auto ZextInput =
MIRBuilder.buildZExt(WideTy, SrcReg);
9534 MRI.createGenericVirtualRegister(WideTy);
9537 auto Shl =
MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
9538 MIRBuilder.buildOr(NextResult, ResultReg, Shl);
9539 ResultReg = NextResult;
9542 if (DstTy.isPointer()) {
9543 if (
MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
9544 DstTy.getAddressSpace())) {
9550 }
else if (WideTy != DstTy) {
9554 MI.eraseFromParent();
9560 const unsigned NumDst =
MI.getNumOperands() - 1;
9561 Register SrcReg =
MI.getOperand(NumDst).getReg();
9562 Register Dst0Reg =
MI.getOperand(0).getReg();
9563 LLT DstTy = MRI.getType(Dst0Reg);
9572 LLT IntTy = MRI.getType(SrcReg);
9577 unsigned Offset = DstSize;
9578 for (
unsigned I = 1;
I != NumDst; ++
I,
Offset += DstSize) {
9580 auto Shift =
MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
9584 MI.eraseFromParent();
9603 if (
MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
9604 InsertVal =
MI.getOperand(2).getReg();
9606 Register Idx =
MI.getOperand(
MI.getNumOperands() - 1).getReg();
9608 LLT VecTy = MRI.getType(SrcVec);
9618 SrcRegs[IdxVal] =
MI.getOperand(2).getReg();
9619 MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
9621 MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
9624 MI.eraseFromParent();
9629 LLVM_DEBUG(
dbgs() <<
"Can't handle non-byte element vectors yet\n");
9640 MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);
9647 int64_t
Offset = IdxVal * EltBytes;
9658 MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);
9661 MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
9663 MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
9666 MI.eraseFromParent();
9672 auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
9673 MI.getFirst3RegLLTs();
9683 for (
int Idx : Mask) {
9685 if (!
Undef.isValid())
9691 assert(!Src0Ty.isScalar() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9693 int NumElts = Src0Ty.getNumElements();
9694 Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
9695 int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
9696 auto [It, Inserted] = CachedExtract.
try_emplace(Idx);
9698 auto IdxK =
MIRBuilder.buildConstant(IdxTy, ExtractIdx);
9700 MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
9705 assert(DstTy.isVector() &&
"Unexpected scalar G_SHUFFLE_VECTOR");
9706 MIRBuilder.buildBuildVector(DstReg, BuildVec);
9707 MI.eraseFromParent();
9713 auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
9714 MI.getFirst4RegLLTs();
9716 if (VecTy.isScalableVector())
9732 auto OutPos =
MIRBuilder.buildConstant(IdxTy, 0);
9735 MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;
9738 MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);
9741 std::optional<APInt> PassthruSplatVal =
9744 if (PassthruSplatVal.has_value()) {
9746 MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
9747 }
else if (HasPassthru) {
9748 auto Popcount =
MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
9749 Popcount =
MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
9755 MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
9759 unsigned NumElmts = VecTy.getNumElements();
9760 for (
unsigned I = 0;
I < NumElmts; ++
I) {
9762 auto Val =
MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
9765 MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);
9768 auto MaskI =
MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
9773 OutPos =
MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);
9775 if (HasPassthru &&
I == NumElmts - 1) {
9778 auto AllLanesSelected =
MIRBuilder.buildICmp(
9780 OutPos =
MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
9781 {OutPos, EndOfVector});
9785 MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
9787 MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
9792 MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);
9794 MI.eraseFromParent();
9811 if (Alignment >
Align(1)) {
9823 const auto &MF = *
MI.getMF();
9829 Register AllocSize =
MI.getOperand(1).getReg();
9832 LLT PtrTy = MRI.getType(Dst);
9833 Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
9840 MI.eraseFromParent();
9846 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9851 MI.eraseFromParent();
9857 Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
9862 MI.eraseFromParent();
9868 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
9869 unsigned Offset =
MI.getOperand(2).getImm();
9872 if (SrcTy.isVector()) {
9873 unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
9874 unsigned DstSize = DstTy.getSizeInBits();
9876 if ((
Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
9877 (
Offset + DstSize <= SrcTy.getSizeInBits())) {
9879 auto Unmerge =
MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);
9883 for (
unsigned Idx =
Offset / SrcEltSize;
9884 Idx < (
Offset + DstSize) / SrcEltSize; ++Idx) {
9885 SubVectorElts.
push_back(Unmerge.getReg(Idx));
9887 if (SubVectorElts.
size() == 1)
9888 MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
9890 MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);
9892 MI.eraseFromParent();
9898 if ((SrcTy.isPointer() &&
9899 DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
9900 (DstTy.isPointer() &&
9901 DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
9902 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9906 if ((DstTy.isScalar() || DstTy.isPointer()) &&
9907 (SrcTy.isScalar() || SrcTy.isPointer() ||
9908 (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
9909 LLT SrcIntTy = SrcTy;
9910 if (!SrcTy.isScalar()) {
9912 SrcReg =
MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
9916 if (DstTy.isPointer())
9918 MRI.createGenericVirtualRegister(
LLT::integer(DstTy.getSizeInBits()));
9924 auto Shr =
MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
9928 if (DstTy.isPointer())
9931 MI.eraseFromParent();
9939 auto [Dst, Src, InsertSrc] =
MI.getFirst3Regs();
9942 LLT DstTy = MRI.getType(Src);
9943 LLT InsertTy = MRI.getType(InsertSrc);
9946 bool IsNonIntegralInsert =
9956 if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
9957 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
9964 if ((
Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
9966 auto UnmergeSrc =
MIRBuilder.buildUnmerge(EltTy, Src);
9970 for (; Idx <
Offset / EltSize; ++Idx) {
9971 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9976 auto UnmergeInsertSrc =
MIRBuilder.buildUnmerge(EltTy, InsertSrc);
9977 for (
unsigned i = 0; Idx < (
Offset + InsertSize) / EltSize;
9979 DstElts.
push_back(UnmergeInsertSrc.getReg(i));
9983 InsertSrc =
MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
9985 InsertSrc =
MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
9992 DstElts.
push_back(UnmergeSrc.getReg(Idx));
9995 MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
9996 MI.eraseFromParent();
10005 if (IsNonIntegralDst || IsNonIntegralInsert) {
10006 LLVM_DEBUG(
dbgs() <<
"Not casting non-integral address space integer\n");
10010 LLT IntDstTy = DstTy;
10014 Src =
MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
10019 InsertSrc =
MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
10025 ExtInsSrc =
MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
10031 auto Mask =
MIRBuilder.buildConstant(IntDstTy, MaskVal);
10032 auto MaskedSrc =
MIRBuilder.buildAnd(IntDstTy, Src, Mask);
10033 auto Or =
MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);
10036 MI.eraseFromParent();
10042 auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
10043 MI.getFirst4RegLLTs();
10044 const bool IsAdd =
MI.getOpcode() == TargetOpcode::G_SADDO;
10047 LLT BoolTy = Dst1Ty;
10049 Register NewDst0 = MRI.cloneVirtualRegister(Dst0);
10058 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10064 auto ResultLowerThanLHS =
10068 MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
10072 auto LHSLessThanRHS =
10074 auto ResultNegative =
10076 MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
10080 MI.eraseFromParent();
10086 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10087 const LLT Ty = MRI.getType(Res);
10090 auto Tmp =
MIRBuilder.buildAdd(Ty, LHS, RHS);
10091 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10092 auto Sum =
MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
10096 auto AX =
MIRBuilder.buildXor(Ty, Sum, LHS);
10097 auto BX =
MIRBuilder.buildXor(Ty, Sum, RHS);
10100 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10103 MI.eraseFromParent();
10108 auto [Res, OvOut, LHS, RHS, CarryIn] =
MI.getFirst5Regs();
10109 const LLT Ty = MRI.getType(Res);
10112 auto CarryZ =
MIRBuilder.buildZExt(Ty, CarryIn);
10113 auto RHSPlusCI =
MIRBuilder.buildAdd(Ty, RHS, CarryZ);
10114 auto Diff =
MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
10118 auto X1 =
MIRBuilder.buildXor(Ty, LHS, RHS);
10119 auto X2 =
MIRBuilder.buildXor(Ty, LHS, Diff);
10121 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10124 MI.eraseFromParent();
10130 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10131 LLT Ty = MRI.getType(Res);
10135 switch (
MI.getOpcode()) {
10138 case TargetOpcode::G_UADDSAT:
10141 BaseOp = TargetOpcode::G_ADD;
10143 case TargetOpcode::G_SADDSAT:
10146 BaseOp = TargetOpcode::G_ADD;
10148 case TargetOpcode::G_USUBSAT:
10151 BaseOp = TargetOpcode::G_SUB;
10153 case TargetOpcode::G_SSUBSAT:
10156 BaseOp = TargetOpcode::G_SUB;
10171 uint64_t NumBits = Ty.getScalarSizeInBits();
10178 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10182 auto NegOne =
MIRBuilder.buildConstant(Ty, -1);
10190 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
10195 auto Min =
MIRBuilder.buildUMin(Ty, Not, RHS);
10196 MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
10199 MI.eraseFromParent();
10205 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10206 LLT Ty = MRI.getType(Res);
10210 unsigned OverflowOp;
10211 switch (
MI.getOpcode()) {
10214 case TargetOpcode::G_UADDSAT:
10217 OverflowOp = TargetOpcode::G_UADDO;
10219 case TargetOpcode::G_SADDSAT:
10222 OverflowOp = TargetOpcode::G_SADDO;
10224 case TargetOpcode::G_USUBSAT:
10227 OverflowOp = TargetOpcode::G_USUBO;
10229 case TargetOpcode::G_SSUBSAT:
10232 OverflowOp = TargetOpcode::G_SSUBO;
10237 MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
10238 Register Tmp = OverflowRes.getReg(0);
10239 Register Ov = OverflowRes.getReg(1);
10248 uint64_t NumBits = Ty.getScalarSizeInBits();
10249 auto ShiftAmount =
MIRBuilder.buildConstant(Ty, NumBits - 1);
10250 auto Sign =
MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
10253 Clamp =
MIRBuilder.buildAdd(Ty, Sign, MinVal);
10261 Clamp =
MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
10263 MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);
10265 MI.eraseFromParent();
10271 assert((
MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
10272 MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
10273 "Expected shlsat opcode!");
10274 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SSHLSAT;
10275 auto [Res, LHS, RHS] =
MI.getFirst3Regs();
10276 LLT Ty = MRI.getType(Res);
10280 auto Result =
MIRBuilder.buildShl(Ty, LHS, RHS);
10281 auto Orig = IsSigned ?
MIRBuilder.buildAShr(Ty, Result, RHS)
10290 SatVal =
MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
10295 MIRBuilder.buildSelect(Res, Ov, SatVal, Result);
10297 MI.eraseFromParent();
10302 auto [Dst, Src] =
MI.getFirst2Regs();
10303 const LLT Ty = MRI.getType(Src);
10304 unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
10305 unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;
10308 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt);
10309 auto LSByteShiftedLeft =
MIRBuilder.buildShl(Ty, Src, ShiftAmt);
10310 auto MSByteShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10311 auto Res =
MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);
10314 for (
unsigned i = 1; i < SizeInBytes / 2; ++i) {
10317 auto Mask =
MIRBuilder.buildConstant(Ty, APMask);
10318 auto ShiftAmt =
MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
10320 auto LoByte =
MIRBuilder.buildAnd(Ty, Src, Mask);
10321 auto LoShiftedLeft =
MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
10322 Res =
MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
10324 auto SrcShiftedRight =
MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
10325 auto HiShiftedRight =
MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
10326 Res =
MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
10328 Res.getInstr()->getOperand(0).setReg(Dst);
10330 MI.eraseFromParent();
10337 const LLT Ty = Dst.getLLTTy(*
B.getMRI());
10340 auto LHS =
B.buildLShr(Ty,
B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
10341 auto RHS =
B.buildAnd(Ty,
B.buildShl(Ty, Src, C_N), MaskLoNTo0);
10342 return B.buildOr(Dst,
LHS,
RHS);
10347 auto [Dst, Src] =
MI.getFirst2Regs();
10348 const LLT SrcTy = MRI.getType(Src);
10349 unsigned Size = SrcTy.getScalarSizeInBits();
10350 unsigned VSize = SrcTy.getSizeInBits();
10353 if (SrcTy.isVector() && (VSize % 8 == 0) &&
10354 (LI.isLegal({TargetOpcode::G_BITREVERSE,
10355 {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
10356 LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
10361 auto BSWAP =
MIRBuilder.buildBSwap(SrcTy, Src);
10362 auto Cast =
MIRBuilder.buildBitcast(VTy, BSWAP);
10363 auto RBIT =
MIRBuilder.buildBitReverse(VTy, Cast);
10367 MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});
10390 for (
unsigned I = 0, J =
Size - 1;
I <
Size; ++
I, --J) {
10394 Tmp2 = MIRBuilder.
buildShl(SrcTy, Src, ShAmt);
10397 Tmp2 = MIRBuilder.
buildLShr(SrcTy, Src, ShAmt);
10401 Tmp2 = MIRBuilder.
buildAnd(SrcTy, Tmp2, Mask);
10405 Tmp = MIRBuilder.
buildOr(SrcTy, Tmp, Tmp2);
10410 MI.eraseFromParent();
10418 bool IsRead =
MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
10419 int NameOpIdx = IsRead ? 1 : 0;
10420 int ValRegIndex = IsRead ? 0 : 1;
10422 Register ValReg =
MI.getOperand(ValRegIndex).getReg();
10423 const LLT Ty = MRI.getType(ValReg);
10425 cast<MDNode>(
MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));
10432 (IsRead ?
"llvm.read_register" :
"llvm.write_register"),
10433 Fn,
MI.getDebugLoc()));
10437 MI.eraseFromParent();
10446 MI.eraseFromParent();
10452 bool IsSigned =
MI.getOpcode() == TargetOpcode::G_SMULH;
10453 unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
10454 Register Result =
MI.getOperand(0).getReg();
10455 LLT OrigTy = MRI.getType(Result);
10459 auto LHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(1)});
10460 auto RHS =
MIRBuilder.buildInstr(ExtOp, {WideTy}, {
MI.getOperand(2)});
10462 unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;
10464 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, SizeInBits);
10465 auto Shifted =
MIRBuilder.buildInstr(ShiftOp, {WideTy}, {
Mul, ShiftAmt});
10468 MI.eraseFromParent();
10474 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10479 MI.eraseFromParent();
10484 MI.eraseFromParent();
10491 unsigned BitSize = SrcTy.getScalarSizeInBits();
10495 auto AsInt = SrcTy == IntTy ?
MIRBuilder.buildCopy(IntTy, SrcReg)
10502 APInt ExpMask = Inf;
10504 APInt QNaNBitMask =
10508 auto SignBitC =
MIRBuilder.buildConstant(IntTy, SignBit);
10509 auto ValueMaskC =
MIRBuilder.buildConstant(IntTy, ValueMask);
10510 auto InfC =
MIRBuilder.buildConstant(IntTy, Inf);
10511 auto ExpMaskC =
MIRBuilder.buildConstant(IntTy, ExpMask);
10512 auto ZeroC =
MIRBuilder.buildConstant(IntTy, 0);
10514 auto Abs =
MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
10518 auto Res =
MIRBuilder.buildConstant(DstTy, 0);
10520 LLT DstTyCopy = DstTy;
10522 Res =
MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
10550 auto ExpBits =
MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
10553 Mask &= ~PartialCheck;
10562 else if (PartialCheck ==
fcZero)
10574 auto OneC =
MIRBuilder.buildConstant(IntTy, 1);
10575 auto VMinusOne =
MIRBuilder.buildSub(IntTy, V, OneC);
10576 auto SubnormalRes =
10578 MIRBuilder.buildConstant(IntTy, AllOneMantissa));
10580 SubnormalRes =
MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
10581 appendToRes(SubnormalRes);
10588 else if (PartialCheck ==
fcInf)
10593 auto NegInfC =
MIRBuilder.buildConstant(IntTy, NegInf);
10600 auto InfWithQnanBitC =
MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
10601 if (PartialCheck ==
fcNan) {
10605 }
else if (PartialCheck ==
fcQNan) {
10615 Abs, InfWithQnanBitC);
10616 appendToRes(
MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
10623 APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
10625 IntTy, Abs,
MIRBuilder.buildConstant(IntTy, ExpLSB));
10626 APInt MaxExpMinusOne = ExpMask - ExpLSB;
10629 MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
10631 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
10634 DstTy, Sign,
MIRBuilder.buildConstant(DstTy, InversionMask));
10635 NormalRes =
MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
10637 appendToRes(NormalRes);
10641 MI.eraseFromParent();
10647 auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
10648 MI.getFirst4RegLLTs();
10657 Op1Reg =
MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
10658 Op1Ty = MRI.getType(Op1Reg);
10659 Op2Reg =
MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
10660 Op2Ty = MRI.getType(Op2Reg);
10664 if (MaskTy.isScalar()) {
10672 MaskElt =
MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);
10675 MaskTy = DstTy.changeElementType(
LLT::integer(DstTy.getScalarSizeInBits()));
10677 MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);
10679 if (DstTy.isVector()) {
10681 auto ShufSplat =
MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
10682 MaskReg = ShufSplat.getReg(0);
10686 }
else if (!DstTy.isVector()) {
10691 if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
10695 if (!Op1Ty.getScalarType().isAnyScalar() &&
10696 !Op1Ty.getScalarType().isInteger())
10697 Op1Reg =
MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
10699 if (!Op2Ty.getScalarType().isAnyScalar() &&
10700 !Op2Ty.getScalarType().isInteger()) {
10702 Op2Ty.changeElementType(
LLT::integer(Op2Ty.getScalarSizeInBits()));
10703 Op2Reg =
MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
10706 auto NotMask =
MIRBuilder.buildNot(MaskTy, MaskReg);
10707 auto NewOp1 =
MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
10708 auto NewOp2 =
MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
10713 if (DstTy == Op1TyInt)
10716 auto Or =
MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
10720 MI.eraseFromParent();
10726 unsigned Opcode =
MI.getOpcode();
10729 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
10730 : TargetOpcode::G_UDIV,
10731 {
MI.getOperand(0).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10733 Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
10734 : TargetOpcode::G_UREM,
10735 {
MI.getOperand(1).getReg()}, {
MI.getOperand(2),
MI.getOperand(3)});
10736 MI.eraseFromParent();
10746 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
10750 auto Shift =
MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
10753 MI.eraseFromParent();
10763 Register SrcReg =
MI.getOperand(1).getReg();
10764 LLT Ty = MRI.getType(SrcReg);
10765 auto Zero =
MIRBuilder.buildConstant(Ty, 0);
10768 MI.eraseFromParent();
10774 Register SrcReg =
MI.getOperand(1).getReg();
10775 Register DestReg =
MI.getOperand(0).getReg();
10777 auto Zero =
MIRBuilder.buildConstant(Ty, 0).getReg(0);
10778 auto Sub =
MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
10781 MI.eraseFromParent();
10787 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10788 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10789 "Expected G_ABDS or G_ABDU instruction");
10791 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10792 LLT Ty = MRI.getType(LHS);
10802 MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);
10804 MI.eraseFromParent();
10810 assert((
MI.getOpcode() == TargetOpcode::G_ABDS ||
10811 MI.getOpcode() == TargetOpcode::G_ABDU) &&
10812 "Expected G_ABDS or G_ABDU instruction");
10814 auto [DstReg, LHS, RHS] =
MI.getFirst3Regs();
10815 LLT Ty = MRI.getType(LHS);
10820 if (
MI.getOpcode() == TargetOpcode::G_ABDS) {
10821 MaxReg =
MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
10822 MinReg =
MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
10824 MaxReg =
MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
10825 MinReg =
MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
10827 MIRBuilder.buildSub(DstReg, MaxReg, MinReg);
10829 MI.eraseFromParent();
10834 auto [DstReg, DstTy, SrcReg, SrcTy] =
MI.getFirst2RegLLTs();
10839 if (!(SrcTy.getScalarType().isAnyScalar() ||
10840 SrcTy.getScalarType().isInteger())) {
10842 SrcTy.changeElementType(
LLT::integer(SrcTy.getScalarSizeInBits()));
10843 CastedSrc =
MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
10846 if (MRI.getType(DstReg) != TyInt) {
10850 .buildAnd(TyInt, CastedSrc,
10853 DstTy.getScalarSizeInBits())))
10865 MI.eraseFromParent();
10871 Register SrcReg =
MI.getOperand(1).getReg();
10872 LLT SrcTy = MRI.getType(SrcReg);
10873 LLT DstTy = MRI.getType(SrcReg);
10876 if (SrcTy.isScalar()) {
10881 MI.setDesc(
MIRBuilder.getTII().get(TargetOpcode::COPY));
10892 Register ListPtr =
MI.getOperand(1).getReg();
10893 LLT PtrTy = MRI.getType(ListPtr);
10900 auto VAList =
MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);
10902 const Align A(
MI.getOperand(2).getImm());
10904 if (
A > TLI.getMinStackArgumentAlignment()) {
10906 MIRBuilder.buildConstant(PtrTyAsScalarTy,
A.value() - 1).getReg(0);
10907 auto AddDst =
MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
10908 auto AndDst =
MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst,
Log2(
A));
10909 VAList = AndDst.getReg(0);
10916 LLT LLTTy = MRI.getType(Dst);
10919 MIRBuilder.buildConstant(PtrTyAsScalarTy,
DL.getTypeAllocSize(Ty));
10920 auto Succ =
MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);
10925 MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
10927 Align EltAlignment =
DL.getABITypeAlign(Ty);
10930 MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);
10932 MI.eraseFromParent();
10937 [[maybe_unused]]
unsigned OpCode =
MI.getOpcode();
10938 assert((OpCode == TargetOpcode::G_SMULFIX ||
10939 OpCode == TargetOpcode::G_UMULFIX) &&
10940 "Operator must be either G_SMULFIX or G_UMULFIX!");
10941 auto [Dst, LHS, RHS] =
MI.getFirst3Regs();
10942 LLT Ty = MRI.getType(Dst);
10943 unsigned Scale =
MI.getOperand(3).getImm();
10947 MI.eraseFromParent();
10953 auto ShiftAmt =
MIRBuilder.buildConstant(WideTy, Scale);
10955 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX) {
10964 if (
MI.getOpcode() == TargetOpcode::G_SMULFIX)
10971 MI.eraseFromParent();
10978 unsigned NumBits = Ty.getScalarSizeInBits();
10980 if (!Ty.isVector() && ValVRegAndVal) {
10981 APInt Scalar = ValVRegAndVal->Value.
trunc(8);
10989 if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
11010 uint64_t KnownLen,
Align Alignment,
11012 auto &MF = *
MI.getParent()->getParent();
11017 assert(KnownLen != 0 &&
"Have a zero length memset length!");
11018 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11021 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11022 const auto &DstMMO = **
MI.memoperands_begin();
11024 if (DstAlignCanChange) {
11027 Align NewAlign =
DL.getABITypeAlign(IRTy);
11028 if (NewAlign > Alignment) {
11029 Alignment = NewAlign;
11037 MachineIRBuilder MIB(
MI);
11039 LLT LargestTy = MemOps[0];
11040 for (
unsigned i = 1; i < MemOps.
size(); i++)
11042 LargestTy = MemOps[i];
11054 LLT PtrTy = MRI.getType(Dst);
11055 unsigned DstOff = 0;
11056 unsigned Size = KnownLen;
11057 for (
unsigned I = 0;
I < MemOps.
size();
I++) {
11058 LLT Ty = MemOps[
I];
11061 if (TySize >
Size) {
11065 DstOff -= TySize -
Size;
11075 TLI.isTruncateFree(LargestVT, VT))
11076 Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
11089 Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst,
Offset).getReg(0);
11092 MIB.buildStore(
Value, Ptr, *StoreMMO);
11097 MI.eraseFromParent();
11103 uint64_t KnownLen,
Align Alignment,
11105 auto &MF = *
MI.getParent()->getParent();
11109 assert(KnownLen != 0 &&
"Have a zero length memcpy length!");
11110 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11113 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11119 const auto &DstMMO = **
MI.memoperands_begin();
11120 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11122 if (DstAlignCanChange) {
11125 Align NewAlign =
DL.getABITypeAlign(IRTy);
11130 if (!
TRI->hasStackRealignment(MF))
11131 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11132 NewAlign = std::min(NewAlign, *StackAlign);
11134 if (NewAlign > Alignment) {
11135 Alignment = NewAlign;
11143 LLVM_DEBUG(
dbgs() <<
"Inlining memcpy: " <<
MI <<
" into loads & stores\n");
11145 MachineIRBuilder MIB(
MI);
11151 unsigned CurrOffset = 0;
11152 unsigned Size = KnownLen;
11153 for (
auto CopyTy : MemOps) {
11154 TypeSize TySize = CopyTy.getSizeInBytes();
11158 if (TySize >
Size) {
11159 unsigned Overlap = TySize -
Size;
11160 assert(Overlap < CurrOffset &&
11161 "overlapping memcpy load/store spans the whole region or more");
11162 CurrOffset -= Overlap;
11172 if (CurrOffset != 0) {
11173 LLT SrcTy = MRI.getType(Src);
11177 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11179 auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);
11183 if (CurrOffset != 0) {
11184 LLT DstTy = MRI.getType(Dst);
11185 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11187 MIB.buildStore(LdVal, StorePtr, *StoreMMO);
11188 CurrOffset += TySize;
11192 MI.eraseFromParent();
11198 uint64_t KnownLen,
Align Alignment,
11200 auto &MF = *
MI.getParent()->getParent();
11204 assert(KnownLen != 0 &&
"Have a zero length memmove length!");
11205 assert(!MemOps.
empty() &&
"Expected at least one memory op");
11208 MachineInstr *FIDef =
getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
11209 const auto &DstMMO = **
MI.memoperands_begin();
11210 const auto &SrcMMO = **std::next(
MI.memoperands_begin());
11212 if (DstAlignCanChange) {
11215 Align NewAlign =
DL.getABITypeAlign(IRTy);
11220 if (!
TRI->hasStackRealignment(MF))
11221 if (MaybeAlign StackAlign =
DL.getStackAlignment())
11222 NewAlign = std::min(NewAlign, *StackAlign);
11224 if (NewAlign > Alignment) {
11225 Alignment = NewAlign;
11233 LLVM_DEBUG(
dbgs() <<
"Inlining memmove: " <<
MI <<
" into loads & stores\n");
11235 MachineIRBuilder MIB(
MI);
11239 unsigned CurrOffset = 0;
11240 unsigned Size = KnownLen;
11241 SmallVector<Register, 16> LoadVals;
11242 for (
auto CopyTy : MemOps) {
11243 TypeSize TySize = CopyTy.getSizeInBytes();
11247 if (TySize >
Size) {
11248 unsigned Overlap = TySize -
Size;
11249 assert(Overlap < CurrOffset &&
11250 "overlapping memmove load spans the whole region or more");
11251 CurrOffset -= Overlap;
11259 if (CurrOffset != 0) {
11260 LLT SrcTy = MRI.getType(Src);
11263 LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src,
Offset).getReg(0);
11265 LoadVals.
push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
11266 CurrOffset += TySize;
11272 for (
unsigned I = 0;
I < MemOps.size(); ++
I) {
11273 LLT CopyTy = MemOps[
I];
11278 if (TySize >
Size) {
11279 unsigned Overlap = TySize -
Size;
11280 assert(Overlap < CurrOffset &&
11281 "overlapping memmove store spans the whole region or more");
11282 CurrOffset -= Overlap;
11289 if (CurrOffset != 0) {
11290 LLT DstTy = MRI.getType(Dst);
11293 StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst,
Offset).getReg(0);
11295 MIB.buildStore(LoadVals[
I], StorePtr, *StoreMMO);
11296 CurrOffset += TySize;
11299 MI.eraseFromParent();
11306 const unsigned Opc =
MI.getOpcode();
11307 assert((
Opc == TargetOpcode::G_MEMCPY ||
11308 Opc == TargetOpcode::G_MEMCPY_INLINE ||
11309 Opc == TargetOpcode::G_MEMMOVE ||
Opc == TargetOpcode::G_MEMSET ||
11310 Opc == TargetOpcode::G_MEMSET_INLINE) &&
11311 "Expected memcpy like instruction");
11313 if (KnownLen == 0) {
11314 MI.eraseFromParent();
11318 if (
Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE) {
11319 return lowerMemcpy(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11322 if (
Opc == TargetOpcode::G_MEMMOVE)
11323 return lowerMemmove(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11325 if (
Opc == TargetOpcode::G_MEMSET ||
Opc == TargetOpcode::G_MEMSET_INLINE)
11326 return lowerMemset(
MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
11336 bool DstAlignCanChange;
11337 std::vector<LLT> MemOps;
11339 DstAlignCanChange, MemOps))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file describes how to lower LLVM calls to machine code calls.
#define GISEL_VECREDUCE_CASES_NONSEQ
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)
#define RTLIBCASE_INT(LibcallPrefix)
static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI)
static Register buildBitFieldInsert(MachineIRBuilder &B, Register TargetReg, Register InsertReg, Register OffsetBits)
Emit code to insert InsertReg into TargetRet at OffsetBits in TargetReg, while preserving other bits ...
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB)
static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size)
static std::pair< RTLIB::Libcall, CmpInst::Predicate > getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size)
Returns the corresponding libcall for the given Pred and the ICMP predicate that should be generated ...
static void broadcastSrcOp(SmallVectorImpl< SrcOp > &Ops, unsigned N, MachineOperand &Op)
Operand Op is used on N sub-instructions.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result, MachineInstr &MI, const TargetInstrInfo &TII, MachineRegisterInfo &MRI)
True if an instruction is in tail position in its caller.
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B, Register Idx, unsigned NewEltSize, unsigned OldEltSize)
Figure out the bit offset into a register when coercing a vector index for the wide element type.
static void makeDstOps(SmallVectorImpl< DstOp > &DstOps, LLT Ty, unsigned NumElts)
Fill DstOps with DstOps that have same number of elements combined as the Ty.
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, MachineInstrBuilder Src, const APInt &Mask)
static bool hasSwiftErrorArg(MachineFunction &MF)
static LegalizerHelper::LegalizeResult loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src, LLT SrcTy, MachineIRBuilder &MIRBuilder)
i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16.
static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal, MachineIRBuilder &MIRBuilder)
static void getUnmergePieces(SmallVectorImpl< Register > &Pieces, MachineIRBuilder &B, Register Src, LLT Ty)
static CmpInst::Predicate minMaxToCompare(unsigned Opc)
static RTLIB::Libcall getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI)
static std::pair< int, int > getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy)
Try to break down OrigTy into NarrowTy sized pieces.
static bool hasSameNumEltsOnAllVectorOperands(GenericMachineInstr &MI, MachineRegisterInfo &MRI, std::initializer_list< unsigned > NonVecOpIndices)
Check that all vector operands have same number of elements.
static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg, LLT VecTy)
static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType, Type *FromType)
static void getUnmergeResults(SmallVectorImpl< Register > &Regs, const MachineInstr &MI)
Append the result registers of G_UNMERGE_VALUES MI to Regs.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI, Register Reg, unsigned BW)
#define RTLIBCASE(LibcallPrefix)
static Type * getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Tracks DebugLocs between checkpoints and verifies that they are transferred.
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
static const fltSemantics & IEEEsingle()
static constexpr roundingMode rmTowardZero
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
opStatus
IEEE-754R 7: Default exception handling.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APFloat getNaN(const fltSemantics &Sem, bool Negative=false, uint64_t payload=0)
Factory for NaN values.
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getMinValue(unsigned numBits)
Gets minimum unsigned value of APInt for a specific bit width.
void negate()
Negate this APInt in place.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
static APInt getBitsSetWithWrap(unsigned numBits, unsigned loBit, unsigned hiBit)
Wrap version of getBitsSet.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
LLT getLLTTy(const MachineRegisterInfo &MRI) const
static constexpr ElementCount getFixed(ScalarTy MinVal)
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
AttributeList getAttributes() const
Return the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Represents any generic load, including sign/zero extending variants.
Register getDstReg() const
Get the definition register of the loaded value.
Register getValueReg() const
Get the stored value register.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
Represents a insert subvector.
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
MachineMemOperand & getMMO() const
Get the MachineMemOperand on this instruction.
LocationSize getMemSize() const
Returns the size in bytes of the memory access.
bool isAtomic() const
Returns true if the attached MachineMemOperand has the atomic flag set.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
Represents a threeway compare.
A base class for all GenericMachineInstrs.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
Predicate getUnsignedPredicate() const
For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
static constexpr LLT float64()
Get a 64-bit IEEE double value.
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
static constexpr LLT float16()
Get a 16-bit IEEE half value.
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
static LLT integer(unsigned SizeInBits)
static constexpr LLT bfloat16()
constexpr LLT changeVectorElementType(LLT NewEltTy) const
Returns a vector with the same number of elements but the new element type.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
LLT changeVectorElementCount(ElementCount EC) const
Return a vector with the same element type and the new element count.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
static LLT floatIEEE(unsigned SizeInBits)
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
LLVM_ABI LegalizeResult lowerShlSat(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerThreewayCompare(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_F16(MachineInstr &MI)
LLVM_ABI LegalizeResult equalizeVectorShuffleLengths(MachineInstr &MI)
Equalize source and destination vector sizes of G_SHUFFLE_VECTOR.
LLVM_ABI LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_INSERT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerDynStackAlloc(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBitCount(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty)
LLVM_ABI LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF64BitFloatOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSSUBE(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerIntrinsicRound(MachineInstr &MI)
LLVM_ABI void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, unsigned ExtOpcode)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI LegalizeResult moreElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerSMULH_UMULH(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerLoad(GAnyLoad &MI)
LLVM_ABI LegalizeResult fewerElementsVectorShuffle(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerAbsToAddXor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT_BF16(MachineInstr &MI)
LLVM_ABI void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Def by performing it with addition...
LLVM_ABI LegalizerHelper::LegalizeResult createAtomicLibcall(MachineInstr &MI) const
LLVM_ABI LegalizeResult lowerFConstant(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerBitreverse(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerExtractInsertVectorElt(MachineInstr &MI)
Lower a vector extract or insert by writing the vector to a stack temporary and reloading the element...
LLVM_ABI LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
Legalize a vector instruction by increasing the number of vector elements involved and ignoring the a...
LLVM_ABI LegalizeResult lowerFunnelShiftWithInverse(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTOINT_SAT(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarCTLS(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerStore(GStore &MI)
LLVM_ABI LegalizeResult lowerAbsToCNeg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPEXT(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
LLVM_ABI LegalizeResult narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy)
Multi-way shift legalization: directly split wide shifts into target-sized parts in a single step,...
LLVM_ABI Register lowerRoundInexactToOdd(LLT ResultTy, Register Op)
LLVM_ABI LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen, Align Alignment, bool DstAlignCanChange, ArrayRef< LLT > MemOps)
LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI Register buildConstantShiftPart(unsigned Opcode, unsigned PartIdx, unsigned NumParts, ArrayRef< Register > SrcParts, const ShiftParams &Params, LLT TargetTy, LLT ShiftAmtTy)
Generates a single output part for constant shifts using direct indexing.
LLVM_ABI void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by truncating the operand's ty...
LLVM_ABI LegalizeResult fewerElementsVectorPhi(GenericMachineInstr &MI, unsigned NumElts)
LLVM_ABI LegalizeResult lowerFPTOUI(MachineInstr &MI)
const TargetLowering & getTargetLowering() const
LLVM_ABI LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
LLVM_ABI LegalizeResult narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer, MachineIRBuilder &B, const LibcallLoweringInfo *Libcalls=nullptr)
LLVM_ABI LegalizeResult lowerUnmergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcast(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by replacing the value type.
LLVM_ABI LegalizeResult scalarizeVectorBooleanStore(GStore &MI)
Given a store of a boolean vector, scalarize it.
LLVM_ABI LegalizeResult lowerBitcast(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFunnelShiftAsShifts(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerInsert(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerReadWriteRegister(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerExtract(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsBitcast(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, LLT HalfTy, LLT ShiftAmtTy)
LLVM_ABI LegalizeResult lowerISFPCLASS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAddSubSatToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPOWI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPExtAndTruncMem(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFAbs(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerVectorReduction(MachineInstr &MI)
const LegalizerInfo & getLegalizerInfo() const
Expose LegalizerInfo so the clients can re-use.
LLVM_ABI LegalizeResult reduceLoadStoreWidth(GLoadStore &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult fewerElementsVectorMultiEltType(GenericMachineInstr &MI, unsigned NumElts, std::initializer_list< unsigned > NonVecOpIndices={})
Handles most opcodes.
LLVM_ABI LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarShiftByConstantMultiway(MachineInstr &MI, const APInt &Amt, LLT TargetTy, LLT ShiftAmtTy)
Optimized path for constant shift amounts using static indexing.
LLVM_ABI void widenScalarSrcUsingFPExt(MachineInstr &MI, LLT WideTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by extending the operand's typ...
LLVM_ABI MachineInstrBuilder createStackStoreLoad(const DstOp &Res, const SrcOp &Val)
Create a store of Val to a stack temporary and return a load as the same type as Res.
LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMODF(MachineInstr &MI)
@ Legalized
Instruction has been legalized and the MachineFunction changed.
@ AlreadyLegal
Instruction was already legal and no change was made to the MachineFunction.
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, LLT MoreTy)
LLVM_ABI LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFCopySign(MachineInstr &MI)
LLVM_ABI LegalizeResult bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSADDE(MachineInstr &MI)
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F32_TO_BF16(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize a vector instruction by splitting into multiple components, each acting on the same scalar t...
GISelChangeObserver & Observer
To keep track of changes made by the LegalizerHelper.
LLVM_ABI LegalizeResult conversionLibcall(MachineInstr &MI, Type *ToType, Type *FromType, LostDebugLocObserver &LocObserver, bool IsSigned=false) const
LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a def by inserting a G_BITCAST from ...
LLVM_ABI LegalizeResult lowerFPTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFMad(MachineInstr &MI)
LLVM_ABI LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy)
Legalize an instruction by performing the operation on a wider scalar type (for example a 16-bit addi...
LLVM_ABI LegalizeResult lowerAddSubSatToAddoSubo(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult lowerFFloor(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerFPTRUNC_F64_TO_BF16(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerAbsDiffToMinMax(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarExt(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult fewerElementsVectorSeqReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Register getDynStackAllocTargetPtr(Register SPReg, Register AllocSize, Align Alignment, LLT PtrTy)
LLVM_ABI LegalizeResult lowerFPTOSI(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerUITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerShuffleVector(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerMergeValues(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver) const
Create a libcall to memcpy et al.
LLVM_ABI LegalizeResult lowerVECTOR_COMPRESS(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerMulfix(MachineInstr &MI)
LLVM_ABI void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a Use by producing a vector with und...
LLVM_ABI LegalizeResult bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
Perform Bitcast legalize action on G_EXTRACT_VECTOR_ELT.
LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerU64ToF32WithSITOFP(MachineInstr &MI)
LLVM_ABI LegalizeResult createLibcall(const char *Name, const CallLowering::ArgInfo &Result, ArrayRef< CallLowering::ArgInfo > Args, CallingConv::ID CC, LostDebugLocObserver &LocObserver, MachineInstr *MI=nullptr) const
Helper function that creates a libcall to the given Name using the given calling convention CC.
LLVM_ABI LegalizeResult bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx, LLT CastTy)
LLVM_ABI LegalizeResult lowerDIVREM(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerSelect(MachineInstr &MI)
LLVM_ABI LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI LegalizeResult narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI Register buildVariableShiftPart(unsigned Opcode, Register MainOperand, Register ShiftAmt, LLT TargetTy, Register CarryOperand=Register())
Generates a shift part with carry for variable shifts.
LLVM_ABI void bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx)
Legalize a single operand OpIdx of the machine instruction MI as a use by inserting a G_BITCAST to Ca...
LLVM_ABI void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, unsigned ExtOpcode)
LLVM_ABI LegalizeResult libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Legalize an instruction by emiting a runtime library call instead.
LLVM_ABI LegalizeResult lowerStackRestore(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorReductions(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult lowerStackSave(MachineInstr &MI)
LLVM_ABI LegalizeResult fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI LegalizeResult narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
LLVM_ABI void widenScalarDstUsingFPTrunc(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI)
LLVM_ABI LegalizeResult lowerBswap(MachineInstr &MI)
LLVM_ABI Register getVectorElementPointer(Register VecPtr, LLT VecTy, Register Index)
Get a pointer to vector element Index located in memory for a vector of type VecTy starting at a base...
LLVM_ABI LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const
Return the alignment to use for a stack temporary object with the given type.
LLVM_ABI LegalizeResult lowerConstant(MachineInstr &MI)
LLVM_ABI Register coerceToInteger(Register Val)
Cast the given value to an LLT::integer with an equivalent size.
LLVM_ABI void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx=0, unsigned TruncOpcode=TargetOpcode::G_TRUNC)
Legalize a single operand OpIdx of the machine instruction MI as a Def by extending the operand's typ...
LLVM_ABI LegalizeResult simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, LostDebugLocObserver &LocObserver) const
LLVM_ABI LegalizeResult legalizeInstrStep(MachineInstr &MI, LostDebugLocObserver &LocObserver)
Replace MI by a sequence of legal instructions that can implement the same operation.
LLVM_ABI LegalizeResult lowerFMinimumMaximum(MachineInstr &MI)
Tracks which library functions to use for a particular subtarget.
TypeSize getValue() const
void checkpoint(bool CheckDebugLocs=true)
Call this to indicate that it's a good point to assess whether locations have been lost.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
LLVM_ABI StringRef getString() const
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
LLVM_ABI iterator getFirstTerminatorForward()
Finds the first terminator in a block by scanning forward.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
void setObjectAlignment(int ObjectIdx, Align Alignment)
setObjectAlignment - Change the alignment of the specified stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Helper class to build MachineInstr.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildMul(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_MUL Op0, Op1.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildURem(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_UREM Op0, Op1.
MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildSub(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_SUB Op0, Op1.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src)
Build and insert a G_INTTOPTR instruction.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildNeg(const DstOp &Dst, const SrcOp &Src0)
Build and insert integer negation Zero = G_CONSTANT 0 Res = G_SUB Zero, Op0.
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_UITOFP Src0.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)
Build and insert Res = G_SITOFP Src0.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src)
Build and insert Dst = G_BITCAST Src.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_OR Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
void setType(LLT NewTy)
Reset the tracked memory type.
LLT getMemoryType() const
Return the memory type of the memory reference.
void clearRanges()
Unset the tracked range metadata.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
const MachinePointerInfo & getPointerInfo() const
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)
const ConstantInt * getCImm() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
void setCImm(const ConstantInt *CI)
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
Represent a constant reference to a string, i.e.
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
TargetInstrInfo - Interface to description of machine instruction set.
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getFP128Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
static LLVM_ABI Type * getX86_FP80Ty(LLVMContext &C)
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Type * getType() const
All values are typed, get the type of this value.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
ConstantMatch< APInt > m_ICst(APInt &Cst)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(Register Def, const MachineRegisterInfo &MRI)
Determines if Def defines a constant integer or a splat vector of constant integers.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI Type * getTypeForLLT(LLT Ty, LLVMContext &C)
Get the type back from LLT.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
constexpr int64_t minIntN(int64_t N)
Gets the minimum value for a N-bit signed integer.
LLVM_ABI MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg, std::function< bool(const Constant *ConstVal)> Match, bool AllowUndefs=false)
Attempt to match a unary predicate against a scalar/splat constant or every element of a constant G_B...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
LLVM_ABI LLVM_READNONE LLT getLCMType(LLT OrigTy, LLT TargetTy)
Return the least common multiple type of OrigTy and TargetTy, by changing the number of vector elemen...
unsigned M1(unsigned Val)
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
auto dyn_cast_or_null(const Y &Val)
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Success
The lock was released successfully.
LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx)
LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...
LLVM_ABI bool canLowerMemCpyFamily(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned MaxLen, Register &Dst, Register &Src, uint64_t &KnownLen, Align &Alignment, bool &DstAlignCanChange, std::vector< LLT > &MemOps)
Matcher for memcpy-like instructions.
To bit_cast(const From &from) noexcept
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int64_t maxIntN(int64_t N)
Gets the maximum value for a N-bit signed integer.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI LLVM_READNONE LLT getGCDType(LLT OrigTy, LLT TargetTy)
Return a type where the total size is the greatest common divisor of OrigTy and TargetTy.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
@ Custom
The result value requires a custom uniformity check.
LLVM_ABI void extractVectorParts(Register Reg, unsigned NumElts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
Version which handles irregular sub-vector splits.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
SmallVector< ISD::ArgFlagsTy, 4 > Flags
CallingConv::ID CallConv
Calling convention to be used for the call.
bool isKnownNeverZero() const
Return true if it's known this can never be a zero.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.